diff options
| author | Rusty Russell <rusty@rustcorp.com.au> | 2004-03-18 16:04:13 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-03-18 16:04:13 -0800 |
| commit | 279ce7b25799360a650473ce5cd89b8103faf8f0 (patch) | |
| tree | 49a4930d9c28f80f41d6c29e34319a216f9a6174 /net/core/dev.c | |
| parent | 9bd3badff4e7b97209961875014053d6a292af99 (diff) | |
[PATCH] Hotplug CPUs: Other CPU_DEAD Notifiers
Various files keep per-cpu caches which need to be freed/moved when a
CPU goes down. All under CONFIG_HOTPLUG_CPU ifdefs.
scsi.c: drain dead cpu's scsi_done_q onto this cpu.
buffer.c: brelse the bh_lrus queue for dead cpu.
timer.c: migrate timers from dead cpu, being careful of lock order vs
__mod_timer.
radix_tree.c: free dead cpu's radix_tree_preloads
page_alloc.c: empty dead cpu's nr_pagecache_local into nr_pagecache, and
free pages on cpu's local cache.
slab.c: stop reap_timer for dead cpu, adjust each cache's free limit, and
free each slab cache's per-cpu block.
swap.c: drain dead cpu's lru_add_pvecs into ours, and empty its committed_space
counter into global counter.
dev.c: drain device queues from dead cpu into this one.
flow.c: drain dead cpu's flow cache.
Diffstat (limited to 'net/core/dev.c')
| -rw-r--r-- | net/core/dev.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/net/core/dev.c b/net/core/dev.c index b4418fb5eb25..201878db9853 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -76,6 +76,7 @@ #include <asm/system.h> #include <asm/bitops.h> #include <linux/config.h> +#include <linux/cpu.h> #include <linux/types.h> #include <linux/kernel.h> #include <linux/sched.h> @@ -3131,6 +3132,52 @@ int unregister_netdevice(struct net_device *dev) return 0; } +#ifdef CONFIG_HOTPLUG_CPU +static int dev_cpu_callback(struct notifier_block *nfb, + unsigned long action, + void *ocpu) +{ + struct sk_buff **list_skb; + struct net_device **list_net; + struct sk_buff *skb; + unsigned int cpu, oldcpu = (unsigned long)ocpu; + struct softnet_data *sd, *oldsd; + + if (action != CPU_DEAD) + return NOTIFY_OK; + + local_irq_disable(); + cpu = smp_processor_id(); + sd = &per_cpu(softnet_data, cpu); + oldsd = &per_cpu(softnet_data, oldcpu); + + /* Find end of our completion_queue. */ + list_skb = &sd->completion_queue; + while (*list_skb) + list_skb = &(*list_skb)->next; + /* Append completion queue from offline CPU. */ + *list_skb = oldsd->completion_queue; + oldsd->completion_queue = NULL; + + /* Find end of our output_queue. */ + list_net = &sd->output_queue; + while (*list_net) + list_net = &(*list_net)->next_sched; + /* Append output queue from offline CPU. */ + *list_net = oldsd->output_queue; + oldsd->output_queue = NULL; + + raise_softirq_irqoff(NET_TX_SOFTIRQ); + local_irq_enable(); + + /* Process offline CPU's input_pkt_queue */ + while ((skb = __skb_dequeue(&oldsd->input_pkt_queue))) + netif_rx(skb); + + return NOTIFY_OK; +} +#endif /* CONFIG_HOTPLUG_CPU */ + /* * Initialize the DEV module. At boot time this walks the device list and @@ -3195,6 +3242,7 @@ static int __init net_dev_init(void) open_softirq(NET_TX_SOFTIRQ, net_tx_action, NULL); open_softirq(NET_RX_SOFTIRQ, net_rx_action, NULL); + hotcpu_notifier(dev_cpu_callback, 0); dst_init(); dev_mcast_init(); rc = 0; |
