diff options
| -rw-r--r-- | drivers/md/md.c | 36 |
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 | ||
| 3930 | static int do_md_stop(struct mddev * mddev, int ro, int is_open); | 3930 | static int do_md_stop(struct mddev * mddev, int ro, struct block_device *bdev); |
| 3931 | static int md_set_readonly(struct mddev * mddev, int is_open); | 3931 | static int md_set_readonly(struct mddev * mddev, struct block_device *bdev); |
| 3932 | static int do_md_run(struct mddev * mddev); | 3932 | static int do_md_run(struct mddev * mddev); |
| 3933 | static int restart_array(struct mddev *mddev); | 3933 | static 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 | } |
| 5353 | EXPORT_SYMBOL_GPL(md_stop); | 5353 | EXPORT_SYMBOL_GPL(md_stop); |
| 5354 | 5354 | ||
| 5355 | static int md_set_readonly(struct mddev *mddev, int is_open) | 5355 | static 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 | */ |
| 5385 | static int do_md_stop(struct mddev * mddev, int mode, int is_open) | 5387 | static 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: |
