diff options
Diffstat (limited to 'drivers/md/md.c')
-rw-r--r-- | drivers/md/md.c | 53 |
1 files changed, 48 insertions, 5 deletions
diff --git a/drivers/md/md.c b/drivers/md/md.c index bc67ab6844f0..254e44e44668 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -801,6 +801,9 @@ void md_super_write(struct mddev *mddev, struct md_rdev *rdev, | |||
801 | struct bio *bio; | 801 | struct bio *bio; |
802 | int ff = 0; | 802 | int ff = 0; |
803 | 803 | ||
804 | if (!page) | ||
805 | return; | ||
806 | |||
804 | if (test_bit(Faulty, &rdev->flags)) | 807 | if (test_bit(Faulty, &rdev->flags)) |
805 | return; | 808 | return; |
806 | 809 | ||
@@ -5452,6 +5455,7 @@ int md_run(struct mddev *mddev) | |||
5452 | * the only valid external interface is through the md | 5455 | * the only valid external interface is through the md |
5453 | * device. | 5456 | * device. |
5454 | */ | 5457 | */ |
5458 | mddev->has_superblocks = false; | ||
5455 | rdev_for_each(rdev, mddev) { | 5459 | rdev_for_each(rdev, mddev) { |
5456 | if (test_bit(Faulty, &rdev->flags)) | 5460 | if (test_bit(Faulty, &rdev->flags)) |
5457 | continue; | 5461 | continue; |
@@ -5465,6 +5469,9 @@ int md_run(struct mddev *mddev) | |||
5465 | set_disk_ro(mddev->gendisk, 1); | 5469 | set_disk_ro(mddev->gendisk, 1); |
5466 | } | 5470 | } |
5467 | 5471 | ||
5472 | if (rdev->sb_page) | ||
5473 | mddev->has_superblocks = true; | ||
5474 | |||
5468 | /* perform some consistency tests on the device. | 5475 | /* perform some consistency tests on the device. |
5469 | * We don't want the data to overlap the metadata, | 5476 | * We don't want the data to overlap the metadata, |
5470 | * Internal Bitmap issues have been handled elsewhere. | 5477 | * Internal Bitmap issues have been handled elsewhere. |
@@ -5497,8 +5504,10 @@ int md_run(struct mddev *mddev) | |||
5497 | } | 5504 | } |
5498 | if (mddev->sync_set == NULL) { | 5505 | if (mddev->sync_set == NULL) { |
5499 | mddev->sync_set = bioset_create(BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS); | 5506 | mddev->sync_set = bioset_create(BIO_POOL_SIZE, 0, BIOSET_NEED_BVECS); |
5500 | if (!mddev->sync_set) | 5507 | if (!mddev->sync_set) { |
5501 | return -ENOMEM; | 5508 | err = -ENOMEM; |
5509 | goto abort; | ||
5510 | } | ||
5502 | } | 5511 | } |
5503 | 5512 | ||
5504 | spin_lock(&pers_lock); | 5513 | spin_lock(&pers_lock); |
@@ -5511,7 +5520,8 @@ int md_run(struct mddev *mddev) | |||
5511 | else | 5520 | else |
5512 | pr_warn("md: personality for level %s is not loaded!\n", | 5521 | pr_warn("md: personality for level %s is not loaded!\n", |
5513 | mddev->clevel); | 5522 | mddev->clevel); |
5514 | return -EINVAL; | 5523 | err = -EINVAL; |
5524 | goto abort; | ||
5515 | } | 5525 | } |
5516 | spin_unlock(&pers_lock); | 5526 | spin_unlock(&pers_lock); |
5517 | if (mddev->level != pers->level) { | 5527 | if (mddev->level != pers->level) { |
@@ -5524,7 +5534,8 @@ int md_run(struct mddev *mddev) | |||
5524 | pers->start_reshape == NULL) { | 5534 | pers->start_reshape == NULL) { |
5525 | /* This personality cannot handle reshaping... */ | 5535 | /* This personality cannot handle reshaping... */ |
5526 | module_put(pers->owner); | 5536 | module_put(pers->owner); |
5527 | return -EINVAL; | 5537 | err = -EINVAL; |
5538 | goto abort; | ||
5528 | } | 5539 | } |
5529 | 5540 | ||
5530 | if (pers->sync_request) { | 5541 | if (pers->sync_request) { |
@@ -5593,7 +5604,7 @@ int md_run(struct mddev *mddev) | |||
5593 | mddev->private = NULL; | 5604 | mddev->private = NULL; |
5594 | module_put(pers->owner); | 5605 | module_put(pers->owner); |
5595 | bitmap_destroy(mddev); | 5606 | bitmap_destroy(mddev); |
5596 | return err; | 5607 | goto abort; |
5597 | } | 5608 | } |
5598 | if (mddev->queue) { | 5609 | if (mddev->queue) { |
5599 | bool nonrot = true; | 5610 | bool nonrot = true; |
@@ -5655,6 +5666,18 @@ int md_run(struct mddev *mddev) | |||
5655 | sysfs_notify_dirent_safe(mddev->sysfs_action); | 5666 | sysfs_notify_dirent_safe(mddev->sysfs_action); |
5656 | sysfs_notify(&mddev->kobj, NULL, "degraded"); | 5667 | sysfs_notify(&mddev->kobj, NULL, "degraded"); |
5657 | return 0; | 5668 | return 0; |
5669 | |||
5670 | abort: | ||
5671 | if (mddev->bio_set) { | ||
5672 | bioset_free(mddev->bio_set); | ||
5673 | mddev->bio_set = NULL; | ||
5674 | } | ||
5675 | if (mddev->sync_set) { | ||
5676 | bioset_free(mddev->sync_set); | ||
5677 | mddev->sync_set = NULL; | ||
5678 | } | ||
5679 | |||
5680 | return err; | ||
5658 | } | 5681 | } |
5659 | EXPORT_SYMBOL_GPL(md_run); | 5682 | EXPORT_SYMBOL_GPL(md_run); |
5660 | 5683 | ||
@@ -8049,6 +8072,7 @@ EXPORT_SYMBOL(md_done_sync); | |||
8049 | bool md_write_start(struct mddev *mddev, struct bio *bi) | 8072 | bool md_write_start(struct mddev *mddev, struct bio *bi) |
8050 | { | 8073 | { |
8051 | int did_change = 0; | 8074 | int did_change = 0; |
8075 | |||
8052 | if (bio_data_dir(bi) != WRITE) | 8076 | if (bio_data_dir(bi) != WRITE) |
8053 | return true; | 8077 | return true; |
8054 | 8078 | ||
@@ -8081,6 +8105,8 @@ bool md_write_start(struct mddev *mddev, struct bio *bi) | |||
8081 | rcu_read_unlock(); | 8105 | rcu_read_unlock(); |
8082 | if (did_change) | 8106 | if (did_change) |
8083 | sysfs_notify_dirent_safe(mddev->sysfs_state); | 8107 | sysfs_notify_dirent_safe(mddev->sysfs_state); |
8108 | if (!mddev->has_superblocks) | ||
8109 | return true; | ||
8084 | wait_event(mddev->sb_wait, | 8110 | wait_event(mddev->sb_wait, |
8085 | !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags) || | 8111 | !test_bit(MD_SB_CHANGE_PENDING, &mddev->sb_flags) || |
8086 | mddev->suspended); | 8112 | mddev->suspended); |
@@ -8543,6 +8569,19 @@ void md_do_sync(struct md_thread *thread) | |||
8543 | set_mask_bits(&mddev->sb_flags, 0, | 8569 | set_mask_bits(&mddev->sb_flags, 0, |
8544 | BIT(MD_SB_CHANGE_PENDING) | BIT(MD_SB_CHANGE_DEVS)); | 8570 | BIT(MD_SB_CHANGE_PENDING) | BIT(MD_SB_CHANGE_DEVS)); |
8545 | 8571 | ||
8572 | if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) && | ||
8573 | !test_bit(MD_RECOVERY_INTR, &mddev->recovery) && | ||
8574 | mddev->delta_disks > 0 && | ||
8575 | mddev->pers->finish_reshape && | ||
8576 | mddev->pers->size && | ||
8577 | mddev->queue) { | ||
8578 | mddev_lock_nointr(mddev); | ||
8579 | md_set_array_sectors(mddev, mddev->pers->size(mddev, 0, 0)); | ||
8580 | mddev_unlock(mddev); | ||
8581 | set_capacity(mddev->gendisk, mddev->array_sectors); | ||
8582 | revalidate_disk(mddev->gendisk); | ||
8583 | } | ||
8584 | |||
8546 | spin_lock(&mddev->lock); | 8585 | spin_lock(&mddev->lock); |
8547 | if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { | 8586 | if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { |
8548 | /* We completed so min/max setting can be forgotten if used. */ | 8587 | /* We completed so min/max setting can be forgotten if used. */ |
@@ -8569,6 +8608,10 @@ static int remove_and_add_spares(struct mddev *mddev, | |||
8569 | int removed = 0; | 8608 | int removed = 0; |
8570 | bool remove_some = false; | 8609 | bool remove_some = false; |
8571 | 8610 | ||
8611 | if (this && test_bit(MD_RECOVERY_RUNNING, &mddev->recovery)) | ||
8612 | /* Mustn't remove devices when resync thread is running */ | ||
8613 | return 0; | ||
8614 | |||
8572 | rdev_for_each(rdev, mddev) { | 8615 | rdev_for_each(rdev, mddev) { |
8573 | if ((this == NULL || rdev == this) && | 8616 | if ((this == NULL || rdev == this) && |
8574 | rdev->raid_disk >= 0 && | 8617 | rdev->raid_disk >= 0 && |