aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/md.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r--drivers/md/md.c30
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
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;