aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/md/md.c36
1 files changed, 23 insertions, 13 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 0c1fe4cbce6b..d5ab4493c8be 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -3927,8 +3927,8 @@ array_state_show(struct mddev *mddev, char *page)
3927 return sprintf(page, "%s\n", array_states[st]); 3927 return sprintf(page, "%s\n", array_states[st]);
3928} 3928}
3929 3929
3930static int do_md_stop(struct mddev * mddev, int ro, int is_open); 3930static int do_md_stop(struct mddev * mddev, int ro, struct block_device *bdev);
3931static int md_set_readonly(struct mddev * mddev, int is_open); 3931static int md_set_readonly(struct mddev * mddev, struct block_device *bdev);
3932static int do_md_run(struct mddev * mddev); 3932static int do_md_run(struct mddev * mddev);
3933static int restart_array(struct mddev *mddev); 3933static int restart_array(struct mddev *mddev);
3934 3934
@@ -3944,14 +3944,14 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
3944 /* stopping an active array */ 3944 /* stopping an active array */
3945 if (atomic_read(&mddev->openers) > 0) 3945 if (atomic_read(&mddev->openers) > 0)
3946 return -EBUSY; 3946 return -EBUSY;
3947 err = do_md_stop(mddev, 0, 0); 3947 err = do_md_stop(mddev, 0, NULL);
3948 break; 3948 break;
3949 case inactive: 3949 case inactive:
3950 /* stopping an active array */ 3950 /* stopping an active array */
3951 if (mddev->pers) { 3951 if (mddev->pers) {
3952 if (atomic_read(&mddev->openers) > 0) 3952 if (atomic_read(&mddev->openers) > 0)
3953 return -EBUSY; 3953 return -EBUSY;
3954 err = do_md_stop(mddev, 2, 0); 3954 err = do_md_stop(mddev, 2, NULL);
3955 } else 3955 } else
3956 err = 0; /* already inactive */ 3956 err = 0; /* already inactive */
3957 break; 3957 break;
@@ -3959,7 +3959,7 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
3959 break; /* not supported yet */ 3959 break; /* not supported yet */
3960 case readonly: 3960 case readonly:
3961 if (mddev->pers) 3961 if (mddev->pers)
3962 err = md_set_readonly(mddev, 0); 3962 err = md_set_readonly(mddev, NULL);
3963 else { 3963 else {
3964 mddev->ro = 1; 3964 mddev->ro = 1;
3965 set_disk_ro(mddev->gendisk, 1); 3965 set_disk_ro(mddev->gendisk, 1);
@@ -3969,7 +3969,7 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len)
3969 case read_auto: 3969 case read_auto:
3970 if (mddev->pers) { 3970 if (mddev->pers) {
3971 if (mddev->ro == 0) 3971 if (mddev->ro == 0)
3972 err = md_set_readonly(mddev, 0); 3972 err = md_set_readonly(mddev, NULL);
3973 else if (mddev->ro == 1) 3973 else if (mddev->ro == 1)
3974 err = restart_array(mddev); 3974 err = restart_array(mddev);
3975 if (err == 0) { 3975 if (err == 0) {
@@ -5352,15 +5352,17 @@ void md_stop(struct mddev *mddev)
5352} 5352}
5353EXPORT_SYMBOL_GPL(md_stop); 5353EXPORT_SYMBOL_GPL(md_stop);
5354 5354
5355static int md_set_readonly(struct mddev *mddev, int is_open) 5355static int md_set_readonly(struct mddev *mddev, struct block_device *bdev)
5356{ 5356{
5357 int err = 0; 5357 int err = 0;
5358 mutex_lock(&mddev->open_mutex); 5358 mutex_lock(&mddev->open_mutex);
5359 if (atomic_read(&mddev->openers) > is_open) { 5359 if (atomic_read(&mddev->openers) > !!bdev) {
5360 printk("md: %s still in use.\n",mdname(mddev)); 5360 printk("md: %s still in use.\n",mdname(mddev));
5361 err = -EBUSY; 5361 err = -EBUSY;
5362 goto out; 5362 goto out;
5363 } 5363 }
5364 if (bdev)
5365 sync_blockdev(bdev);
5364 if (mddev->pers) { 5366 if (mddev->pers) {
5365 __md_stop_writes(mddev); 5367 __md_stop_writes(mddev);
5366 5368
@@ -5382,18 +5384,26 @@ out:
5382 * 0 - completely stop and dis-assemble array 5384 * 0 - completely stop and dis-assemble array
5383 * 2 - stop but do not disassemble array 5385 * 2 - stop but do not disassemble array
5384 */ 5386 */
5385static int do_md_stop(struct mddev * mddev, int mode, int is_open) 5387static int do_md_stop(struct mddev * mddev, int mode,
5388 struct block_device *bdev)
5386{ 5389{
5387 struct gendisk *disk = mddev->gendisk; 5390 struct gendisk *disk = mddev->gendisk;
5388 struct md_rdev *rdev; 5391 struct md_rdev *rdev;
5389 5392
5390 mutex_lock(&mddev->open_mutex); 5393 mutex_lock(&mddev->open_mutex);
5391 if (atomic_read(&mddev->openers) > is_open || 5394 if (atomic_read(&mddev->openers) > !!bdev ||
5392 mddev->sysfs_active) { 5395 mddev->sysfs_active) {
5393 printk("md: %s still in use.\n",mdname(mddev)); 5396 printk("md: %s still in use.\n",mdname(mddev));
5394 mutex_unlock(&mddev->open_mutex); 5397 mutex_unlock(&mddev->open_mutex);
5395 return -EBUSY; 5398 return -EBUSY;
5396 } 5399 }
5400 if (bdev)
5401 /* It is possible IO was issued on some other
5402 * open file which was closed before we took ->open_mutex.
5403 * As that was not the last close __blkdev_put will not
5404 * have called sync_blockdev, so we must.
5405 */
5406 sync_blockdev(bdev);
5397 5407
5398 if (mddev->pers) { 5408 if (mddev->pers) {
5399 if (mddev->ro) 5409 if (mddev->ro)
@@ -5467,7 +5477,7 @@ static void autorun_array(struct mddev *mddev)
5467 err = do_md_run(mddev); 5477 err = do_md_run(mddev);
5468 if (err) { 5478 if (err) {
5469 printk(KERN_WARNING "md: do_md_run() returned %d\n", err); 5479 printk(KERN_WARNING "md: do_md_run() returned %d\n", err);
5470 do_md_stop(mddev, 0, 0); 5480 do_md_stop(mddev, 0, NULL);
5471 } 5481 }
5472} 5482}
5473 5483
@@ -6482,11 +6492,11 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode,
6482 goto done_unlock; 6492 goto done_unlock;
6483 6493
6484 case STOP_ARRAY: 6494 case STOP_ARRAY:
6485 err = do_md_stop(mddev, 0, 1); 6495 err = do_md_stop(mddev, 0, bdev);
6486 goto done_unlock; 6496 goto done_unlock;
6487 6497
6488 case STOP_ARRAY_RO: 6498 case STOP_ARRAY_RO:
6489 err = md_set_readonly(mddev, 1); 6499 err = md_set_readonly(mddev, bdev);
6490 goto done_unlock; 6500 goto done_unlock;
6491 6501
6492 case BLKROSET: 6502 case BLKROSET: