summaryrefslogtreecommitdiff
path: root/include/linux/netdevice.h
diff options
context:
space:
mode:
authorDavid S. Miller <davem@nuts.ninka.net>2003-05-19 04:30:48 -0700
committerDavid S. Miller <davem@nuts.ninka.net>2003-05-19 04:30:48 -0700
commitff936f4e8148e75b20595eda5de6d3a4bb55b631 (patch)
tree96e7b8175a9da098dde77ee24e030258a2fe4ee1 /include/linux/netdevice.h
parent3b1d5e1d06c7d8c6d24f565ef2a7d1cdfdf9a908 (diff)
[NET]: Fix netdevice unregister races.
We had two major issues when unregistering networking devices. 1) Even trying to run hotplug asynchronously could deadlock if keventd was currently trying to get the RTNL semaphore in order to process linkwatch events. 2) Unregister needs to wait for the last reference to go away before the finalization of the unregister can execute. This cannot occur under the RTNL semaphore as this is deadlock prone as well. The solution is to do all of this stuff after dropping the RTNL semaphore. rtnl_lock, if it is about to protect a region of code that could unregister network devices, registers a list to which unregistered netdevs are attached. At rtnl_unlock time this list is processed to wait for refcounts to drop to zero and then finalize the unregister.
Diffstat (limited to 'include/linux/netdevice.h')
-rw-r--r--include/linux/netdevice.h10
1 files changed, 4 insertions, 6 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index 9ebb267411df..27716f740fb0 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -427,9 +427,6 @@ struct net_device
int (*neigh_setup)(struct net_device *dev, struct neigh_parms *);
int (*accept_fastpath)(struct net_device *, struct dst_entry*);
- /* open/release and usage marking */
- struct module *owner;
-
/* bridge stuff */
struct net_bridge_port *br_port;
@@ -448,6 +445,7 @@ struct net_device
struct kobject kobj;
};
+#define SET_MODULE_OWNER(dev) do { } while (0)
struct packet_type
{
@@ -626,12 +624,12 @@ static inline int netif_rx_ni(struct sk_buff *skb)
return err;
}
-extern int netdev_finish_unregister(struct net_device *dev);
+/* Called by rtnetlink.c:rtnl_unlock() */
+extern void netdev_wait_and_finish_unregister(struct net_device **list);
static inline void dev_put(struct net_device *dev)
{
- if (atomic_dec_and_test(&dev->refcnt))
- netdev_finish_unregister(dev);
+ atomic_dec(&dev->refcnt);
}
#define __dev_put(dev) atomic_dec(&(dev)->refcnt)