aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2014-12-14 20:56:57 -0500
committerNeilBrown <neilb@suse.de>2015-02-03 16:35:52 -0500
commit5aa61f427e4979be733e4847b9199ff9cc48a47e (patch)
treed3e4fa9418f1134085cd9deef0877e7762076266
parent3be260cc18f850873cd32381158e28b0a9a391fd (diff)
md: split detach operation out from ->stop.
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>
-rw-r--r--drivers/md/linear.c1
-rw-r--r--drivers/md/md.c30
-rw-r--r--drivers/md/multipath.c2
-rw-r--r--drivers/md/raid0.c1
-rw-r--r--drivers/md/raid1.c18
-rw-r--r--drivers/md/raid10.c8
-rw-r--r--drivers/md/raid5.c1
7 files changed, 29 insertions, 32 deletions
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index b3e717adbc9b..c201555b9c6c 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -253,7 +253,6 @@ static int linear_stop (struct mddev *mddev)
253{ 253{
254 struct linear_conf *conf = mddev->private; 254 struct linear_conf *conf = mddev->private;
255 255
256 blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
257 kfree(conf); 256 kfree(conf);
258 mddev->private = NULL; 257 mddev->private = NULL;
259 258
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 9f0ff7187136..58f140bef999 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -72,6 +72,7 @@ static struct workqueue_struct *md_misc_wq;
72 72
73static int remove_and_add_spares(struct mddev *mddev, 73static int remove_and_add_spares(struct mddev *mddev,
74 struct md_rdev *this); 74 struct md_rdev *this);
75static void mddev_detach(struct mddev *mddev);
75 76
76/* 77/*
77 * Default number of read corrections we'll attempt on an rdev 78 * 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)
3372 3373
3373 /* Looks like we have a winner */ 3374 /* Looks like we have a winner */
3374 mddev_suspend(mddev); 3375 mddev_suspend(mddev);
3376 mddev_detach(mddev);
3375 mddev->pers->stop(mddev); 3377 mddev->pers->stop(mddev);
3376 3378
3377 if (mddev->pers->sync_request == NULL && 3379 if (mddev->pers->sync_request == NULL &&
@@ -4928,18 +4930,17 @@ int md_run(struct mddev *mddev)
4928 (unsigned long long)mddev->array_sectors / 2, 4930 (unsigned long long)mddev->array_sectors / 2,
4929 (unsigned long long)mddev->pers->size(mddev, 0, 0) / 2); 4931 (unsigned long long)mddev->pers->size(mddev, 0, 0) / 2);
4930 err = -EINVAL; 4932 err = -EINVAL;
4931 mddev->pers->stop(mddev);
4932 } 4933 }
4933 if (err == 0 && mddev->pers->sync_request && 4934 if (err == 0 && mddev->pers->sync_request &&
4934 (mddev->bitmap_info.file || mddev->bitmap_info.offset)) { 4935 (mddev->bitmap_info.file || mddev->bitmap_info.offset)) {
4935 err = bitmap_create(mddev); 4936 err = bitmap_create(mddev);
4936 if (err) { 4937 if (err)
4937 printk(KERN_ERR "%s: failed to create bitmap (%d)\n", 4938 printk(KERN_ERR "%s: failed to create bitmap (%d)\n",
4938 mdname(mddev), err); 4939 mdname(mddev), err);
4939 mddev->pers->stop(mddev);
4940 }
4941 } 4940 }
4942 if (err) { 4941 if (err) {
4942 mddev_detach(mddev);
4943 mddev->pers->stop(mddev);
4943 module_put(mddev->pers->owner); 4944 module_put(mddev->pers->owner);
4944 mddev->pers = NULL; 4945 mddev->pers = NULL;
4945 bitmap_destroy(mddev); 4946 bitmap_destroy(mddev);
@@ -5112,9 +5113,30 @@ void md_stop_writes(struct mddev *mddev)
5112} 5113}
5113EXPORT_SYMBOL_GPL(md_stop_writes); 5114EXPORT_SYMBOL_GPL(md_stop_writes);
5114 5115
5116static void mddev_detach(struct mddev *mddev)
5117{
5118 struct bitmap *bitmap = mddev->bitmap;
5119 /* wait for behind writes to complete */
5120 if (bitmap && atomic_read(&bitmap->behind_writes) > 0) {
5121 printk(KERN_INFO "md:%s: behind writes in progress - waiting to stop.\n",
5122 mdname(mddev));
5123 /* need to kick something here to make sure I/O goes? */
5124 wait_event(bitmap->behind_wait,
5125 atomic_read(&bitmap->behind_writes) == 0);
5126 }
5127 if (mddev->pers->quiesce) {
5128 mddev->pers->quiesce(mddev, 1);
5129 mddev->pers->quiesce(mddev, 0);
5130 }
5131 md_unregister_thread(&mddev->thread);
5132 if (mddev->queue)
5133 blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
5134}
5135
5115static void __md_stop(struct mddev *mddev) 5136static void __md_stop(struct mddev *mddev)
5116{ 5137{
5117 mddev->ready = 0; 5138 mddev->ready = 0;
5139 mddev_detach(mddev);
5118 mddev->pers->stop(mddev); 5140 mddev->pers->stop(mddev);
5119 if (mddev->pers->sync_request && mddev->to_remove == NULL) 5141 if (mddev->pers->sync_request && mddev->to_remove == NULL)
5120 mddev->to_remove = &md_redundancy_group; 5142 mddev->to_remove = &md_redundancy_group;
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index fedb1b31877d..9fe34453835b 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -504,8 +504,6 @@ static int multipath_stop (struct mddev *mddev)
504{ 504{
505 struct mpconf *conf = mddev->private; 505 struct mpconf *conf = mddev->private;
506 506
507 md_unregister_thread(&mddev->thread);
508 blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
509 mempool_destroy(conf->pool); 507 mempool_destroy(conf->pool);
510 kfree(conf->multipaths); 508 kfree(conf->multipaths);
511 kfree(conf); 509 kfree(conf);
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 3770c9675b17..01dfca94b663 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -477,7 +477,6 @@ static int raid0_stop(struct mddev *mddev)
477{ 477{
478 struct r0conf *conf = mddev->private; 478 struct r0conf *conf = mddev->private;
479 479
480 blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
481 kfree(conf->strip_zone); 480 kfree(conf->strip_zone);
482 kfree(conf->devlist); 481 kfree(conf->devlist);
483 kfree(conf); 482 kfree(conf);
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 45c512a4b75d..fccea0b39808 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -2954,29 +2954,17 @@ static int run(struct mddev *mddev)
2954 } 2954 }
2955 2955
2956 ret = md_integrity_register(mddev); 2956 ret = md_integrity_register(mddev);
2957 if (ret) 2957 if (ret) {
2958 md_unregister_thread(&mddev->thread);
2958 stop(mddev); 2959 stop(mddev);
2960 }
2959 return ret; 2961 return ret;
2960} 2962}
2961 2963
2962static int stop(struct mddev *mddev) 2964static int stop(struct mddev *mddev)
2963{ 2965{
2964 struct r1conf *conf = mddev->private; 2966 struct r1conf *conf = mddev->private;
2965 struct bitmap *bitmap = mddev->bitmap;
2966
2967 /* wait for behind writes to complete */
2968 if (bitmap && atomic_read(&bitmap->behind_writes) > 0) {
2969 printk(KERN_INFO "md/raid1:%s: behind writes in progress - waiting to stop.\n",
2970 mdname(mddev));
2971 /* need to kick something here to make sure I/O goes? */
2972 wait_event(bitmap->behind_wait,
2973 atomic_read(&bitmap->behind_writes) == 0);
2974 }
2975
2976 freeze_array(conf, 0);
2977 unfreeze_array(conf);
2978 2967
2979 md_unregister_thread(&mddev->thread);
2980 if (conf->r1bio_pool) 2968 if (conf->r1bio_pool)
2981 mempool_destroy(conf->r1bio_pool); 2969 mempool_destroy(conf->r1bio_pool);
2982 kfree(conf->mirrors); 2970 kfree(conf->mirrors);
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 407c81a820f4..654fdae906aa 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -3802,14 +3802,6 @@ static int stop(struct mddev *mddev)
3802{ 3802{
3803 struct r10conf *conf = mddev->private; 3803 struct r10conf *conf = mddev->private;
3804 3804
3805 raise_barrier(conf, 0);
3806 lower_barrier(conf);
3807
3808 md_unregister_thread(&mddev->thread);
3809 if (mddev->queue)
3810 /* the unplug fn references 'conf'*/
3811 blk_sync_queue(mddev->queue);
3812
3813 if (conf->r10bio_pool) 3805 if (conf->r10bio_pool)
3814 mempool_destroy(conf->r10bio_pool); 3806 mempool_destroy(conf->r10bio_pool);
3815 safe_put_page(conf->tmppage); 3807 safe_put_page(conf->tmppage);
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 2d4a2cc85eb2..482526077647 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -6317,7 +6317,6 @@ static int stop(struct mddev *mddev)
6317{ 6317{
6318 struct r5conf *conf = mddev->private; 6318 struct r5conf *conf = mddev->private;
6319 6319
6320 md_unregister_thread(&mddev->thread);
6321 free_conf(conf); 6320 free_conf(conf);
6322 mddev->private = NULL; 6321 mddev->private = NULL;
6323 mddev->to_remove = &raid5_attrs_group; 6322 mddev->to_remove = &raid5_attrs_group;