md: split detach operation out from ->stop.
authorNeilBrown <neilb@suse.de>
Mon, 15 Dec 2014 01:56:57 +0000 (12:56 +1100)
committerNeilBrown <neilb@suse.de>
Tue, 3 Feb 2015 21:35:52 +0000 (08:35 +1100)
Each md personality has a 'stop' operation which does two
things:
 1/ it finalizes some aspects of the array to ensure nothing
    is accessing the ->private data
 2/ it frees the ->private data.

All the steps in '1' can apply to all arrays and so can be
performed in common code.

This is useful as in the case where we change the personality which
manages an array (in level_store()), it would be helpful to do
step 1 early, and step 2 later.

So split the 'step 1' functionality out into a new mddev_detach().

Signed-off-by: NeilBrown <neilb@suse.de>
drivers/md/linear.c
drivers/md/md.c
drivers/md/multipath.c
drivers/md/raid0.c
drivers/md/raid1.c
drivers/md/raid10.c
drivers/md/raid5.c

index b3e717adbc9b480ad9bf69e2142ce44b545f3bc7..c201555b9c6c5575aede84c56929bd0c99e837a1 100644 (file)
@@ -253,7 +253,6 @@ static int linear_stop (struct mddev *mddev)
 {
        struct linear_conf *conf = mddev->private;
 
-       blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
        kfree(conf);
        mddev->private = NULL;
 
index 9f0ff718713622f13ed3af9a94ddd5c7d9bf747d..58f140bef99933b0da4a131edae3377b5da72018 100644 (file)
@@ -72,6 +72,7 @@ static struct workqueue_struct *md_misc_wq;
 
 static int remove_and_add_spares(struct mddev *mddev,
                                 struct md_rdev *this);
+static void mddev_detach(struct mddev *mddev);
 
 /*
  * Default number of read corrections we'll attempt on an rdev
@@ -3372,6 +3373,7 @@ level_store(struct mddev *mddev, const char *buf, size_t len)
 
        /* Looks like we have a winner */
        mddev_suspend(mddev);
+       mddev_detach(mddev);
        mddev->pers->stop(mddev);
 
        if (mddev->pers->sync_request == NULL &&
@@ -4928,18 +4930,17 @@ int md_run(struct mddev *mddev)
                       (unsigned long long)mddev->array_sectors / 2,
                       (unsigned long long)mddev->pers->size(mddev, 0, 0) / 2);
                err = -EINVAL;
-               mddev->pers->stop(mddev);
        }
        if (err == 0 && mddev->pers->sync_request &&
            (mddev->bitmap_info.file || mddev->bitmap_info.offset)) {
                err = bitmap_create(mddev);
-               if (err) {
+               if (err)
                        printk(KERN_ERR "%s: failed to create bitmap (%d)\n",
                               mdname(mddev), err);
-                       mddev->pers->stop(mddev);
-               }
        }
        if (err) {
+               mddev_detach(mddev);
+               mddev->pers->stop(mddev);
                module_put(mddev->pers->owner);
                mddev->pers = NULL;
                bitmap_destroy(mddev);
@@ -5112,9 +5113,30 @@ void md_stop_writes(struct mddev *mddev)
 }
 EXPORT_SYMBOL_GPL(md_stop_writes);
 
+static void mddev_detach(struct mddev *mddev)
+{
+       struct bitmap *bitmap = mddev->bitmap;
+       /* wait for behind writes to complete */
+       if (bitmap && atomic_read(&bitmap->behind_writes) > 0) {
+               printk(KERN_INFO "md:%s: behind writes in progress - waiting to stop.\n",
+                      mdname(mddev));
+               /* need to kick something here to make sure I/O goes? */
+               wait_event(bitmap->behind_wait,
+                          atomic_read(&bitmap->behind_writes) == 0);
+       }
+       if (mddev->pers->quiesce) {
+               mddev->pers->quiesce(mddev, 1);
+               mddev->pers->quiesce(mddev, 0);
+       }
+       md_unregister_thread(&mddev->thread);
+       if (mddev->queue)
+               blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
+}
+
 static void __md_stop(struct mddev *mddev)
 {
        mddev->ready = 0;
+       mddev_detach(mddev);
        mddev->pers->stop(mddev);
        if (mddev->pers->sync_request && mddev->to_remove == NULL)
                mddev->to_remove = &md_redundancy_group;
index fedb1b31877db4c72373d2c2137fdf2051350744..9fe34453835b1b06056bbb731becf858b528e8dd 100644 (file)
@@ -504,8 +504,6 @@ static int multipath_stop (struct mddev *mddev)
 {
        struct mpconf *conf = mddev->private;
 
-       md_unregister_thread(&mddev->thread);
-       blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
        mempool_destroy(conf->pool);
        kfree(conf->multipaths);
        kfree(conf);
index 3770c9675b1748b2b2db5a434144fcea1a096952..01dfca94b66343edaffe3ecb96a562d9fa4e742b 100644 (file)
@@ -477,7 +477,6 @@ static int raid0_stop(struct mddev *mddev)
 {
        struct r0conf *conf = mddev->private;
 
-       blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
        kfree(conf->strip_zone);
        kfree(conf->devlist);
        kfree(conf);
index 45c512a4b75d8e56b73cd4a24d25af6053e3459e..fccea0b39808592c99f524af0b37b0ce66e4bd6d 100644 (file)
@@ -2954,29 +2954,17 @@ static int run(struct mddev *mddev)
        }
 
        ret =  md_integrity_register(mddev);
-       if (ret)
+       if (ret) {
+               md_unregister_thread(&mddev->thread);
                stop(mddev);
+       }
        return ret;
 }
 
 static int stop(struct mddev *mddev)
 {
        struct r1conf *conf = mddev->private;
-       struct bitmap *bitmap = mddev->bitmap;
-
-       /* wait for behind writes to complete */
-       if (bitmap && atomic_read(&bitmap->behind_writes) > 0) {
-               printk(KERN_INFO "md/raid1:%s: behind writes in progress - waiting to stop.\n",
-                      mdname(mddev));
-               /* need to kick something here to make sure I/O goes? */
-               wait_event(bitmap->behind_wait,
-                          atomic_read(&bitmap->behind_writes) == 0);
-       }
-
-       freeze_array(conf, 0);
-       unfreeze_array(conf);
 
-       md_unregister_thread(&mddev->thread);
        if (conf->r1bio_pool)
                mempool_destroy(conf->r1bio_pool);
        kfree(conf->mirrors);
index 407c81a820f4b38865f24e3097f991d55ca0647f..654fdae906aa20c3b12431d2fe741724839c7299 100644 (file)
@@ -3802,14 +3802,6 @@ static int stop(struct mddev *mddev)
 {
        struct r10conf *conf = mddev->private;
 
-       raise_barrier(conf, 0);
-       lower_barrier(conf);
-
-       md_unregister_thread(&mddev->thread);
-       if (mddev->queue)
-               /* the unplug fn references 'conf'*/
-               blk_sync_queue(mddev->queue);
-
        if (conf->r10bio_pool)
                mempool_destroy(conf->r10bio_pool);
        safe_put_page(conf->tmppage);
index 2d4a2cc85eb2e62a891d2f35d90e0c9e3c7cf468..48252607764777c128f06552ea97f7270af3bce7 100644 (file)
@@ -6317,7 +6317,6 @@ static int stop(struct mddev *mddev)
 {
        struct r5conf *conf = mddev->private;
 
-       md_unregister_thread(&mddev->thread);
        free_conf(conf);
        mddev->private = NULL;
        mddev->to_remove = &raid5_attrs_group;