diff options
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 121 |
1 files changed, 42 insertions, 79 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index 1c2f9048e1ae..3f6203a4c7ea 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -498,61 +498,13 @@ void md_flush_request(struct mddev *mddev, struct bio *bio) | |||
498 | } | 498 | } |
499 | EXPORT_SYMBOL(md_flush_request); | 499 | EXPORT_SYMBOL(md_flush_request); |
500 | 500 | ||
501 | /* Support for plugging. | 501 | void md_unplug(struct blk_plug_cb *cb, bool from_schedule) |
502 | * This mirrors the plugging support in request_queue, but does not | ||
503 | * require having a whole queue or request structures. | ||
504 | * We allocate an md_plug_cb for each md device and each thread it gets | ||
505 | * plugged on. This links tot the private plug_handle structure in the | ||
506 | * personality data where we keep a count of the number of outstanding | ||
507 | * plugs so other code can see if a plug is active. | ||
508 | */ | ||
509 | struct md_plug_cb { | ||
510 | struct blk_plug_cb cb; | ||
511 | struct mddev *mddev; | ||
512 | }; | ||
513 | |||
514 | static void plugger_unplug(struct blk_plug_cb *cb) | ||
515 | { | 502 | { |
516 | struct md_plug_cb *mdcb = container_of(cb, struct md_plug_cb, cb); | 503 | struct mddev *mddev = cb->data; |
517 | if (atomic_dec_and_test(&mdcb->mddev->plug_cnt)) | 504 | md_wakeup_thread(mddev->thread); |
518 | md_wakeup_thread(mdcb->mddev->thread); | 505 | kfree(cb); |
519 | kfree(mdcb); | ||
520 | } | ||
521 | |||
522 | /* Check that an unplug wakeup will come shortly. | ||
523 | * If not, wakeup the md thread immediately | ||
524 | */ | ||
525 | int mddev_check_plugged(struct mddev *mddev) | ||
526 | { | ||
527 | struct blk_plug *plug = current->plug; | ||
528 | struct md_plug_cb *mdcb; | ||
529 | |||
530 | if (!plug) | ||
531 | return 0; | ||
532 | |||
533 | list_for_each_entry(mdcb, &plug->cb_list, cb.list) { | ||
534 | if (mdcb->cb.callback == plugger_unplug && | ||
535 | mdcb->mddev == mddev) { | ||
536 | /* Already on the list, move to top */ | ||
537 | if (mdcb != list_first_entry(&plug->cb_list, | ||
538 | struct md_plug_cb, | ||
539 | cb.list)) | ||
540 | list_move(&mdcb->cb.list, &plug->cb_list); | ||
541 | return 1; | ||
542 | } | ||
543 | } | ||
544 | /* Not currently on the callback list */ | ||
545 | mdcb = kmalloc(sizeof(*mdcb), GFP_ATOMIC); | ||
546 | if (!mdcb) | ||
547 | return 0; | ||
548 | |||
549 | mdcb->mddev = mddev; | ||
550 | mdcb->cb.callback = plugger_unplug; | ||
551 | atomic_inc(&mddev->plug_cnt); | ||
552 | list_add(&mdcb->cb.list, &plug->cb_list); | ||
553 | return 1; | ||
554 | } | 506 | } |
555 | EXPORT_SYMBOL_GPL(mddev_check_plugged); | 507 | EXPORT_SYMBOL(md_unplug); |
556 | 508 | ||
557 | static inline struct mddev *mddev_get(struct mddev *mddev) | 509 | static inline struct mddev *mddev_get(struct mddev *mddev) |
558 | { | 510 | { |
@@ -602,7 +554,6 @@ void mddev_init(struct mddev *mddev) | |||
602 | atomic_set(&mddev->active, 1); | 554 | atomic_set(&mddev->active, 1); |
603 | atomic_set(&mddev->openers, 0); | 555 | atomic_set(&mddev->openers, 0); |
604 | atomic_set(&mddev->active_io, 0); | 556 | atomic_set(&mddev->active_io, 0); |
605 | atomic_set(&mddev->plug_cnt, 0); | ||
606 | spin_lock_init(&mddev->write_lock); | 557 | spin_lock_init(&mddev->write_lock); |
607 | atomic_set(&mddev->flush_pending, 0); | 558 | atomic_set(&mddev->flush_pending, 0); |
608 | init_waitqueue_head(&mddev->sb_wait); | 559 | init_waitqueue_head(&mddev->sb_wait); |
@@ -1157,8 +1108,11 @@ static int super_90_load(struct md_rdev *rdev, struct md_rdev *refdev, int minor | |||
1157 | ret = 0; | 1108 | ret = 0; |
1158 | } | 1109 | } |
1159 | rdev->sectors = rdev->sb_start; | 1110 | rdev->sectors = rdev->sb_start; |
1160 | /* Limit to 4TB as metadata cannot record more than that */ | 1111 | /* Limit to 4TB as metadata cannot record more than that. |
1161 | if (rdev->sectors >= (2ULL << 32)) | 1112 | * (not needed for Linear and RAID0 as metadata doesn't |
1113 | * record this size) | ||
1114 | */ | ||
1115 | if (rdev->sectors >= (2ULL << 32) && sb->level >= 1) | ||
1162 | rdev->sectors = (2ULL << 32) - 2; | 1116 | rdev->sectors = (2ULL << 32) - 2; |
1163 | 1117 | ||
1164 | if (rdev->sectors < ((sector_t)sb->size) * 2 && sb->level >= 1) | 1118 | if (rdev->sectors < ((sector_t)sb->size) * 2 && sb->level >= 1) |
@@ -1449,7 +1403,7 @@ super_90_rdev_size_change(struct md_rdev *rdev, sector_t num_sectors) | |||
1449 | /* Limit to 4TB as metadata cannot record more than that. | 1403 | /* Limit to 4TB as metadata cannot record more than that. |
1450 | * 4TB == 2^32 KB, or 2*2^32 sectors. | 1404 | * 4TB == 2^32 KB, or 2*2^32 sectors. |
1451 | */ | 1405 | */ |
1452 | if (num_sectors >= (2ULL << 32)) | 1406 | if (num_sectors >= (2ULL << 32) && rdev->mddev->level >= 1) |
1453 | num_sectors = (2ULL << 32) - 2; | 1407 | num_sectors = (2ULL << 32) - 2; |
1454 | md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size, | 1408 | md_super_write(rdev->mddev, rdev, rdev->sb_start, rdev->sb_size, |
1455 | rdev->sb_page); | 1409 | rdev->sb_page); |
@@ -2931,6 +2885,7 @@ offset_store(struct md_rdev *rdev, const char *buf, size_t len) | |||
2931 | * can be sane */ | 2885 | * can be sane */ |
2932 | return -EBUSY; | 2886 | return -EBUSY; |
2933 | rdev->data_offset = offset; | 2887 | rdev->data_offset = offset; |
2888 | rdev->new_data_offset = offset; | ||
2934 | return len; | 2889 | return len; |
2935 | } | 2890 | } |
2936 | 2891 | ||
@@ -3926,8 +3881,8 @@ array_state_show(struct mddev *mddev, char *page) | |||
3926 | return sprintf(page, "%s\n", array_states[st]); | 3881 | return sprintf(page, "%s\n", array_states[st]); |
3927 | } | 3882 | } |
3928 | 3883 | ||
3929 | static int do_md_stop(struct mddev * mddev, int ro, int is_open); | 3884 | 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); | 3885 | static int md_set_readonly(struct mddev * mddev, struct block_device *bdev); |
3931 | static int do_md_run(struct mddev * mddev); | 3886 | static int do_md_run(struct mddev * mddev); |
3932 | static int restart_array(struct mddev *mddev); | 3887 | static int restart_array(struct mddev *mddev); |
3933 | 3888 | ||
@@ -3941,24 +3896,20 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len) | |||
3941 | break; | 3896 | break; |
3942 | case clear: | 3897 | case clear: |
3943 | /* stopping an active array */ | 3898 | /* stopping an active array */ |
3944 | if (atomic_read(&mddev->openers) > 0) | 3899 | err = do_md_stop(mddev, 0, NULL); |
3945 | return -EBUSY; | ||
3946 | err = do_md_stop(mddev, 0, 0); | ||
3947 | break; | 3900 | break; |
3948 | case inactive: | 3901 | case inactive: |
3949 | /* stopping an active array */ | 3902 | /* stopping an active array */ |
3950 | if (mddev->pers) { | 3903 | if (mddev->pers) |
3951 | if (atomic_read(&mddev->openers) > 0) | 3904 | err = do_md_stop(mddev, 2, NULL); |
3952 | return -EBUSY; | 3905 | else |
3953 | err = do_md_stop(mddev, 2, 0); | ||
3954 | } else | ||
3955 | err = 0; /* already inactive */ | 3906 | err = 0; /* already inactive */ |
3956 | break; | 3907 | break; |
3957 | case suspended: | 3908 | case suspended: |
3958 | break; /* not supported yet */ | 3909 | break; /* not supported yet */ |
3959 | case readonly: | 3910 | case readonly: |
3960 | if (mddev->pers) | 3911 | if (mddev->pers) |
3961 | err = md_set_readonly(mddev, 0); | 3912 | err = md_set_readonly(mddev, NULL); |
3962 | else { | 3913 | else { |
3963 | mddev->ro = 1; | 3914 | mddev->ro = 1; |
3964 | set_disk_ro(mddev->gendisk, 1); | 3915 | set_disk_ro(mddev->gendisk, 1); |
@@ -3968,7 +3919,7 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len) | |||
3968 | case read_auto: | 3919 | case read_auto: |
3969 | if (mddev->pers) { | 3920 | if (mddev->pers) { |
3970 | if (mddev->ro == 0) | 3921 | if (mddev->ro == 0) |
3971 | err = md_set_readonly(mddev, 0); | 3922 | err = md_set_readonly(mddev, NULL); |
3972 | else if (mddev->ro == 1) | 3923 | else if (mddev->ro == 1) |
3973 | err = restart_array(mddev); | 3924 | err = restart_array(mddev); |
3974 | if (err == 0) { | 3925 | if (err == 0) { |
@@ -5351,15 +5302,17 @@ void md_stop(struct mddev *mddev) | |||
5351 | } | 5302 | } |
5352 | EXPORT_SYMBOL_GPL(md_stop); | 5303 | EXPORT_SYMBOL_GPL(md_stop); |
5353 | 5304 | ||
5354 | static int md_set_readonly(struct mddev *mddev, int is_open) | 5305 | static int md_set_readonly(struct mddev *mddev, struct block_device *bdev) |
5355 | { | 5306 | { |
5356 | int err = 0; | 5307 | int err = 0; |
5357 | mutex_lock(&mddev->open_mutex); | 5308 | mutex_lock(&mddev->open_mutex); |
5358 | if (atomic_read(&mddev->openers) > is_open) { | 5309 | if (atomic_read(&mddev->openers) > !!bdev) { |
5359 | printk("md: %s still in use.\n",mdname(mddev)); | 5310 | printk("md: %s still in use.\n",mdname(mddev)); |
5360 | err = -EBUSY; | 5311 | err = -EBUSY; |
5361 | goto out; | 5312 | goto out; |
5362 | } | 5313 | } |
5314 | if (bdev) | ||
5315 | sync_blockdev(bdev); | ||
5363 | if (mddev->pers) { | 5316 | if (mddev->pers) { |
5364 | __md_stop_writes(mddev); | 5317 | __md_stop_writes(mddev); |
5365 | 5318 | ||
@@ -5381,18 +5334,26 @@ out: | |||
5381 | * 0 - completely stop and dis-assemble array | 5334 | * 0 - completely stop and dis-assemble array |
5382 | * 2 - stop but do not disassemble array | 5335 | * 2 - stop but do not disassemble array |
5383 | */ | 5336 | */ |
5384 | static int do_md_stop(struct mddev * mddev, int mode, int is_open) | 5337 | static int do_md_stop(struct mddev * mddev, int mode, |
5338 | struct block_device *bdev) | ||
5385 | { | 5339 | { |
5386 | struct gendisk *disk = mddev->gendisk; | 5340 | struct gendisk *disk = mddev->gendisk; |
5387 | struct md_rdev *rdev; | 5341 | struct md_rdev *rdev; |
5388 | 5342 | ||
5389 | mutex_lock(&mddev->open_mutex); | 5343 | mutex_lock(&mddev->open_mutex); |
5390 | if (atomic_read(&mddev->openers) > is_open || | 5344 | if (atomic_read(&mddev->openers) > !!bdev || |
5391 | mddev->sysfs_active) { | 5345 | mddev->sysfs_active) { |
5392 | printk("md: %s still in use.\n",mdname(mddev)); | 5346 | printk("md: %s still in use.\n",mdname(mddev)); |
5393 | mutex_unlock(&mddev->open_mutex); | 5347 | mutex_unlock(&mddev->open_mutex); |
5394 | return -EBUSY; | 5348 | return -EBUSY; |
5395 | } | 5349 | } |
5350 | if (bdev) | ||
5351 | /* It is possible IO was issued on some other | ||
5352 | * open file which was closed before we took ->open_mutex. | ||
5353 | * As that was not the last close __blkdev_put will not | ||
5354 | * have called sync_blockdev, so we must. | ||
5355 | */ | ||
5356 | sync_blockdev(bdev); | ||
5396 | 5357 | ||
5397 | if (mddev->pers) { | 5358 | if (mddev->pers) { |
5398 | if (mddev->ro) | 5359 | if (mddev->ro) |
@@ -5466,7 +5427,7 @@ static void autorun_array(struct mddev *mddev) | |||
5466 | err = do_md_run(mddev); | 5427 | err = do_md_run(mddev); |
5467 | if (err) { | 5428 | if (err) { |
5468 | printk(KERN_WARNING "md: do_md_run() returned %d\n", err); | 5429 | printk(KERN_WARNING "md: do_md_run() returned %d\n", err); |
5469 | do_md_stop(mddev, 0, 0); | 5430 | do_md_stop(mddev, 0, NULL); |
5470 | } | 5431 | } |
5471 | } | 5432 | } |
5472 | 5433 | ||
@@ -5784,8 +5745,7 @@ static int add_new_disk(struct mddev * mddev, mdu_disk_info_t *info) | |||
5784 | super_types[mddev->major_version]. | 5745 | super_types[mddev->major_version]. |
5785 | validate_super(mddev, rdev); | 5746 | validate_super(mddev, rdev); |
5786 | if ((info->state & (1<<MD_DISK_SYNC)) && | 5747 | if ((info->state & (1<<MD_DISK_SYNC)) && |
5787 | (!test_bit(In_sync, &rdev->flags) || | 5748 | rdev->raid_disk != info->raid_disk) { |
5788 | rdev->raid_disk != info->raid_disk)) { | ||
5789 | /* This was a hot-add request, but events doesn't | 5749 | /* This was a hot-add request, but events doesn't |
5790 | * match, so reject it. | 5750 | * match, so reject it. |
5791 | */ | 5751 | */ |
@@ -6482,11 +6442,11 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, | |||
6482 | goto done_unlock; | 6442 | goto done_unlock; |
6483 | 6443 | ||
6484 | case STOP_ARRAY: | 6444 | case STOP_ARRAY: |
6485 | err = do_md_stop(mddev, 0, 1); | 6445 | err = do_md_stop(mddev, 0, bdev); |
6486 | goto done_unlock; | 6446 | goto done_unlock; |
6487 | 6447 | ||
6488 | case STOP_ARRAY_RO: | 6448 | case STOP_ARRAY_RO: |
6489 | err = md_set_readonly(mddev, 1); | 6449 | err = md_set_readonly(mddev, bdev); |
6490 | goto done_unlock; | 6450 | goto done_unlock; |
6491 | 6451 | ||
6492 | case BLKROSET: | 6452 | case BLKROSET: |
@@ -6751,7 +6711,7 @@ struct md_thread *md_register_thread(void (*run) (struct mddev *), struct mddev | |||
6751 | thread->tsk = kthread_run(md_thread, thread, | 6711 | thread->tsk = kthread_run(md_thread, thread, |
6752 | "%s_%s", | 6712 | "%s_%s", |
6753 | mdname(thread->mddev), | 6713 | mdname(thread->mddev), |
6754 | name ?: mddev->pers->name); | 6714 | name); |
6755 | if (IS_ERR(thread->tsk)) { | 6715 | if (IS_ERR(thread->tsk)) { |
6756 | kfree(thread); | 6716 | kfree(thread); |
6757 | return NULL; | 6717 | return NULL; |
@@ -7298,6 +7258,7 @@ void md_do_sync(struct mddev *mddev) | |||
7298 | int skipped = 0; | 7258 | int skipped = 0; |
7299 | struct md_rdev *rdev; | 7259 | struct md_rdev *rdev; |
7300 | char *desc; | 7260 | char *desc; |
7261 | struct blk_plug plug; | ||
7301 | 7262 | ||
7302 | /* just incase thread restarts... */ | 7263 | /* just incase thread restarts... */ |
7303 | if (test_bit(MD_RECOVERY_DONE, &mddev->recovery)) | 7264 | if (test_bit(MD_RECOVERY_DONE, &mddev->recovery)) |
@@ -7447,6 +7408,7 @@ void md_do_sync(struct mddev *mddev) | |||
7447 | } | 7408 | } |
7448 | mddev->curr_resync_completed = j; | 7409 | mddev->curr_resync_completed = j; |
7449 | 7410 | ||
7411 | blk_start_plug(&plug); | ||
7450 | while (j < max_sectors) { | 7412 | while (j < max_sectors) { |
7451 | sector_t sectors; | 7413 | sector_t sectors; |
7452 | 7414 | ||
@@ -7552,6 +7514,7 @@ void md_do_sync(struct mddev *mddev) | |||
7552 | * this also signals 'finished resyncing' to md_stop | 7514 | * this also signals 'finished resyncing' to md_stop |
7553 | */ | 7515 | */ |
7554 | out: | 7516 | out: |
7517 | blk_finish_plug(&plug); | ||
7555 | wait_event(mddev->recovery_wait, !atomic_read(&mddev->recovery_active)); | 7518 | wait_event(mddev->recovery_wait, !atomic_read(&mddev->recovery_active)); |
7556 | 7519 | ||
7557 | /* tell personality that we are finished */ | 7520 | /* tell personality that we are finished */ |