diff options
Diffstat (limited to 'drivers/md/raid5.c')
-rw-r--r-- | drivers/md/raid5.c | 85 |
1 files changed, 55 insertions, 30 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 37835538b58e..b8a2c5dc67ba 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -3785,7 +3785,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped | |||
3785 | conf->reshape_progress < raid5_size(mddev, 0, 0)) { | 3785 | conf->reshape_progress < raid5_size(mddev, 0, 0)) { |
3786 | sector_nr = raid5_size(mddev, 0, 0) | 3786 | sector_nr = raid5_size(mddev, 0, 0) |
3787 | - conf->reshape_progress; | 3787 | - conf->reshape_progress; |
3788 | } else if (mddev->delta_disks > 0 && | 3788 | } else if (mddev->delta_disks >= 0 && |
3789 | conf->reshape_progress > 0) | 3789 | conf->reshape_progress > 0) |
3790 | sector_nr = conf->reshape_progress; | 3790 | sector_nr = conf->reshape_progress; |
3791 | sector_div(sector_nr, new_data_disks); | 3791 | sector_div(sector_nr, new_data_disks); |
@@ -3999,6 +3999,9 @@ static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *ski | |||
3999 | return 0; | 3999 | return 0; |
4000 | } | 4000 | } |
4001 | 4001 | ||
4002 | /* Allow raid5_quiesce to complete */ | ||
4003 | wait_event(conf->wait_for_overlap, conf->quiesce != 2); | ||
4004 | |||
4002 | if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) | 4005 | if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) |
4003 | return reshape_request(mddev, sector_nr, skipped); | 4006 | return reshape_request(mddev, sector_nr, skipped); |
4004 | 4007 | ||
@@ -4316,6 +4319,15 @@ raid5_size(mddev_t *mddev, sector_t sectors, int raid_disks) | |||
4316 | return sectors * (raid_disks - conf->max_degraded); | 4319 | return sectors * (raid_disks - conf->max_degraded); |
4317 | } | 4320 | } |
4318 | 4321 | ||
4322 | static void free_conf(raid5_conf_t *conf) | ||
4323 | { | ||
4324 | shrink_stripes(conf); | ||
4325 | safe_put_page(conf->spare_page); | ||
4326 | kfree(conf->disks); | ||
4327 | kfree(conf->stripe_hashtbl); | ||
4328 | kfree(conf); | ||
4329 | } | ||
4330 | |||
4319 | static raid5_conf_t *setup_conf(mddev_t *mddev) | 4331 | static raid5_conf_t *setup_conf(mddev_t *mddev) |
4320 | { | 4332 | { |
4321 | raid5_conf_t *conf; | 4333 | raid5_conf_t *conf; |
@@ -4447,11 +4459,7 @@ static raid5_conf_t *setup_conf(mddev_t *mddev) | |||
4447 | 4459 | ||
4448 | abort: | 4460 | abort: |
4449 | if (conf) { | 4461 | if (conf) { |
4450 | shrink_stripes(conf); | 4462 | free_conf(conf); |
4451 | safe_put_page(conf->spare_page); | ||
4452 | kfree(conf->disks); | ||
4453 | kfree(conf->stripe_hashtbl); | ||
4454 | kfree(conf); | ||
4455 | return ERR_PTR(-EIO); | 4463 | return ERR_PTR(-EIO); |
4456 | } else | 4464 | } else |
4457 | return ERR_PTR(-ENOMEM); | 4465 | return ERR_PTR(-ENOMEM); |
@@ -4501,7 +4509,26 @@ static int run(mddev_t *mddev) | |||
4501 | (old_disks-max_degraded)); | 4509 | (old_disks-max_degraded)); |
4502 | /* here_old is the first stripe that we might need to read | 4510 | /* here_old is the first stripe that we might need to read |
4503 | * from */ | 4511 | * from */ |
4504 | if (here_new >= here_old) { | 4512 | if (mddev->delta_disks == 0) { |
4513 | /* We cannot be sure it is safe to start an in-place | ||
4514 | * reshape. It is only safe if user-space if monitoring | ||
4515 | * and taking constant backups. | ||
4516 | * mdadm always starts a situation like this in | ||
4517 | * readonly mode so it can take control before | ||
4518 | * allowing any writes. So just check for that. | ||
4519 | */ | ||
4520 | if ((here_new * mddev->new_chunk_sectors != | ||
4521 | here_old * mddev->chunk_sectors) || | ||
4522 | mddev->ro == 0) { | ||
4523 | printk(KERN_ERR "raid5: in-place reshape must be started" | ||
4524 | " in read-only mode - aborting\n"); | ||
4525 | return -EINVAL; | ||
4526 | } | ||
4527 | } else if (mddev->delta_disks < 0 | ||
4528 | ? (here_new * mddev->new_chunk_sectors <= | ||
4529 | here_old * mddev->chunk_sectors) | ||
4530 | : (here_new * mddev->new_chunk_sectors >= | ||
4531 | here_old * mddev->chunk_sectors)) { | ||
4505 | /* Reading from the same stripe as writing to - bad */ | 4532 | /* Reading from the same stripe as writing to - bad */ |
4506 | printk(KERN_ERR "raid5: reshape_position too early for " | 4533 | printk(KERN_ERR "raid5: reshape_position too early for " |
4507 | "auto-recovery - aborting.\n"); | 4534 | "auto-recovery - aborting.\n"); |
@@ -4629,12 +4656,8 @@ abort: | |||
4629 | md_unregister_thread(mddev->thread); | 4656 | md_unregister_thread(mddev->thread); |
4630 | mddev->thread = NULL; | 4657 | mddev->thread = NULL; |
4631 | if (conf) { | 4658 | if (conf) { |
4632 | shrink_stripes(conf); | ||
4633 | print_raid5_conf(conf); | 4659 | print_raid5_conf(conf); |
4634 | safe_put_page(conf->spare_page); | 4660 | free_conf(conf); |
4635 | kfree(conf->disks); | ||
4636 | kfree(conf->stripe_hashtbl); | ||
4637 | kfree(conf); | ||
4638 | } | 4661 | } |
4639 | mddev->private = NULL; | 4662 | mddev->private = NULL; |
4640 | printk(KERN_ALERT "raid5: failed to run raid set %s\n", mdname(mddev)); | 4663 | printk(KERN_ALERT "raid5: failed to run raid set %s\n", mdname(mddev)); |
@@ -4649,13 +4672,10 @@ static int stop(mddev_t *mddev) | |||
4649 | 4672 | ||
4650 | md_unregister_thread(mddev->thread); | 4673 | md_unregister_thread(mddev->thread); |
4651 | mddev->thread = NULL; | 4674 | mddev->thread = NULL; |
4652 | shrink_stripes(conf); | ||
4653 | kfree(conf->stripe_hashtbl); | ||
4654 | mddev->queue->backing_dev_info.congested_fn = NULL; | 4675 | mddev->queue->backing_dev_info.congested_fn = NULL; |
4655 | blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ | 4676 | blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ |
4656 | sysfs_remove_group(&mddev->kobj, &raid5_attrs_group); | 4677 | sysfs_remove_group(&mddev->kobj, &raid5_attrs_group); |
4657 | kfree(conf->disks); | 4678 | free_conf(conf); |
4658 | kfree(conf); | ||
4659 | mddev->private = NULL; | 4679 | mddev->private = NULL; |
4660 | return 0; | 4680 | return 0; |
4661 | } | 4681 | } |
@@ -4857,6 +4877,7 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors) | |||
4857 | return -EINVAL; | 4877 | return -EINVAL; |
4858 | set_capacity(mddev->gendisk, mddev->array_sectors); | 4878 | set_capacity(mddev->gendisk, mddev->array_sectors); |
4859 | mddev->changed = 1; | 4879 | mddev->changed = 1; |
4880 | revalidate_disk(mddev->gendisk); | ||
4860 | if (sectors > mddev->dev_sectors && mddev->recovery_cp == MaxSector) { | 4881 | if (sectors > mddev->dev_sectors && mddev->recovery_cp == MaxSector) { |
4861 | mddev->recovery_cp = mddev->dev_sectors; | 4882 | mddev->recovery_cp = mddev->dev_sectors; |
4862 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | 4883 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); |
@@ -5002,7 +5023,7 @@ static int raid5_start_reshape(mddev_t *mddev) | |||
5002 | spin_unlock_irqrestore(&conf->device_lock, flags); | 5023 | spin_unlock_irqrestore(&conf->device_lock, flags); |
5003 | } | 5024 | } |
5004 | mddev->raid_disks = conf->raid_disks; | 5025 | mddev->raid_disks = conf->raid_disks; |
5005 | mddev->reshape_position = 0; | 5026 | mddev->reshape_position = conf->reshape_progress; |
5006 | set_bit(MD_CHANGE_DEVS, &mddev->flags); | 5027 | set_bit(MD_CHANGE_DEVS, &mddev->flags); |
5007 | 5028 | ||
5008 | clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); | 5029 | clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); |
@@ -5057,7 +5078,6 @@ static void end_reshape(raid5_conf_t *conf) | |||
5057 | */ | 5078 | */ |
5058 | static void raid5_finish_reshape(mddev_t *mddev) | 5079 | static void raid5_finish_reshape(mddev_t *mddev) |
5059 | { | 5080 | { |
5060 | struct block_device *bdev; | ||
5061 | raid5_conf_t *conf = mddev->private; | 5081 | raid5_conf_t *conf = mddev->private; |
5062 | 5082 | ||
5063 | if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { | 5083 | if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { |
@@ -5066,15 +5086,7 @@ static void raid5_finish_reshape(mddev_t *mddev) | |||
5066 | md_set_array_sectors(mddev, raid5_size(mddev, 0, 0)); | 5086 | md_set_array_sectors(mddev, raid5_size(mddev, 0, 0)); |
5067 | set_capacity(mddev->gendisk, mddev->array_sectors); | 5087 | set_capacity(mddev->gendisk, mddev->array_sectors); |
5068 | mddev->changed = 1; | 5088 | mddev->changed = 1; |
5069 | 5089 | revalidate_disk(mddev->gendisk); | |
5070 | bdev = bdget_disk(mddev->gendisk, 0); | ||
5071 | if (bdev) { | ||
5072 | mutex_lock(&bdev->bd_inode->i_mutex); | ||
5073 | i_size_write(bdev->bd_inode, | ||
5074 | (loff_t)mddev->array_sectors << 9); | ||
5075 | mutex_unlock(&bdev->bd_inode->i_mutex); | ||
5076 | bdput(bdev); | ||
5077 | } | ||
5078 | } else { | 5090 | } else { |
5079 | int d; | 5091 | int d; |
5080 | mddev->degraded = conf->raid_disks; | 5092 | mddev->degraded = conf->raid_disks; |
@@ -5085,8 +5097,15 @@ static void raid5_finish_reshape(mddev_t *mddev) | |||
5085 | mddev->degraded--; | 5097 | mddev->degraded--; |
5086 | for (d = conf->raid_disks ; | 5098 | for (d = conf->raid_disks ; |
5087 | d < conf->raid_disks - mddev->delta_disks; | 5099 | d < conf->raid_disks - mddev->delta_disks; |
5088 | d++) | 5100 | d++) { |
5089 | raid5_remove_disk(mddev, d); | 5101 | mdk_rdev_t *rdev = conf->disks[d].rdev; |
5102 | if (rdev && raid5_remove_disk(mddev, d) == 0) { | ||
5103 | char nm[20]; | ||
5104 | sprintf(nm, "rd%d", rdev->raid_disk); | ||
5105 | sysfs_remove_link(&mddev->kobj, nm); | ||
5106 | rdev->raid_disk = -1; | ||
5107 | } | ||
5108 | } | ||
5090 | } | 5109 | } |
5091 | mddev->layout = conf->algorithm; | 5110 | mddev->layout = conf->algorithm; |
5092 | mddev->chunk_sectors = conf->chunk_sectors; | 5111 | mddev->chunk_sectors = conf->chunk_sectors; |
@@ -5106,12 +5125,18 @@ static void raid5_quiesce(mddev_t *mddev, int state) | |||
5106 | 5125 | ||
5107 | case 1: /* stop all writes */ | 5126 | case 1: /* stop all writes */ |
5108 | spin_lock_irq(&conf->device_lock); | 5127 | spin_lock_irq(&conf->device_lock); |
5109 | conf->quiesce = 1; | 5128 | /* '2' tells resync/reshape to pause so that all |
5129 | * active stripes can drain | ||
5130 | */ | ||
5131 | conf->quiesce = 2; | ||
5110 | wait_event_lock_irq(conf->wait_for_stripe, | 5132 | wait_event_lock_irq(conf->wait_for_stripe, |
5111 | atomic_read(&conf->active_stripes) == 0 && | 5133 | atomic_read(&conf->active_stripes) == 0 && |
5112 | atomic_read(&conf->active_aligned_reads) == 0, | 5134 | atomic_read(&conf->active_aligned_reads) == 0, |
5113 | conf->device_lock, /* nothing */); | 5135 | conf->device_lock, /* nothing */); |
5136 | conf->quiesce = 1; | ||
5114 | spin_unlock_irq(&conf->device_lock); | 5137 | spin_unlock_irq(&conf->device_lock); |
5138 | /* allow reshape to continue */ | ||
5139 | wake_up(&conf->wait_for_overlap); | ||
5115 | break; | 5140 | break; |
5116 | 5141 | ||
5117 | case 0: /* re-enable writes */ | 5142 | case 0: /* re-enable writes */ |