mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2024-11-17 10:01:01 +03:00
Cleanup zvol initialization code
The following error will occur on some (possibly all) kernels because blk_init_queue() will try to take the spinlock before we initialize it. BUG: spinlock bad magic on CPU#0, zpool/4054 lock: 0xffff88021a73de60, .magic: 00000000, .owner: <none>/-1, .owner_cpu: 0 Pid: 4054, comm: zpool Not tainted 3.9.3 #11 Call Trace: [<ffffffff81478ef8>] spin_dump+0x8c/0x91 [<ffffffff81478f1e>] spin_bug+0x21/0x26 [<ffffffff812da097>] do_raw_spin_lock+0x127/0x130 [<ffffffff8147d851>] _raw_spin_lock_irq+0x21/0x30 [<ffffffff812c2c1e>] cfq_init_queue+0x1fe/0x350 [<ffffffff812aacb8>] elevator_init+0x78/0x140 [<ffffffff812b2677>] blk_init_allocated_queue+0x87/0xb0 [<ffffffff812b26d5>] blk_init_queue_node+0x35/0x70 [<ffffffff812b271e>] blk_init_queue+0xe/0x10 [<ffffffff8125211b>] __zvol_create_minor+0x24b/0x620 [<ffffffff81253264>] zvol_create_minors_cb+0x24/0x30 [<ffffffff811bd9ca>] dmu_objset_find_spa+0xea/0x510 [<ffffffff811bda71>] dmu_objset_find_spa+0x191/0x510 [<ffffffff81253ea2>] zvol_create_minors+0x92/0x180 [<ffffffff811f8d80>] spa_open_common+0x250/0x380 [<ffffffff811f8ece>] spa_open+0xe/0x10 [<ffffffff8122817e>] pool_status_check.part.22+0x1e/0x80 [<ffffffff81228a55>] zfsdev_ioctl+0x155/0x190 [<ffffffff8116a695>] do_vfs_ioctl+0x325/0x5a0 [<ffffffff8116a950>] sys_ioctl+0x40/0x80 [<ffffffff814812c9>] ? do_page_fault+0x9/0x10 [<ffffffff81483929>] system_call_fastpath+0x16/0x1b zd0: unknown partition table We fix this by calling spin_lock_init before blk_init_queue. The manner in which zvol_init() initializes structures is suspectible to a race between initialization and a probe on a zvol. We reorganize zvol_init() to prevent that. Signed-off-by: Richard Yao <ryao@gentoo.org> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
This commit is contained in:
parent
526af78550
commit
2a3871d4bc
@ -1215,6 +1215,9 @@ zvol_alloc(dev_t dev, const char *name)
|
|||||||
|
|
||||||
zv = kmem_zalloc(sizeof (zvol_state_t), KM_SLEEP);
|
zv = kmem_zalloc(sizeof (zvol_state_t), KM_SLEEP);
|
||||||
|
|
||||||
|
spin_lock_init(&zv->zv_lock);
|
||||||
|
list_link_init(&zv->zv_next);
|
||||||
|
|
||||||
zv->zv_queue = blk_init_queue(zvol_request, &zv->zv_lock);
|
zv->zv_queue = blk_init_queue(zvol_request, &zv->zv_lock);
|
||||||
if (zv->zv_queue == NULL)
|
if (zv->zv_queue == NULL)
|
||||||
goto out_kmem;
|
goto out_kmem;
|
||||||
@ -1248,9 +1251,6 @@ zvol_alloc(dev_t dev, const char *name)
|
|||||||
sizeof (rl_t), offsetof(rl_t, r_node));
|
sizeof (rl_t), offsetof(rl_t, r_node));
|
||||||
zv->zv_znode.z_is_zvol = TRUE;
|
zv->zv_znode.z_is_zvol = TRUE;
|
||||||
|
|
||||||
spin_lock_init(&zv->zv_lock);
|
|
||||||
list_link_init(&zv->zv_next);
|
|
||||||
|
|
||||||
zv->zv_disk->major = zvol_major;
|
zv->zv_disk->major = zvol_major;
|
||||||
zv->zv_disk->first_minor = (dev & MINORMASK);
|
zv->zv_disk->first_minor = (dev & MINORMASK);
|
||||||
zv->zv_disk->fops = &zvol_ops;
|
zv->zv_disk->fops = &zvol_ops;
|
||||||
@ -1561,30 +1561,38 @@ zvol_init(void)
|
|||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
|
list_create(&zvol_state_list, sizeof (zvol_state_t),
|
||||||
|
offsetof(zvol_state_t, zv_next));
|
||||||
|
mutex_init(&zvol_state_lock, NULL, MUTEX_DEFAULT, NULL);
|
||||||
|
|
||||||
zvol_taskq = taskq_create(ZVOL_DRIVER, zvol_threads, maxclsyspri,
|
zvol_taskq = taskq_create(ZVOL_DRIVER, zvol_threads, maxclsyspri,
|
||||||
zvol_threads, INT_MAX, TASKQ_PREPOPULATE);
|
zvol_threads, INT_MAX, TASKQ_PREPOPULATE);
|
||||||
if (zvol_taskq == NULL) {
|
if (zvol_taskq == NULL) {
|
||||||
printk(KERN_INFO "ZFS: taskq_create() failed\n");
|
printk(KERN_INFO "ZFS: taskq_create() failed\n");
|
||||||
return (-ENOMEM);
|
error = -ENOMEM;
|
||||||
|
goto out1;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = register_blkdev(zvol_major, ZVOL_DRIVER);
|
error = register_blkdev(zvol_major, ZVOL_DRIVER);
|
||||||
if (error) {
|
if (error) {
|
||||||
printk(KERN_INFO "ZFS: register_blkdev() failed %d\n", error);
|
printk(KERN_INFO "ZFS: register_blkdev() failed %d\n", error);
|
||||||
taskq_destroy(zvol_taskq);
|
goto out2;
|
||||||
return (error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
blk_register_region(MKDEV(zvol_major, 0), 1UL << MINORBITS,
|
blk_register_region(MKDEV(zvol_major, 0), 1UL << MINORBITS,
|
||||||
THIS_MODULE, zvol_probe, NULL, NULL);
|
THIS_MODULE, zvol_probe, NULL, NULL);
|
||||||
|
|
||||||
mutex_init(&zvol_state_lock, NULL, MUTEX_DEFAULT, NULL);
|
|
||||||
list_create(&zvol_state_list, sizeof (zvol_state_t),
|
|
||||||
offsetof(zvol_state_t, zv_next));
|
|
||||||
|
|
||||||
(void) zvol_create_minors(NULL);
|
(void) zvol_create_minors(NULL);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
|
out2:
|
||||||
|
taskq_destroy(zvol_taskq);
|
||||||
|
out1:
|
||||||
|
mutex_destroy(&zvol_state_lock);
|
||||||
|
list_destroy(&zvol_state_list);
|
||||||
|
|
||||||
|
return (error);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
Loading…
Reference in New Issue
Block a user