diff options
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 30 |
1 files changed, 26 insertions, 4 deletions
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 | ||
73 | static int remove_and_add_spares(struct mddev *mddev, | 73 | static int remove_and_add_spares(struct mddev *mddev, |
74 | struct md_rdev *this); | 74 | struct md_rdev *this); |
75 | static 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 | } |
5113 | EXPORT_SYMBOL_GPL(md_stop_writes); | 5114 | EXPORT_SYMBOL_GPL(md_stop_writes); |
5114 | 5115 | ||
5116 | static 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 | |||
5115 | static void __md_stop(struct mddev *mddev) | 5136 | static 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; |