aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/virtio_net.c
diff options
context:
space:
mode:
authorJason Wang <jasowang@redhat.com>2013-10-29 03:11:07 -0400
committerDavid S. Miller <davem@davemloft.net>2013-10-29 22:43:41 -0400
commitec9debbd9a88d8ea86c488d6ffcac419ee7d46d9 (patch)
tree35bf707a68aeb4092d4208926896e61899f406cf /drivers/net/virtio_net.c
parent06499098a02b9ed906a7b6060f2c60fb813918d4 (diff)
virtio-net: correctly handle cpu hotplug notifier during resuming
commit 3ab098df35f8b98b6553edc2e40234af512ba877 (virtio-net: don't respond to cpu hotplug notifier if we're not ready) tries to bypass the cpu hotplug notifier by checking the config_enable and does nothing is it was false. So it need to try to hold the config_lock mutex which may happen in atomic environment which leads the following warnings: [ 622.944441] CPU0 attaching NULL sched-domain. [ 622.944446] CPU1 attaching NULL sched-domain. [ 622.944485] CPU0 attaching NULL sched-domain. [ 622.950795] BUG: sleeping function called from invalid context at kernel/mutex.c:616 [ 622.950796] in_atomic(): 1, irqs_disabled(): 1, pid: 10, name: migration/1 [ 622.950796] no locks held by migration/1/10. [ 622.950798] CPU: 1 PID: 10 Comm: migration/1 Not tainted 3.12.0-rc5-wl-01249-gb91e82d #317 [ 622.950799] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 [ 622.950802] 0000000000000000 ffff88001d42dba0 ffffffff81a32f22 ffff88001bfb9c70 [ 622.950803] ffff88001d42dbb0 ffffffff810edb02 ffff88001d42dc38 ffffffff81a396ed [ 622.950805] 0000000000000046 ffff88001d42dbe8 ffffffff810e861d 0000000000000000 [ 622.950805] Call Trace: [ 622.950810] [<ffffffff81a32f22>] dump_stack+0x54/0x74 [ 622.950815] [<ffffffff810edb02>] __might_sleep+0x112/0x114 [ 622.950817] [<ffffffff81a396ed>] mutex_lock_nested+0x3c/0x3c6 [ 622.950818] [<ffffffff810e861d>] ? up+0x39/0x3e [ 622.950821] [<ffffffff8153ea7c>] ? acpi_os_signal_semaphore+0x21/0x2d [ 622.950824] [<ffffffff81565ed1>] ? acpi_ut_release_mutex+0x5e/0x62 [ 622.950828] [<ffffffff816d04ec>] virtnet_cpu_callback+0x33/0x87 [ 622.950830] [<ffffffff81a42576>] notifier_call_chain+0x3c/0x5e [ 622.950832] [<ffffffff810e86a8>] __raw_notifier_call_chain+0xe/0x10 [ 622.950835] [<ffffffff810c5556>] __cpu_notify+0x20/0x37 [ 622.950836] [<ffffffff810c5580>] cpu_notify+0x13/0x15 [ 622.950838] [<ffffffff81a237cd>] take_cpu_down+0x27/0x3a [ 622.950841] [<ffffffff81136289>] stop_machine_cpu_stop+0x93/0xf1 [ 622.950842] [<ffffffff81136167>] cpu_stopper_thread+0xa0/0x12f [ 622.950844] [<ffffffff811361f6>] ? cpu_stopper_thread+0x12f/0x12f [ 622.950847] [<ffffffff81119710>] ? lock_release_holdtime.part.7+0xa3/0xa8 [ 622.950848] [<ffffffff81135e4b>] ? cpu_stop_should_run+0x3f/0x47 [ 622.950850] [<ffffffff810ea9b0>] smpboot_thread_fn+0x1c5/0x1e3 [ 622.950852] [<ffffffff810ea7eb>] ? lg_global_unlock+0x67/0x67 [ 622.950854] [<ffffffff810e36b7>] kthread+0xd8/0xe0 [ 622.950857] [<ffffffff81a3bfad>] ? wait_for_common+0x12f/0x164 [ 622.950859] [<ffffffff810e35df>] ? kthread_create_on_node+0x124/0x124 [ 622.950861] [<ffffffff81a45ffc>] ret_from_fork+0x7c/0xb0 [ 622.950862] [<ffffffff810e35df>] ? kthread_create_on_node+0x124/0x124 [ 622.950876] smpboot: CPU 1 is now offline [ 623.194556] SMP alternatives: lockdep: fixing up alternatives [ 623.194559] smpboot: Booting Node 0 Processor 1 APIC 0x1 ... A correct fix is to unregister the hotcpu notifier during restore and register a new one in resume. Reported-by: Fengguang Wu <fengguang.wu@intel.com> Tested-by: Fengguang Wu <fengguang.wu@intel.com> Cc: Wanlong Gao <gaowanlong@cn.fujitsu.com> Cc: Rusty Russell <rusty@rustcorp.com.au> Cc: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Jason Wang <jasowang@redhat.com> Acked-by: Michael S. Tsirkin <mst@redhat.com> Reviewed-by: Wanlong Gao <gaowanlong@cn.fujitsu.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/virtio_net.c')
-rw-r--r--drivers/net/virtio_net.c13
1 files changed, 6 insertions, 7 deletions
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 9fbdfcd1e1a0..bbc9cb84ec1f 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -1118,11 +1118,6 @@ static int virtnet_cpu_callback(struct notifier_block *nfb,
1118{ 1118{
1119 struct virtnet_info *vi = container_of(nfb, struct virtnet_info, nb); 1119 struct virtnet_info *vi = container_of(nfb, struct virtnet_info, nb);
1120 1120
1121 mutex_lock(&vi->config_lock);
1122
1123 if (!vi->config_enable)
1124 goto done;
1125
1126 switch(action & ~CPU_TASKS_FROZEN) { 1121 switch(action & ~CPU_TASKS_FROZEN) {
1127 case CPU_ONLINE: 1122 case CPU_ONLINE:
1128 case CPU_DOWN_FAILED: 1123 case CPU_DOWN_FAILED:
@@ -1136,8 +1131,6 @@ static int virtnet_cpu_callback(struct notifier_block *nfb,
1136 break; 1131 break;
1137 } 1132 }
1138 1133
1139done:
1140 mutex_unlock(&vi->config_lock);
1141 return NOTIFY_OK; 1134 return NOTIFY_OK;
1142} 1135}
1143 1136
@@ -1699,6 +1692,8 @@ static int virtnet_freeze(struct virtio_device *vdev)
1699 struct virtnet_info *vi = vdev->priv; 1692 struct virtnet_info *vi = vdev->priv;
1700 int i; 1693 int i;
1701 1694
1695 unregister_hotcpu_notifier(&vi->nb);
1696
1702 /* Prevent config work handler from accessing the device */ 1697 /* Prevent config work handler from accessing the device */
1703 mutex_lock(&vi->config_lock); 1698 mutex_lock(&vi->config_lock);
1704 vi->config_enable = false; 1699 vi->config_enable = false;
@@ -1747,6 +1742,10 @@ static int virtnet_restore(struct virtio_device *vdev)
1747 virtnet_set_queues(vi, vi->curr_queue_pairs); 1742 virtnet_set_queues(vi, vi->curr_queue_pairs);
1748 rtnl_unlock(); 1743 rtnl_unlock();
1749 1744
1745 err = register_hotcpu_notifier(&vi->nb);
1746 if (err)
1747 return err;
1748
1750 return 0; 1749 return 0;
1751} 1750}
1752#endif 1751#endif