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>
This commit is contained in:
parent
1f3c9907b8
commit
a7a3f08dc2
|
@ -4752,6 +4752,8 @@ md_attr_store(struct kobject *kobj, struct attribute *attr,
|
||||||
}
|
}
|
||||||
mddev_get(mddev);
|
mddev_get(mddev);
|
||||||
spin_unlock(&all_mddevs_lock);
|
spin_unlock(&all_mddevs_lock);
|
||||||
|
if (entry->store == new_dev_store)
|
||||||
|
flush_workqueue(md_misc_wq);
|
||||||
rv = mddev_lock(mddev);
|
rv = mddev_lock(mddev);
|
||||||
if (!rv) {
|
if (!rv) {
|
||||||
rv = entry->store(mddev, page, length);
|
rv = entry->store(mddev, page, length);
|
||||||
|
@ -6397,6 +6399,10 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
|
||||||
goto abort;
|
goto abort;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cmd == ADD_NEW_DISK)
|
||||||
|
/* need to ensure md_delayed_delete() has completed */
|
||||||
|
flush_workqueue(md_misc_wq);
|
||||||
|
|
||||||
err = mddev_lock(mddev);
|
err = mddev_lock(mddev);
|
||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_INFO
|
printk(KERN_INFO
|
||||||
|
|
Loading…
Reference in New Issue