aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2012-12-10 21:35:54 -0500
committerNeilBrown <neilb@suse.de>2012-12-10 21:35:54 -0500
commita7a3f08dc24690ae00c75cfe4b4701a970dd0155 (patch)
treebc9174cc50feba550a33148e661dc57ac37950dd /drivers/md
parent1f3c9907b8037de7b9635b0b471572ea8758bcd1 (diff)
md: close race between removing and adding a device.
When we remove a device from an md array, the final removal of the "dev-XX" sys entry is run asynchronously. If we then re-add that device immediately before the worker thread gets to run, we can end up trying to add the "dev-XX" sysfs entry back before it has been removed. So in both places where we add a device, call flush_workqueue(md_misc_wq); before taking the md lock (as holding the md lock can prevent removal to complete). Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/md.c6
1 files changed, 6 insertions, 0 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 89dbd444517..8b0e3d21f73 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -4752,6 +4752,8 @@ md_attr_store(struct kobject *kobj, struct attribute *attr,
4752 } 4752 }
4753 mddev_get(mddev); 4753 mddev_get(mddev);
4754 spin_unlock(&all_mddevs_lock); 4754 spin_unlock(&all_mddevs_lock);
4755 if (entry->store == new_dev_store)
4756 flush_workqueue(md_misc_wq);
4755 rv = mddev_lock(mddev); 4757 rv = mddev_lock(mddev);
4756 if (!rv) { 4758 if (!rv) {
4757 rv = entry->store(mddev, page, length); 4759 rv = entry->store(mddev, page, length);
@@ -6397,6 +6399,10 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
6397 goto abort; 6399 goto abort;
6398 } 6400 }
6399 6401
6402 if (cmd == ADD_NEW_DISK)
6403 /* need to ensure md_delayed_delete() has completed */
6404 flush_workqueue(md_misc_wq);
6405
6400 err = mddev_lock(mddev); 6406 err = mddev_lock(mddev);
6401 if (err) { 6407 if (err) {
6402 printk(KERN_INFO 6408 printk(KERN_INFO