diff --git a/drivers/md/linear.c b/drivers/md/linear.c index b3e717adbc9b480ad9bf69e2142ce44b545f3bc7..c201555b9c6c5575aede84c56929bd0c99e837a1 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -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; diff --git a/drivers/md/md.c b/drivers/md/md.c index 9f0ff718713622f13ed3af9a94ddd5c7d9bf747d..58f140bef99933b0da4a131edae3377b5da72018 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -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; diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index fedb1b31877db4c72373d2c2137fdf2051350744..9fe34453835b1b06056bbb731becf858b528e8dd 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -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); diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 3770c9675b1748b2b2db5a434144fcea1a096952..01dfca94b66343edaffe3ecb96a562d9fa4e742b 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -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); diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 45c512a4b75d8e56b73cd4a24d25af6053e3459e..fccea0b39808592c99f524af0b37b0ce66e4bd6d 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -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); diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 407c81a820f4b38865f24e3097f991d55ca0647f..654fdae906aa20c3b12431d2fe741724839c7299 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -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); diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 2d4a2cc85eb2e62a891d2f35d90e0c9e3c7cf468..48252607764777c128f06552ea97f7270af3bce7 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -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;