]> err.no Git - linux-2.6/blobdiff - net/ipv4/fib_semantics.c
Merge refs/heads/ieee80211-wifi from master.kernel.org:/pub/scm/linux/kernel/git...
[linux-2.6] / net / ipv4 / fib_semantics.c
index 029362d66135124a3327046440b6c94892c4d1ae..d41219e8037c7a9f8a9c69dc1bd720f36d357d0b 100644 (file)
@@ -276,7 +276,7 @@ void rtmsg_fib(int event, u32 key, struct fib_alias *fa,
               struct nlmsghdr *n, struct netlink_skb_parms *req)
 {
        struct sk_buff *skb;
-       u32 pid = req ? req->pid : 0;
+       u32 pid = req ? req->pid : n->nlmsg_pid;
        int size = NLMSG_SPACE(sizeof(struct rtmsg)+256);
 
        skb = alloc_skb(size, GFP_KERNEL);
@@ -286,14 +286,14 @@ void rtmsg_fib(int event, u32 key, struct fib_alias *fa,
        if (fib_dump_info(skb, pid, n->nlmsg_seq, event, tb_id,
                          fa->fa_type, fa->fa_scope, &key, z,
                          fa->fa_tos,
-                         fa->fa_info) < 0) {
+                         fa->fa_info, 0) < 0) {
                kfree_skb(skb);
                return;
        }
-       NETLINK_CB(skb).dst_groups = RTMGRP_IPV4_ROUTE;
+       NETLINK_CB(skb).dst_group = RTNLGRP_IPV4_ROUTE;
        if (n->nlmsg_flags&NLM_F_ECHO)
                atomic_inc(&skb->users);
-       netlink_broadcast(rtnl, skb, pid, RTMGRP_IPV4_ROUTE, GFP_KERNEL);
+       netlink_broadcast(rtnl, skb, pid, RTNLGRP_IPV4_ROUTE, GFP_KERNEL);
        if (n->nlmsg_flags&NLM_F_ECHO)
                netlink_unicast(rtnl, skb, pid, MSG_DONTWAIT);
 }
@@ -593,10 +593,13 @@ static void fib_hash_move(struct hlist_head *new_info_hash,
                          struct hlist_head *new_laddrhash,
                          unsigned int new_size)
 {
+       struct hlist_head *old_info_hash, *old_laddrhash;
        unsigned int old_size = fib_hash_size;
-       unsigned int i;
+       unsigned int i, bytes;
 
        write_lock(&fib_info_lock);
+       old_info_hash = fib_info_hash;
+       old_laddrhash = fib_info_laddrhash;
        fib_hash_size = new_size;
 
        for (i = 0; i < old_size; i++) {
@@ -636,6 +639,10 @@ static void fib_hash_move(struct hlist_head *new_info_hash,
        fib_info_laddrhash = new_laddrhash;
 
        write_unlock(&fib_info_lock);
+
+       bytes = old_size * sizeof(struct hlist_head *);
+       fib_hash_free(old_info_hash, bytes);
+       fib_hash_free(old_laddrhash, bytes);
 }
 
 struct fib_info *
@@ -847,6 +854,7 @@ failure:
        return NULL;
 }
 
+/* Note! fib_semantic_match intentionally uses  RCU list functions. */
 int fib_semantic_match(struct list_head *head, const struct flowi *flp,
                       struct fib_result *res, __u32 zone, __u32 mask, 
                        int prefixlen)
@@ -854,7 +862,7 @@ int fib_semantic_match(struct list_head *head, const struct flowi *flp,
        struct fib_alias *fa;
        int nh_sel = 0;
 
-       list_for_each_entry(fa, head, fa_list) {
+       list_for_each_entry_rcu(fa, head, fa_list) {
                int err;
 
                if (fa->fa_tos &&
@@ -932,13 +940,13 @@ u32 __fib_res_prefsrc(struct fib_result *res)
 int
 fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
              u8 tb_id, u8 type, u8 scope, void *dst, int dst_len, u8 tos,
-             struct fib_info *fi)
+             struct fib_info *fi, unsigned int flags)
 {
        struct rtmsg *rtm;
        struct nlmsghdr  *nlh;
        unsigned char    *b = skb->tail;
 
-       nlh = NLMSG_PUT(skb, pid, seq, event, sizeof(*rtm));
+       nlh = NLMSG_NEW(skb, pid, seq, event, sizeof(*rtm), flags);
        rtm = NLMSG_DATA(nlh);
        rtm->rtm_family = AF_INET;
        rtm->rtm_dst_len = dst_len;
@@ -1035,7 +1043,7 @@ fib_convert_rtentry(int cmd, struct nlmsghdr *nl, struct rtmsg *rtm,
        }
 
        nl->nlmsg_flags = NLM_F_REQUEST;
-       nl->nlmsg_pid = 0;
+       nl->nlmsg_pid = current->pid;
        nl->nlmsg_seq = 0;
        nl->nlmsg_len = NLMSG_LENGTH(sizeof(*rtm));
        if (cmd == SIOCDELRT) {