rtnetlink: place link af dump into own helper
authorFlorian Westphal <fw@strlen.de>
Mon, 16 Oct 2017 13:44:35 +0000 (15:44 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 16 Oct 2017 20:26:40 +0000 (21:26 +0100)
next patch will rcu-ify rtnl af_ops, i.e. allow af_ops
lookup and function calls with rcu read lock held instead
of rtnl mutex.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/core/rtnetlink.c

index 6a09f3d575afcffd7c7b16a3f3551ca158d5d90d..a49cad25e577103082c1538d10dc16b9526e9926 100644 (file)
@@ -1382,6 +1382,47 @@ static int rtnl_fill_link_netnsid(struct sk_buff *skb,
        return 0;
 }
 
+static int rtnl_fill_link_af(struct sk_buff *skb,
+                            const struct net_device *dev,
+                            u32 ext_filter_mask)
+{
+       const struct rtnl_af_ops *af_ops;
+       struct nlattr *af_spec;
+
+       af_spec = nla_nest_start(skb, IFLA_AF_SPEC);
+       if (!af_spec)
+               return -EMSGSIZE;
+
+       list_for_each_entry(af_ops, &rtnl_af_ops, list) {
+               struct nlattr *af;
+               int err;
+
+               if (!af_ops->fill_link_af)
+                       continue;
+
+               af = nla_nest_start(skb, af_ops->family);
+               if (!af)
+                       return -EMSGSIZE;
+
+               err = af_ops->fill_link_af(skb, dev, ext_filter_mask);
+               /*
+                * Caller may return ENODATA to indicate that there
+                * was no data to be dumped. This is not an error, it
+                * means we should trim the attribute header and
+                * continue.
+                */
+               if (err == -ENODATA)
+                       nla_nest_cancel(skb, af);
+               else if (err < 0)
+                       return -EMSGSIZE;
+
+               nla_nest_end(skb, af);
+       }
+
+       nla_nest_end(skb, af_spec);
+       return 0;
+}
+
 static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
                            int type, u32 pid, u32 seq, u32 change,
                            unsigned int flags, u32 ext_filter_mask,
@@ -1389,8 +1430,6 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
 {
        struct ifinfomsg *ifm;
        struct nlmsghdr *nlh;
-       struct nlattr *af_spec;
-       struct rtnl_af_ops *af_ops;
 
        ASSERT_RTNL();
        nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags);
@@ -1477,36 +1516,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
            nla_put_s32(skb, IFLA_NEW_NETNSID, *new_nsid) < 0)
                goto nla_put_failure;
 
-       if (!(af_spec = nla_nest_start(skb, IFLA_AF_SPEC)))
+       if (rtnl_fill_link_af(skb, dev, ext_filter_mask))
                goto nla_put_failure;
 
-       list_for_each_entry(af_ops, &rtnl_af_ops, list) {
-               if (af_ops->fill_link_af) {
-                       struct nlattr *af;
-                       int err;
-
-                       if (!(af = nla_nest_start(skb, af_ops->family)))
-                               goto nla_put_failure;
-
-                       err = af_ops->fill_link_af(skb, dev, ext_filter_mask);
-
-                       /*
-                        * Caller may return ENODATA to indicate that there
-                        * was no data to be dumped. This is not an error, it
-                        * means we should trim the attribute header and
-                        * continue.
-                        */
-                       if (err == -ENODATA)
-                               nla_nest_cancel(skb, af);
-                       else if (err < 0)
-                               goto nla_put_failure;
-
-                       nla_nest_end(skb, af);
-               }
-       }
-
-       nla_nest_end(skb, af_spec);
-
        nlmsg_end(skb, nlh);
        return 0;