md: close race between removing and adding a device.
authorNeilBrown <neilb@suse.de>
Tue, 11 Dec 2012 02:35:54 +0000 (13:35 +1100)
committerNeilBrown <neilb@suse.de>
Tue, 11 Dec 2012 02:35:54 +0000 (13:35 +1100)
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>
drivers/md/md.c

index 89dbd444517e916176baa02a419f47f056e845c8..8b0e3d21f736f300b1e57897ba366c11a72c9401 100644 (file)
@@ -4752,6 +4752,8 @@ md_attr_store(struct kobject *kobj, struct attribute *attr,
        }
        mddev_get(mddev);
        spin_unlock(&all_mddevs_lock);
+       if (entry->store == new_dev_store)
+               flush_workqueue(md_misc_wq);
        rv = mddev_lock(mddev);
        if (!rv) {
                rv = entry->store(mddev, page, length);
@@ -6397,6 +6399,10 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
                goto abort;
        }
 
+       if (cmd == ADD_NEW_DISK)
+               /* need to ensure md_delayed_delete() has completed */
+               flush_workqueue(md_misc_wq);
+
        err = mddev_lock(mddev);
        if (err) {
                printk(KERN_INFO