Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

rtnetlink: rtnl_setlink() and rtnl_getlink() changes

rtnl_getlink() & rtnl_setlink() run with RTNL held, we can use
__dev_get_by_index() and __dev_get_by_name() variants and avoid
dev_hold()/dev_put()

Adds to rtnl_getlink() the capability to find a device by its name,
not only by its index.

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Eric Dumazet and committed by
David S. Miller
a3d12891 a61f8026

+19 -19
+19 -19
net/core/rtnetlink.c
··· 910 910 err = -EINVAL; 911 911 ifm = nlmsg_data(nlh); 912 912 if (ifm->ifi_index > 0) 913 - dev = dev_get_by_index(net, ifm->ifi_index); 913 + dev = __dev_get_by_index(net, ifm->ifi_index); 914 914 else if (tb[IFLA_IFNAME]) 915 - dev = dev_get_by_name(net, ifname); 915 + dev = __dev_get_by_name(net, ifname); 916 916 else 917 917 goto errout; 918 918 ··· 922 922 } 923 923 924 924 if ((err = validate_linkmsg(dev, tb)) < 0) 925 - goto errout_dev; 925 + goto errout; 926 926 927 927 err = do_setlink(dev, ifm, tb, ifname, 0); 928 - errout_dev: 929 - dev_put(dev); 930 928 errout: 931 929 return err; 932 930 } ··· 1152 1154 { 1153 1155 struct net *net = sock_net(skb->sk); 1154 1156 struct ifinfomsg *ifm; 1157 + char ifname[IFNAMSIZ]; 1155 1158 struct nlattr *tb[IFLA_MAX+1]; 1156 1159 struct net_device *dev = NULL; 1157 1160 struct sk_buff *nskb; ··· 1162 1163 if (err < 0) 1163 1164 return err; 1164 1165 1166 + if (tb[IFLA_IFNAME]) 1167 + nla_strlcpy(ifname, tb[IFLA_IFNAME], IFNAMSIZ); 1168 + 1165 1169 ifm = nlmsg_data(nlh); 1166 - if (ifm->ifi_index > 0) { 1167 - dev = dev_get_by_index(net, ifm->ifi_index); 1168 - if (dev == NULL) 1169 - return -ENODEV; 1170 - } else 1170 + if (ifm->ifi_index > 0) 1171 + dev = __dev_get_by_index(net, ifm->ifi_index); 1172 + else if (tb[IFLA_IFNAME]) 1173 + dev = __dev_get_by_name(net, ifname); 1174 + else 1171 1175 return -EINVAL; 1172 1176 1177 + if (dev == NULL) 1178 + return -ENODEV; 1179 + 1173 1180 nskb = nlmsg_new(if_nlmsg_size(dev), GFP_KERNEL); 1174 - if (nskb == NULL) { 1175 - err = -ENOBUFS; 1176 - goto errout; 1177 - } 1181 + if (nskb == NULL) 1182 + return -ENOBUFS; 1178 1183 1179 1184 err = rtnl_fill_ifinfo(nskb, dev, RTM_NEWLINK, NETLINK_CB(skb).pid, 1180 1185 nlh->nlmsg_seq, 0, 0); ··· 1186 1183 /* -EMSGSIZE implies BUG in if_nlmsg_size */ 1187 1184 WARN_ON(err == -EMSGSIZE); 1188 1185 kfree_skb(nskb); 1189 - goto errout; 1190 - } 1191 - err = rtnl_unicast(nskb, net, NETLINK_CB(skb).pid); 1192 - errout: 1193 - dev_put(dev); 1186 + } else 1187 + err = rtnl_unicast(nskb, net, NETLINK_CB(skb).pid); 1194 1188 1195 1189 return err; 1196 1190 }