Commit e72aee74 authored by David S. Miller's avatar David S. Miller Committed by David S. Miller

[NET]: Process hotplug list in FIFO order.

Based upon a patch from Stephen Hemminger.
parent a3072b56
......@@ -3005,14 +3005,15 @@ subsys_initcall(net_dev_init);
#ifdef CONFIG_HOTPLUG
struct net_hotplug_todo {
struct net_hotplug_todo *next;
struct list_head list;
char ifname[IFNAMSIZ];
int is_register;
};
static spinlock_t net_hotplug_list_lock = SPIN_LOCK_UNLOCKED;
static struct net_hotplug_todo *net_hotplug_list;
static DECLARE_MUTEX(net_hotplug_run);
static struct list_head net_hotplug_list = LIST_HEAD_INIT(net_hotplug_list);
static void net_run_hotplug_one(struct net_hotplug_todo *ent)
static inline void net_run_hotplug_one(struct net_hotplug_todo *ent)
{
char *argv[3], *envp[5], ifname[12 + IFNAMSIZ], action_str[32];
int i;
......@@ -3037,23 +3038,37 @@ static void net_run_hotplug_one(struct net_hotplug_todo *ent)
call_usermodehelper(argv [0], argv, envp, 0);
}
/* Run all queued hotplug requests.
* Requests are run in FIFO order.
*/
static void net_run_hotplug_todo(void)
{
struct net_hotplug_todo *list;
struct list_head list = LIST_HEAD_INIT(list);
/* This is racy but okay since any other requests will get
* processed when the other guy does rtnl_unlock.
*/
if (list_empty(&net_hotplug_list))
return;
/* Need to guard against multiple cpu's getting out of order. */
down(&net_hotplug_run);
/* Snapshot list, allow later requests */
spin_lock(&net_hotplug_list_lock);
list = net_hotplug_list;
net_hotplug_list = NULL;
list_splice_init(&net_hotplug_list, &list);
spin_unlock(&net_hotplug_list_lock);
while (list != NULL) {
struct net_hotplug_todo *next = list->next;
while (!list_empty(&list)) {
struct net_hotplug_todo *ent;
net_run_hotplug_one(list);
kfree(list);
list = next;
ent = list_entry(list.next, struct net_hotplug_todo, list);
list_del(&ent->list);
net_run_hotplug_one(ent);
kfree(ent);
}
up(&net_hotplug_run);
}
/* Notify userspace when a netdevice event occurs,
......@@ -3065,15 +3080,17 @@ static void net_run_sbin_hotplug(struct net_device *dev, int is_register)
{
struct net_hotplug_todo *ent = kmalloc(sizeof(*ent), GFP_KERNEL);
ASSERT_RTNL();
if (!ent)
return;
INIT_LIST_HEAD(&ent->list);
memcpy(ent->ifname, dev->name, IFNAMSIZ);
ent->is_register = is_register;
spin_lock(&net_hotplug_list_lock);
ent->next = net_hotplug_list;
net_hotplug_list = ent;
list_add(&ent->list, &net_hotplug_list);
spin_unlock(&net_hotplug_list_lock);
}
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment