diff options
| author | NeilBrown <neilb@suse.de> | 2012-12-10 21:35:54 -0500 |
|---|---|---|
| committer | NeilBrown <neilb@suse.de> | 2012-12-10 21:35:54 -0500 |
| commit | a7a3f08dc24690ae00c75cfe4b4701a970dd0155 (patch) | |
| tree | bc9174cc50feba550a33148e661dc57ac37950dd /drivers/md | |
| parent | 1f3c9907b8037de7b9635b0b471572ea8758bcd1 (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.c | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 89dbd444517e..8b0e3d21f736 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 |
