summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2007-09-17 11:56:21 -0700
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 16:49:10 -0700
commit881d966b48b035ab3f3aeaae0f3d3f9b584f45b2 (patch)
treec579d59a4107cbbe9e2b85939bc0d496b815c887 /net
parentb4b510290b056b86611757ce1175a230f1080f53 (diff)
[NET]: Make the device list and device lookups per namespace.
This patch makes most of the generic device layer network namespace safe. This patch makes dev_base_head a network namespace variable, and then it picks up a few associated variables. The functions: dev_getbyhwaddr dev_getfirsthwbytype dev_get_by_flags dev_get_by_name __dev_get_by_name dev_get_by_index __dev_get_by_index dev_ioctl dev_ethtool dev_load wireless_process_ioctl were modified to take a network namespace argument, and deal with it. vlan_ioctl_set and brioctl_set were modified so their hooks will receive a network namespace argument. So basically anthing in the core of the network stack that was affected to by the change of dev_base was modified to handle multiple network namespaces. The rest of the network stack was simply modified to explicitly use &init_net the initial network namespace. This can be fixed when those components of the network stack are modified to handle multiple network namespaces. For now the ifindex generator is left global. Fundametally ifindex numbers are per namespace, or else we will have corner case problems with migration when we get that far. At the same time there are assumptions in the network stack that the ifindex of a network device won't change. Making the ifindex number global seems a good compromise until the network stack can cope with ifindex changes when you change namespaces, and the like. Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/802/tr.c2
-rw-r--r--net/8021q/vlan.c6
-rw-r--r--net/8021q/vlan_netlink.c3
-rw-r--r--net/8021q/vlanproc.c6
-rw-r--r--net/appletalk/ddp.c6
-rw-r--r--net/atm/mpc.c2
-rw-r--r--net/ax25/af_ax25.c2
-rw-r--r--net/bridge/br_if.c4
-rw-r--r--net/bridge/br_ioctl.c7
-rw-r--r--net/bridge/br_netlink.c5
-rw-r--r--net/bridge/br_private.h2
-rw-r--r--net/core/dev.c271
-rw-r--r--net/core/dev_mcast.c41
-rw-r--r--net/core/ethtool.c4
-rw-r--r--net/core/fib_rules.c4
-rw-r--r--net/core/neighbour.c6
-rw-r--r--net/core/netpoll.c2
-rw-r--r--net/core/pktgen.c2
-rw-r--r--net/core/rtnetlink.c35
-rw-r--r--net/core/sock.c3
-rw-r--r--net/decnet/af_decnet.c2
-rw-r--r--net/decnet/dn_dev.c20
-rw-r--r--net/decnet/dn_fib.c8
-rw-r--r--net/decnet/dn_route.c6
-rw-r--r--net/decnet/sysctl_net_decnet.c4
-rw-r--r--net/econet/af_econet.c2
-rw-r--r--net/ipv4/arp.c4
-rw-r--r--net/ipv4/devinet.c18
-rw-r--r--net/ipv4/fib_frontend.c2
-rw-r--r--net/ipv4/fib_semantics.c4
-rw-r--r--net/ipv4/icmp.c2
-rw-r--r--net/ipv4/igmp.c4
-rw-r--r--net/ipv4/ip_fragment.c2
-rw-r--r--net/ipv4/ip_gre.c4
-rw-r--r--net/ipv4/ip_sockglue.c2
-rw-r--r--net/ipv4/ipconfig.c2
-rw-r--r--net/ipv4/ipip.c4
-rw-r--r--net/ipv4/ipmr.c4
-rw-r--r--net/ipv4/ipvs/ip_vs_sync.c10
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c2
-rw-r--r--net/ipv4/route.c4
-rw-r--r--net/ipv6/addrconf.c28
-rw-r--r--net/ipv6/af_inet6.c2
-rw-r--r--net/ipv6/anycast.c12
-rw-r--r--net/ipv6/datagram.c2
-rw-r--r--net/ipv6/ip6_tunnel.c6
-rw-r--r--net/ipv6/ipv6_sockglue.c2
-rw-r--r--net/ipv6/mcast.c12
-rw-r--r--net/ipv6/raw.c2
-rw-r--r--net/ipv6/reassembly.c2
-rw-r--r--net/ipv6/route.c4
-rw-r--r--net/ipv6/sit.c4
-rw-r--r--net/ipx/af_ipx.c6
-rw-r--r--net/irda/irnetlink.c9
-rw-r--r--net/llc/af_llc.c4
-rw-r--r--net/llc/llc_core.c3
-rw-r--r--net/mac80211/ieee80211.c1
-rw-r--r--net/mac80211/ieee80211_cfg.c3
-rw-r--r--net/mac80211/tx.c9
-rw-r--r--net/mac80211/util.c7
-rw-r--r--net/netrom/nr_route.c6
-rw-r--r--net/packet/af_packet.c18
-rw-r--r--net/rose/rose_route.c8
-rw-r--r--net/sched/act_mirred.c3
-rw-r--r--net/sched/cls_api.c4
-rw-r--r--net/sched/em_meta.c2
-rw-r--r--net/sched/sch_api.c10
-rw-r--r--net/sctp/ipv6.c4
-rw-r--r--net/sctp/protocol.c2
-rw-r--r--net/socket.c22
-rw-r--r--net/tipc/eth_media.c2
-rw-r--r--net/wireless/wext.c38
-rw-r--r--net/x25/x25_route.c2
73 files changed, 464 insertions, 298 deletions
diff --git a/net/802/tr.c b/net/802/tr.c
index 032c31e748eb..55c76d77d322 100644
--- a/net/802/tr.c
+++ b/net/802/tr.c
@@ -533,7 +533,7 @@ static int rif_seq_show(struct seq_file *seq, void *v)
seq_puts(seq,
"if TR address TTL rcf routing segments\n");
else {
- struct net_device *dev = dev_get_by_index(entry->iface);
+ struct net_device *dev = dev_get_by_index(&init_net, entry->iface);
long ttl = (long) (entry->last_used + sysctl_tr_rif_timeout)
- (long) jiffies;
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index d0d36fdedbe9..a9ced0a6f4c0 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -51,7 +51,7 @@ static char vlan_copyright[] = "Ben Greear <greearb@candelatech.com>";
static char vlan_buggyright[] = "David S. Miller <davem@redhat.com>";
static int vlan_device_event(struct notifier_block *, unsigned long, void *);
-static int vlan_ioctl_handler(void __user *);
+static int vlan_ioctl_handler(struct net *net, void __user *);
static int unregister_vlan_dev(struct net_device *, unsigned short );
static struct notifier_block vlan_notifier_block = {
@@ -697,7 +697,7 @@ out:
* o execute requested action or pass command to the device driver
* arg is really a struct vlan_ioctl_args __user *.
*/
-static int vlan_ioctl_handler(void __user *arg)
+static int vlan_ioctl_handler(struct net *net, void __user *arg)
{
int err;
unsigned short vid = 0;
@@ -726,7 +726,7 @@ static int vlan_ioctl_handler(void __user *arg)
case GET_VLAN_REALDEV_NAME_CMD:
case GET_VLAN_VID_CMD:
err = -ENODEV;
- dev = __dev_get_by_name(args.device1);
+ dev = __dev_get_by_name(&init_net, args.device1);
if (!dev)
goto out;
diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c
index 6cdd1e015e2d..0996185e2ed5 100644
--- a/net/8021q/vlan_netlink.c
+++ b/net/8021q/vlan_netlink.c
@@ -11,6 +11,7 @@
#include <linux/kernel.h>
#include <linux/netdevice.h>
#include <linux/if_vlan.h>
+#include <net/net_namespace.h>
#include <net/netlink.h>
#include <net/rtnetlink.h>
#include "vlan.h"
@@ -112,7 +113,7 @@ static int vlan_newlink(struct net_device *dev,
if (!tb[IFLA_LINK])
return -EINVAL;
- real_dev = __dev_get_by_index(nla_get_u32(tb[IFLA_LINK]));
+ real_dev = __dev_get_by_index(&init_net, nla_get_u32(tb[IFLA_LINK]));
if (!real_dev)
return -ENODEV;
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c
index ac80e6b9ef53..6cefdf8e381a 100644
--- a/net/8021q/vlanproc.c
+++ b/net/8021q/vlanproc.c
@@ -254,7 +254,7 @@ static void *vlan_seq_start(struct seq_file *seq, loff_t *pos)
if (*pos == 0)
return SEQ_START_TOKEN;
- for_each_netdev(dev) {
+ for_each_netdev(&init_net, dev) {
if (!is_vlan_dev(dev))
continue;
@@ -273,9 +273,9 @@ static void *vlan_seq_next(struct seq_file *seq, void *v, loff_t *pos)
dev = (struct net_device *)v;
if (v == SEQ_START_TOKEN)
- dev = net_device_entry(&dev_base_head);
+ dev = net_device_entry(&init_net.dev_base_head);
- for_each_netdev_continue(dev) {
+ for_each_netdev_continue(&init_net, dev) {
if (!is_vlan_dev(dev))
continue;
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c
index 36fcdbf923c4..7c0b5151d526 100644
--- a/net/appletalk/ddp.c
+++ b/net/appletalk/ddp.c
@@ -677,7 +677,7 @@ static int atif_ioctl(int cmd, void __user *arg)
if (copy_from_user(&atreq, arg, sizeof(atreq)))
return -EFAULT;
- dev = __dev_get_by_name(atreq.ifr_name);
+ dev = __dev_get_by_name(&init_net, atreq.ifr_name);
if (!dev)
return -ENODEV;
@@ -901,7 +901,7 @@ static int atrtr_ioctl(unsigned int cmd, void __user *arg)
if (copy_from_user(name, rt.rt_dev, IFNAMSIZ-1))
return -EFAULT;
name[IFNAMSIZ-1] = '\0';
- dev = __dev_get_by_name(name);
+ dev = __dev_get_by_name(&init_net, name);
if (!dev)
return -ENODEV;
}
@@ -1273,7 +1273,7 @@ static __inline__ int is_ip_over_ddp(struct sk_buff *skb)
static int handle_ip_over_ddp(struct sk_buff *skb)
{
- struct net_device *dev = __dev_get_by_name("ipddp0");
+ struct net_device *dev = __dev_get_by_name(&init_net, "ipddp0");
struct net_device_stats *stats;
/* This needs to be able to handle ipddp"N" devices */
diff --git a/net/atm/mpc.c b/net/atm/mpc.c
index 0968430a7f58..2086396de177 100644
--- a/net/atm/mpc.c
+++ b/net/atm/mpc.c
@@ -244,7 +244,7 @@ static struct net_device *find_lec_by_itfnum(int itf)
char name[IFNAMSIZ];
sprintf(name, "lec%d", itf);
- dev = dev_get_by_name(name);
+ dev = dev_get_by_name(&init_net, name);
return dev;
}
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 8d13a8bca0e0..993e5c75e909 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -631,7 +631,7 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
break;
}
- dev = dev_get_by_name(devname);
+ dev = dev_get_by_name(&init_net, devname);
if (dev == NULL) {
res = -ENODEV;
break;
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c
index 9272f12f664c..935784f736b3 100644
--- a/net/bridge/br_if.c
+++ b/net/bridge/br_if.c
@@ -303,7 +303,7 @@ int br_del_bridge(const char *name)
int ret = 0;
rtnl_lock();
- dev = __dev_get_by_name(name);
+ dev = __dev_get_by_name(&init_net, name);
if (dev == NULL)
ret = -ENXIO; /* Could not find device */
@@ -444,7 +444,7 @@ void __exit br_cleanup_bridges(void)
struct net_device *dev, *nxt;
rtnl_lock();
- for_each_netdev_safe(dev, nxt)
+ for_each_netdev_safe(&init_net, dev, nxt)
if (dev->priv_flags & IFF_EBRIDGE)
del_br(dev->priv);
rtnl_unlock();
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c
index bb15e9e259b1..0655a5f07f58 100644
--- a/net/bridge/br_ioctl.c
+++ b/net/bridge/br_ioctl.c
@@ -18,6 +18,7 @@
#include <linux/if_bridge.h>
#include <linux/netdevice.h>
#include <linux/times.h>
+#include <net/net_namespace.h>
#include <asm/uaccess.h>
#include "br_private.h"
@@ -27,7 +28,7 @@ static int get_bridge_ifindices(int *indices, int num)
struct net_device *dev;
int i = 0;
- for_each_netdev(dev) {
+ for_each_netdev(&init_net, dev) {
if (i >= num)
break;
if (dev->priv_flags & IFF_EBRIDGE)
@@ -90,7 +91,7 @@ static int add_del_if(struct net_bridge *br, int ifindex, int isadd)
if (!capable(CAP_NET_ADMIN))
return -EPERM;
- dev = dev_get_by_index(ifindex);
+ dev = dev_get_by_index(&init_net, ifindex);
if (dev == NULL)
return -EINVAL;
@@ -364,7 +365,7 @@ static int old_deviceless(void __user *uarg)
return -EOPNOTSUPP;
}
-int br_ioctl_deviceless_stub(unsigned int cmd, void __user *uarg)
+int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *uarg)
{
switch (cmd) {
case SIOCGIFBR:
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 0fcf6f073064..53ab8e0cb518 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <net/rtnetlink.h>
+#include <net/net_namespace.h>
#include "br_private.h"
static inline size_t br_nlmsg_size(void)
@@ -110,7 +111,7 @@ static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
int idx;
idx = 0;
- for_each_netdev(dev) {
+ for_each_netdev(&init_net, dev) {
/* not a bridge port */
if (dev->br_port == NULL || idx < cb->args[0])
goto skip;
@@ -155,7 +156,7 @@ static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg)
if (new_state > BR_STATE_BLOCKING)
return -EINVAL;
- dev = __dev_get_by_index(ifm->ifi_index);
+ dev = __dev_get_by_index(&init_net, ifm->ifi_index);
if (!dev)
return -ENODEV;
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index e6dc6f52990d..f666f7b28ff5 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -192,7 +192,7 @@ extern struct sk_buff *br_handle_frame(struct net_bridge_port *p,
/* br_ioctl.c */
extern int br_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-extern int br_ioctl_deviceless_stub(unsigned int cmd, void __user *arg);
+extern int br_ioctl_deviceless_stub(struct net *net, unsigned int cmd, void __user *arg);
/* br_netfilter.c */
#ifdef CONFIG_BRIDGE_NETFILTER
diff --git a/net/core/dev.c b/net/core/dev.c
index 40fd66fbe4e1..3a3d5ee73909 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -190,25 +190,22 @@ static struct net_dma net_dma = {
* unregister_netdevice(), which must be called with the rtnl
* semaphore held.
*/
-LIST_HEAD(dev_base_head);
DEFINE_RWLOCK(dev_base_lock);
-EXPORT_SYMBOL(dev_base_head);
EXPORT_SYMBOL(dev_base_lock);
#define NETDEV_HASHBITS 8
-static struct hlist_head dev_name_head[1<<NETDEV_HASHBITS];
-static struct hlist_head dev_index_head[1<<NETDEV_HASHBITS];
+#define NETDEV_HASHENTRIES (1 << NETDEV_HASHBITS)
-static inline struct hlist_head *dev_name_hash(const char *name)
+static inline struct hlist_head *dev_name_hash(struct net *net, const char *name)
{
unsigned hash = full_name_hash(name, strnlen(name, IFNAMSIZ));
- return &dev_name_head[hash & ((1<<NETDEV_HASHBITS)-1)];
+ return &net->dev_name_head[hash & ((1 << NETDEV_HASHBITS) - 1)];
}
-static inline struct hlist_head *dev_index_hash(int ifindex)
+static inline struct hlist_head *dev_index_hash(struct net *net, int ifindex)
{
- return &dev_index_head[ifindex & ((1<<NETDEV_HASHBITS)-1)];
+ return &net->dev_index_head[ifindex & ((1 << NETDEV_HASHBITS) - 1)];
}
/*
@@ -492,7 +489,7 @@ unsigned long netdev_boot_base(const char *prefix, int unit)
* If device already registered then return base of 1
* to indicate not to probe for this interface
*/
- if (__dev_get_by_name(name))
+ if (__dev_get_by_name(&init_net, name))
return 1;
for (i = 0; i < NETDEV_BOOT_SETUP_MAX; i++)
@@ -547,11 +544,11 @@ __setup("netdev=", netdev_boot_setup);
* careful with locks.
*/
-struct net_device *__dev_get_by_name(const char *name)
+struct net_device *__dev_get_by_name(struct net *net, const char *name)
{
struct hlist_node *p;
- hlist_for_each(p, dev_name_hash(name)) {
+ hlist_for_each(p, dev_name_hash(net, name)) {
struct net_device *dev
= hlist_entry(p, struct net_device, name_hlist);
if (!strncmp(dev->name, name, IFNAMSIZ))
@@ -571,12 +568,12 @@ struct net_device *__dev_get_by_name(const char *name)
* matching device is found.
*/
-struct net_device *dev_get_by_name(const char *name)
+struct net_device *dev_get_by_name(struct net *net, const char *name)
{
struct net_device *dev;
read_lock(&dev_base_lock);
- dev = __dev_get_by_name(name);
+ dev = __dev_get_by_name(net, name);
if (dev)
dev_hold(dev);
read_unlock(&dev_base_lock);
@@ -594,11 +591,11 @@ struct net_device *dev_get_by_name(const char *name)
* or @dev_base_lock.
*/
-struct net_device *__dev_get_by_index(int ifindex)
+struct net_device *__dev_get_by_index(struct net *net, int ifindex)
{
struct hlist_node *p;
- hlist_for_each(p, dev_index_hash(ifindex)) {
+ hlist_for_each(p, dev_index_hash(net, ifindex)) {
struct net_device *dev
= hlist_entry(p, struct net_device, index_hlist);
if (dev->ifindex == ifindex)
@@ -618,12 +615,12 @@ struct net_device *__dev_get_by_index(int ifindex)
* dev_put to indicate they have finished with it.
*/
-struct net_device *dev_get_by_index(int ifindex)
+struct net_device *dev_get_by_index(struct net *net, int ifindex)
{
struct net_device *dev;
read_lock(&dev_base_lock);
- dev = __dev_get_by_index(ifindex);
+ dev = __dev_get_by_index(net, ifindex);
if (dev)
dev_hold(dev);
read_unlock(&dev_base_lock);
@@ -644,13 +641,13 @@ struct net_device *dev_get_by_index(int ifindex)
* If the API was consistent this would be __dev_get_by_hwaddr
*/
-struct net_device *dev_getbyhwaddr(unsigned short type, char *ha)
+struct net_device *dev_getbyhwaddr(struct net *net, unsigned short type, char *ha)
{
struct net_device *dev;
ASSERT_RTNL();
- for_each_netdev(dev)
+ for_each_netdev(&init_net, dev)
if (dev->type == type &&
!memcmp(dev->dev_addr, ha, dev->addr_len))
return dev;
@@ -660,12 +657,12 @@ struct net_device *dev_getbyhwaddr(unsigned short type, char *ha)
EXPORT_SYMBOL(dev_getbyhwaddr);
-struct net_device *__dev_getfirstbyhwtype(unsigned short type)
+struct net_device *__dev_getfirstbyhwtype(struct net *net, unsigned short type)
{
struct net_device *dev;
ASSERT_RTNL();
- for_each_netdev(dev)
+ for_each_netdev(net, dev)
if (dev->type == type)
return dev;
@@ -674,12 +671,12 @@ struct net_device *__dev_getfirstbyhwtype(unsigned short type)
EXPORT_SYMBOL(__dev_getfirstbyhwtype);
-struct net_device *dev_getfirstbyhwtype(unsigned short type)
+struct net_device *dev_getfirstbyhwtype(struct net *net, unsigned short type)
{
struct net_device *dev;
rtnl_lock();
- dev = __dev_getfirstbyhwtype(type);
+ dev = __dev_getfirstbyhwtype(net, type);
if (dev)
dev_hold(dev);
rtnl_unlock();
@@ -699,13 +696,13 @@ EXPORT_SYMBOL(dev_getfirstbyhwtype);
* dev_put to indicate they have finished with it.
*/
-struct net_device * dev_get_by_flags(unsigned short if_flags, unsigned short mask)
+struct net_device * dev_get_by_flags(struct net *net, unsigned short if_flags, unsigned short mask)
{
struct net_device *dev, *ret;
ret = NULL;
read_lock(&dev_base_lock);
- for_each_netdev(dev) {
+ for_each_netdev(net, dev) {
if (((dev->flags ^ if_flags) & mask) == 0) {
dev_hold(dev);
ret = dev;
@@ -763,6 +760,10 @@ int dev_alloc_name(struct net_device *dev, const char *name)
const int max_netdevices = 8*PAGE_SIZE;
long *inuse;
struct net_device *d;
+ struct net *net;
+
+ BUG_ON(!dev->nd_net);
+ net = dev->nd_net;
p = strnchr(name, IFNAMSIZ-1, '%');
if (p) {
@@ -779,7 +780,7 @@ int dev_alloc_name(struct net_device *dev, const char *name)
if (!inuse)
return -ENOMEM;
- for_each_netdev(d) {
+ for_each_netdev(net, d) {
if (!sscanf(d->name, name, &i))
continue;
if (i < 0 || i >= max_netdevices)
@@ -796,7 +797,7 @@ int dev_alloc_name(struct net_device *dev, const char *name)
}
snprintf(buf, sizeof(buf), name, i);
- if (!__dev_get_by_name(buf)) {
+ if (!__dev_get_by_name(net, buf)) {
strlcpy(dev->name, buf, IFNAMSIZ);
return i;
}
@@ -822,9 +823,12 @@ int dev_change_name(struct net_device *dev, char *newname)
char oldname[IFNAMSIZ];
int err = 0;
int ret;
+ struct net *net;
ASSERT_RTNL();
+ BUG_ON(!dev->nd_net);
+ net = dev->nd_net;
if (dev->flags & IFF_UP)
return -EBUSY;
@@ -839,7 +843,7 @@ int dev_change_name(struct net_device *dev, char *newname)
return err;
strcpy(newname, dev->name);
}
- else if (__dev_get_by_name(newname))
+ else if (__dev_get_by_name(net, newname))
return -EEXIST;
else
strlcpy(dev->name, newname, IFNAMSIZ);
@@ -849,7 +853,7 @@ rollback:
write_lock_bh(&dev_base_lock);
hlist_del(&dev->name_hlist);
- hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name));
+ hlist_add_head(&dev->name_hlist, dev_name_hash(net, dev->name));
write_unlock_bh(&dev_base_lock);
ret = raw_notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
@@ -908,12 +912,12 @@ void netdev_state_change(struct net_device *dev)
* available in this kernel then it becomes a nop.
*/
-void dev_load(const char *name)
+void dev_load(struct net *net, const char *name)
{
struct net_device *dev;
read_lock(&dev_base_lock);
- dev = __dev_get_by_name(name);
+ dev = __dev_get_by_name(net, name);
read_unlock(&dev_base_lock);
if (!dev && capable(CAP_SYS_MODULE))
@@ -1052,6 +1056,8 @@ int dev_close(struct net_device *dev)
}
+static int dev_boot_phase = 1;
+
/*
* Device change register/unregister. These are not inline or static
* as we export them to the world.
@@ -1075,23 +1081,27 @@ int register_netdevice_notifier(struct notifier_block *nb)
{
struct net_device *dev;
struct net_device *last;
+ struct net *net;
int err;
rtnl_lock();
err = raw_notifier_chain_register(&netdev_chain, nb);
if (err)
goto unlock;
+ if (dev_boot_phase)
+ goto unlock;
+ for_each_net(net) {
+ for_each_netdev(net, dev) {
+ err =