diff options
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 37 |
1 files changed, 24 insertions, 13 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index a4c219e3c859..d5ab4493c8be 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -2931,6 +2931,7 @@ offset_store(struct md_rdev *rdev, const char *buf, size_t len) | |||
2931 | * can be sane */ | 2931 | * can be sane */ |
2932 | return -EBUSY; | 2932 | return -EBUSY; |
2933 | rdev->data_offset = offset; | 2933 | rdev->data_offset = offset; |
2934 | rdev->new_data_offset = offset; | ||
2934 | return len; | 2935 | return len; |
2935 | } | 2936 | } |
2936 | 2937 | ||
@@ -3926,8 +3927,8 @@ array_state_show(struct mddev *mddev, char *page) | |||
3926 | return sprintf(page, "%s\n", array_states[st]); | 3927 | return sprintf(page, "%s\n", array_states[st]); |
3927 | } | 3928 | } |
3928 | 3929 | ||
3929 | 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); |
3930 | static int md_set_readonly(struct mddev * mddev, int is_open); | 3931 | static int md_set_readonly(struct mddev * mddev, struct block_device *bdev); |
3931 | static int do_md_run(struct mddev * mddev); | 3932 | static int do_md_run(struct mddev * mddev); |
3932 | static int restart_array(struct mddev *mddev); | 3933 | static int restart_array(struct mddev *mddev); |
3933 | 3934 | ||
@@ -3943,14 +3944,14 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len) | |||
3943 | /* stopping an active array */ | 3944 | /* stopping an active array */ |
3944 | if (atomic_read(&mddev->openers) > 0) | 3945 | if (atomic_read(&mddev->openers) > 0) |
3945 | return -EBUSY; | 3946 | return -EBUSY; |
3946 | err = do_md_stop(mddev, 0, 0); | 3947 | err = do_md_stop(mddev, 0, NULL); |
3947 | break; | 3948 | break; |
3948 | case inactive: | 3949 | case inactive: |
3949 | /* stopping an active array */ | 3950 | /* stopping an active array */ |
3950 | if (mddev->pers) { | 3951 | if (mddev->pers) { |
3951 | if (atomic_read(&mddev->openers) > 0) | 3952 | if (atomic_read(&mddev->openers) > 0) |
3952 | return -EBUSY; | 3953 | return -EBUSY; |
3953 | err = do_md_stop(mddev, 2, 0); | 3954 | err = do_md_stop(mddev, 2, NULL); |
3954 | } else | 3955 | } else |
3955 | err = 0; /* already inactive */ | 3956 | err = 0; /* already inactive */ |
3956 | break; | 3957 | break; |
@@ -3958,7 +3959,7 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len) | |||
3958 | break; /* not supported yet */ | 3959 | break; /* not supported yet */ |
3959 | case readonly: | 3960 | case readonly: |
3960 | if (mddev->pers) | 3961 | if (mddev->pers) |
3961 | err = md_set_readonly(mddev, 0); | 3962 | err = md_set_readonly(mddev, NULL); |
3962 | else { | 3963 | else { |
3963 | mddev->ro = 1; | 3964 | mddev->ro = 1; |
3964 | set_disk_ro(mddev->gendisk, 1); | 3965 | set_disk_ro(mddev->gendisk, 1); |
@@ -3968,7 +3969,7 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len) | |||
3968 | case read_auto: | 3969 | case read_auto: |
3969 | if (mddev->pers) { | 3970 | if (mddev->pers) { |
3970 | if (mddev->ro == 0) | 3971 | if (mddev->ro == 0) |
3971 | err = md_set_readonly(mddev, 0); | 3972 | err = md_set_readonly(mddev, NULL); |
3972 | else if (mddev->ro == 1) | 3973 | else if (mddev->ro == 1) |
3973 | err = restart_array(mddev); | 3974 | err = restart_array(mddev); |
3974 | if (err == 0) { | 3975 | if (err == 0) { |
@@ -5351,15 +5352,17 @@ void md_stop(struct mddev *mddev) | |||
5351 | } | 5352 | } |
5352 | EXPORT_SYMBOL_GPL(md_stop); | 5353 | EXPORT_SYMBOL_GPL(md_stop); |
5353 | 5354 | ||
5354 | static int md_set_readonly(struct mddev *mddev, int is_open) | 5355 | static int md_set_readonly(struct mddev *mddev, struct block_device *bdev) |
5355 | { | 5356 | { |
5356 | int err = 0; | 5357 | int err = 0; |
5357 | mutex_lock(&mddev->open_mutex); | 5358 | mutex_lock(&mddev->open_mutex); |
5358 | if (atomic_read(&mddev->openers) > is_open) { | 5359 | if (atomic_read(&mddev->openers) > !!bdev) { |
5359 | printk("md: %s still in use.\n",mdname(mddev)); | 5360 | printk("md: %s still in use.\n",mdname(mddev)); |
5360 | err = -EBUSY; | 5361 | err = -EBUSY; |
5361 | goto out; | 5362 | goto out; |
5362 | } | 5363 | } |
5364 | if (bdev) | ||
5365 | sync_blockdev(bdev); | ||
5363 | if (mddev->pers) { | 5366 | if (mddev->pers) { |
5364 | __md_stop_writes(mddev); | 5367 | __md_stop_writes(mddev); |
5365 | 5368 | ||
@@ -5381,18 +5384,26 @@ out: | |||
5381 | * 0 - completely stop and dis-assemble array | 5384 | * 0 - completely stop and dis-assemble array |
5382 | * 2 - stop but do not disassemble array | 5385 | * 2 - stop but do not disassemble array |
5383 | */ | 5386 | */ |
5384 | 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) | ||
5385 | { | 5389 | { |
5386 | struct gendisk *disk = mddev->gendisk; | 5390 | struct gendisk *disk = mddev->gendisk; |
5387 | struct md_rdev *rdev; | 5391 | struct md_rdev *rdev; |
5388 | 5392 | ||
5389 | mutex_lock(&mddev->open_mutex); | 5393 | mutex_lock(&mddev->open_mutex); |
5390 | if (atomic_read(&mddev->openers) > is_open || | 5394 | if (atomic_read(&mddev->openers) > !!bdev || |
5391 | mddev->sysfs_active) { | 5395 | mddev->sysfs_active) { |
5392 | printk("md: %s still in use.\n",mdname(mddev)); | 5396 | printk("md: %s still in use.\n",mdname(mddev)); |
5393 | mutex_unlock(&mddev->open_mutex); | 5397 | mutex_unlock(&mddev->open_mutex); |
5394 | return -EBUSY; | 5398 | return -EBUSY; |
5395 | } | 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); | ||
5396 | 5407 | ||
5397 | if (mddev->pers) { | 5408 | if (mddev->pers) { |
5398 | if (mddev->ro) | 5409 | if (mddev->ro) |
@@ -5466,7 +5477,7 @@ static void autorun_array(struct mddev *mddev) | |||
5466 | err = do_md_run(mddev); | 5477 | err = do_md_run(mddev); |
5467 | if (err) { | 5478 | if (err) { |
5468 | printk(KERN_WARNING "md: do_md_run() returned %d\n", err); | 5479 | printk(KERN_WARNING "md: do_md_run() returned %d\n", err); |
5469 | do_md_stop(mddev, 0, 0); | 5480 | do_md_stop(mddev, 0, NULL); |
5470 | } | 5481 | } |
5471 | } | 5482 | } |
5472 | 5483 | ||
@@ -6481,11 +6492,11 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, | |||
6481 | goto done_unlock; | 6492 | goto done_unlock; |
6482 | 6493 | ||
6483 | case STOP_ARRAY: | 6494 | case STOP_ARRAY: |
6484 | err = do_md_stop(mddev, 0, 1); | 6495 | err = do_md_stop(mddev, 0, bdev); |
6485 | goto done_unlock; | 6496 | goto done_unlock; |
6486 | 6497 | ||
6487 | case STOP_ARRAY_RO: | 6498 | case STOP_ARRAY_RO: |
6488 | err = md_set_readonly(mddev, 1); | 6499 | err = md_set_readonly(mddev, bdev); |
6489 | goto done_unlock; | 6500 | goto done_unlock; |
6490 | 6501 | ||
6491 | case BLKROSET: | 6502 | case BLKROSET: |