Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

[PATCH] md: avoid a deadlock when removing a device from an md array via sysfs

A device can be removed from an md array via e.g.
echo remove > /sys/block/md3/md/dev-sde/state

This will try to remove the 'dev-sde' subtree which will deadlock
since
commit e7b0d26a86943370c04d6833c6edba2a72a6e240

With this patch we run the kobject_del via schedule_work so as to
avoid the deadlock.

Cc: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Neil Brown <neilb@suse.de>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

NeilBrown and committed by
Linus Torvalds
5792a285 456a09dc

+16 -1
+15 -1
drivers/md/md.c
··· 1378 1378 return err; 1379 1379 } 1380 1380 1381 + static void delayed_delete(struct work_struct *ws) 1382 + { 1383 + mdk_rdev_t *rdev = container_of(ws, mdk_rdev_t, del_work); 1384 + kobject_del(&rdev->kobj); 1385 + } 1386 + 1381 1387 static void unbind_rdev_from_array(mdk_rdev_t * rdev) 1382 1388 { 1383 1389 char b[BDEVNAME_SIZE]; ··· 1396 1390 printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b)); 1397 1391 rdev->mddev = NULL; 1398 1392 sysfs_remove_link(&rdev->kobj, "block"); 1399 - kobject_del(&rdev->kobj); 1393 + 1394 + /* We need to delay this, otherwise we can deadlock when 1395 + * writing to 'remove' to "dev/state" 1396 + */ 1397 + INIT_WORK(&rdev->del_work, delayed_delete); 1398 + schedule_work(&rdev->del_work); 1400 1399 } 1401 1400 1402 1401 /* ··· 3399 3388 sprintf(nm, "rd%d", rdev->raid_disk); 3400 3389 sysfs_remove_link(&mddev->kobj, nm); 3401 3390 } 3391 + 3392 + /* make sure all delayed_delete calls have finished */ 3393 + flush_scheduled_work(); 3402 3394 3403 3395 export_array(mddev); 3404 3396
+1
include/linux/raid/md_k.h
··· 104 104 * for reporting to userspace and storing 105 105 * in superblock. 106 106 */ 107 + struct work_struct del_work; /* used for delayed sysfs removal */ 107 108 }; 108 109 109 110 struct mddev_s