net: Kill hold_net release_net
[linux-2.6-block.git] / net / core / neighbour.c
index 8d614c93f86a233a5cb3864c600d9c68fe5f9ea1..0e8b32efc0316c85e56c4b7a95c4c903fde63ecf 100644 (file)
@@ -397,25 +397,15 @@ struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey,
                               struct net_device *dev)
 {
        struct neighbour *n;
-       int key_len = tbl->key_len;
-       u32 hash_val;
-       struct neigh_hash_table *nht;
 
        NEIGH_CACHE_STAT_INC(tbl, lookups);
 
        rcu_read_lock_bh();
-       nht = rcu_dereference_bh(tbl->nht);
-       hash_val = tbl->hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
-
-       for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
-            n != NULL;
-            n = rcu_dereference_bh(n->next)) {
-               if (dev == n->dev && !memcmp(n->primary_key, pkey, key_len)) {
-                       if (!atomic_inc_not_zero(&n->refcnt))
-                               n = NULL;
-                       NEIGH_CACHE_STAT_INC(tbl, hits);
-                       break;
-               }
+       n = __neigh_lookup_noref(tbl, pkey, dev);
+       if (n) {
+               if (!atomic_inc_not_zero(&n->refcnt))
+                       n = NULL;
+               NEIGH_CACHE_STAT_INC(tbl, hits);
        }
 
        rcu_read_unlock_bh();
@@ -601,7 +591,7 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
        if (!n)
                goto out;
 
-       write_pnet(&n->net, hold_net(net));
+       write_pnet(&n->net, net);
        memcpy(n->key, pkey, key_len);
        n->dev = dev;
        if (dev)
@@ -610,7 +600,6 @@ struct pneigh_entry * pneigh_lookup(struct neigh_table *tbl,
        if (tbl->pconstructor && tbl->pconstructor(n)) {
                if (dev)
                        dev_put(dev);
-               release_net(net);
                kfree(n);
                n = NULL;
                goto out;
@@ -644,7 +633,6 @@ int pneigh_delete(struct neigh_table *tbl, struct net *net, const void *pkey,
                                tbl->pdestructor(n);
                        if (n->dev)
                                dev_put(n->dev);
-                       release_net(pneigh_net(n));
                        kfree(n);
                        return 0;
                }
@@ -667,7 +655,6 @@ static int pneigh_ifdown(struct neigh_table *tbl, struct net_device *dev)
                                        tbl->pdestructor(n);
                                if (n->dev)
                                        dev_put(n->dev);
-                               release_net(pneigh_net(n));
                                kfree(n);
                                continue;
                        }
@@ -1263,10 +1250,10 @@ struct neighbour *neigh_event_ns(struct neigh_table *tbl,
 EXPORT_SYMBOL(neigh_event_ns);
 
 /* called with read_lock_bh(&n->lock); */
-static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst)
+static void neigh_hh_init(struct neighbour *n)
 {
-       struct net_device *dev = dst->dev;
-       __be16 prot = dst->ops->protocol;
+       struct net_device *dev = n->dev;
+       __be16 prot = n->tbl->protocol;
        struct hh_cache *hh = &n->hh;
 
        write_lock_bh(&n->lock);
@@ -1280,43 +1267,19 @@ static void neigh_hh_init(struct neighbour *n, struct dst_entry *dst)
        write_unlock_bh(&n->lock);
 }
 
-/* This function can be used in contexts, where only old dev_queue_xmit
- * worked, f.e. if you want to override normal output path (eql, shaper),
- * but resolution is not made yet.
- */
-
-int neigh_compat_output(struct neighbour *neigh, struct sk_buff *skb)
-{
-       struct net_device *dev = skb->dev;
-
-       __skb_pull(skb, skb_network_offset(skb));
-
-       if (dev_hard_header(skb, dev, ntohs(skb->protocol), NULL, NULL,
-                           skb->len) < 0 &&
-           dev_rebuild_header(skb))
-               return 0;
-
-       return dev_queue_xmit(skb);
-}
-EXPORT_SYMBOL(neigh_compat_output);
-
 /* Slow and careful. */
 
 int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
 {
-       struct dst_entry *dst = skb_dst(skb);
        int rc = 0;
 
-       if (!dst)
-               goto discard;
-
        if (!neigh_event_send(neigh, skb)) {
                int err;
                struct net_device *dev = neigh->dev;
                unsigned int seq;
 
                if (dev->header_ops->cache && !neigh->hh.hh_len)
-                       neigh_hh_init(neigh, dst);
+                       neigh_hh_init(neigh);
 
                do {
                        __skb_pull(skb, skb_network_offset(skb));
@@ -1332,8 +1295,6 @@ int neigh_resolve_output(struct neighbour *neigh, struct sk_buff *skb)
        }
 out:
        return rc;
-discard:
-       neigh_dbg(1, "%s: dst=%p neigh=%p\n", __func__, dst, neigh);
 out_kfree_skb:
        rc = -EINVAL;
        kfree_skb(skb);
@@ -1464,11 +1425,10 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
                                neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
                dev_hold(dev);
                p->dev = dev;
-               write_pnet(&p->net, hold_net(net));
+               write_pnet(&p->net, net);
                p->sysctl_table = NULL;
 
                if (ops->ndo_neigh_setup && ops->ndo_neigh_setup(dev, p)) {
-                       release_net(net);
                        dev_put(dev);
                        kfree(p);
                        return NULL;
@@ -1508,7 +1468,6 @@ EXPORT_SYMBOL(neigh_parms_release);
 
 static void neigh_parms_destroy(struct neigh_parms *parms)
 {
-       release_net(neigh_parms_net(parms));
        kfree(parms);
 }
 
@@ -1884,7 +1843,8 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
                goto nla_put_failure;
 
        read_unlock_bh(&tbl->lock);
-       return nlmsg_end(skb, nlh);
+       nlmsg_end(skb, nlh);
+       return 0;
 
 nla_put_failure:
        read_unlock_bh(&tbl->lock);
@@ -1917,7 +1877,8 @@ static int neightbl_fill_param_info(struct sk_buff *skb,
                goto errout;
 
        read_unlock_bh(&tbl->lock);
-       return nlmsg_end(skb, nlh);
+       nlmsg_end(skb, nlh);
+       return 0;
 errout:
        read_unlock_bh(&tbl->lock);
        nlmsg_cancel(skb, nlh);
@@ -2126,7 +2087,7 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
 
                if (neightbl_fill_info(skb, tbl, NETLINK_CB(cb->skb).portid,
                                       cb->nlh->nlmsg_seq, RTM_NEWNEIGHTBL,
-                                      NLM_F_MULTI) <= 0)
+                                      NLM_F_MULTI) < 0)
                        break;
 
                nidx = 0;
@@ -2142,7 +2103,7 @@ static int neightbl_dump_info(struct sk_buff *skb, struct netlink_callback *cb)
                                                     NETLINK_CB(cb->skb).portid,
                                                     cb->nlh->nlmsg_seq,
                                                     RTM_NEWNEIGHTBL,
-                                                    NLM_F_MULTI) <= 0)
+                                                    NLM_F_MULTI) < 0)
                                goto out;
                next:
                        nidx++;
@@ -2202,7 +2163,8 @@ static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
            nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci))
                goto nla_put_failure;
 
-       return nlmsg_end(skb, nlh);
+       nlmsg_end(skb, nlh);
+       return 0;
 
 nla_put_failure:
        nlmsg_cancel(skb, nlh);
@@ -2232,7 +2194,8 @@ static int pneigh_fill_info(struct sk_buff *skb, struct pneigh_entry *pn,
        if (nla_put(skb, NDA_DST, tbl->key_len, pn->key))
                goto nla_put_failure;
 
-       return nlmsg_end(skb, nlh);
+       nlmsg_end(skb, nlh);
+       return 0;
 
 nla_put_failure:
        nlmsg_cancel(skb, nlh);
@@ -2270,7 +2233,7 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
                        if (neigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
                                            cb->nlh->nlmsg_seq,
                                            RTM_NEWNEIGH,
-                                           NLM_F_MULTI) <= 0) {
+                                           NLM_F_MULTI) < 0) {
                                rc = -1;
                                goto out;
                        }
@@ -2307,7 +2270,7 @@ static int pneigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb,
                        if (pneigh_fill_info(skb, n, NETLINK_CB(cb->skb).portid,
                                            cb->nlh->nlmsg_seq,
                                            RTM_NEWNEIGH,
-                                           NLM_F_MULTI, tbl) <= 0) {
+                                           NLM_F_MULTI, tbl) < 0) {
                                read_unlock_bh(&tbl->lock);
                                rc = -1;
                                goto out;
@@ -2423,6 +2386,40 @@ void __neigh_for_each_release(struct neigh_table *tbl,
 }
 EXPORT_SYMBOL(__neigh_for_each_release);
 
+int neigh_xmit(int index, struct net_device *dev,
+              const void *addr, struct sk_buff *skb)
+{
+       int err = -EAFNOSUPPORT;
+       if (likely(index < NEIGH_NR_TABLES)) {
+               struct neigh_table *tbl;
+               struct neighbour *neigh;
+
+               tbl = neigh_tables[index];
+               if (!tbl)
+                       goto out;
+               neigh = __neigh_lookup_noref(tbl, addr, dev);
+               if (!neigh)
+                       neigh = __neigh_create(tbl, addr, dev, false);
+               err = PTR_ERR(neigh);
+               if (IS_ERR(neigh))
+                       goto out_kfree_skb;
+               err = neigh->output(neigh, skb);
+       }
+       else if (index == NEIGH_LINK_TABLE) {
+               err = dev_hard_header(skb, dev, ntohs(skb->protocol),
+                                     addr, NULL, skb->len);
+               if (err < 0)
+                       goto out_kfree_skb;
+               err = dev_queue_xmit(skb);
+       }
+out:
+       return err;
+out_kfree_skb:
+       kfree_skb(skb);
+       goto out;
+}
+EXPORT_SYMBOL(neigh_xmit);
+
 #ifdef CONFIG_PROC_FS
 
 static struct neighbour *neigh_get_first(struct seq_file *seq)