diff options
Diffstat (limited to 'drivers/md/raid5.c')
-rw-r--r-- | drivers/md/raid5.c | 51 |
1 files changed, 25 insertions, 26 deletions
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 37835538b58e..2b521ee67dfa 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -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); |
@@ -4629,12 +4637,8 @@ abort: | |||
4629 | md_unregister_thread(mddev->thread); | 4637 | md_unregister_thread(mddev->thread); |
4630 | mddev->thread = NULL; | 4638 | mddev->thread = NULL; |
4631 | if (conf) { | 4639 | if (conf) { |
4632 | shrink_stripes(conf); | ||
4633 | print_raid5_conf(conf); | 4640 | print_raid5_conf(conf); |
4634 | safe_put_page(conf->spare_page); | 4641 | free_conf(conf); |
4635 | kfree(conf->disks); | ||
4636 | kfree(conf->stripe_hashtbl); | ||
4637 | kfree(conf); | ||
4638 | } | 4642 | } |
4639 | mddev->private = NULL; | 4643 | mddev->private = NULL; |
4640 | printk(KERN_ALERT "raid5: failed to run raid set %s\n", mdname(mddev)); | 4644 | printk(KERN_ALERT "raid5: failed to run raid set %s\n", mdname(mddev)); |
@@ -4649,13 +4653,10 @@ static int stop(mddev_t *mddev) | |||
4649 | 4653 | ||
4650 | md_unregister_thread(mddev->thread); | 4654 | md_unregister_thread(mddev->thread); |
4651 | mddev->thread = NULL; | 4655 | mddev->thread = NULL; |
4652 | shrink_stripes(conf); | ||
4653 | kfree(conf->stripe_hashtbl); | ||
4654 | mddev->queue->backing_dev_info.congested_fn = NULL; | 4656 | mddev->queue->backing_dev_info.congested_fn = NULL; |
4655 | blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ | 4657 | blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ |
4656 | sysfs_remove_group(&mddev->kobj, &raid5_attrs_group); | 4658 | sysfs_remove_group(&mddev->kobj, &raid5_attrs_group); |
4657 | kfree(conf->disks); | 4659 | free_conf(conf); |
4658 | kfree(conf); | ||
4659 | mddev->private = NULL; | 4660 | mddev->private = NULL; |
4660 | return 0; | 4661 | return 0; |
4661 | } | 4662 | } |
@@ -4857,6 +4858,7 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors) | |||
4857 | return -EINVAL; | 4858 | return -EINVAL; |
4858 | set_capacity(mddev->gendisk, mddev->array_sectors); | 4859 | set_capacity(mddev->gendisk, mddev->array_sectors); |
4859 | mddev->changed = 1; | 4860 | mddev->changed = 1; |
4861 | revalidate_disk(mddev->gendisk); | ||
4860 | if (sectors > mddev->dev_sectors && mddev->recovery_cp == MaxSector) { | 4862 | if (sectors > mddev->dev_sectors && mddev->recovery_cp == MaxSector) { |
4861 | mddev->recovery_cp = mddev->dev_sectors; | 4863 | mddev->recovery_cp = mddev->dev_sectors; |
4862 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | 4864 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); |
@@ -5002,7 +5004,7 @@ static int raid5_start_reshape(mddev_t *mddev) | |||
5002 | spin_unlock_irqrestore(&conf->device_lock, flags); | 5004 | spin_unlock_irqrestore(&conf->device_lock, flags); |
5003 | } | 5005 | } |
5004 | mddev->raid_disks = conf->raid_disks; | 5006 | mddev->raid_disks = conf->raid_disks; |
5005 | mddev->reshape_position = 0; | 5007 | mddev->reshape_position = conf->reshape_progress; |
5006 | set_bit(MD_CHANGE_DEVS, &mddev->flags); | 5008 | set_bit(MD_CHANGE_DEVS, &mddev->flags); |
5007 | 5009 | ||
5008 | clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); | 5010 | clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); |
@@ -5057,7 +5059,6 @@ static void end_reshape(raid5_conf_t *conf) | |||
5057 | */ | 5059 | */ |
5058 | static void raid5_finish_reshape(mddev_t *mddev) | 5060 | static void raid5_finish_reshape(mddev_t *mddev) |
5059 | { | 5061 | { |
5060 | struct block_device *bdev; | ||
5061 | raid5_conf_t *conf = mddev->private; | 5062 | raid5_conf_t *conf = mddev->private; |
5062 | 5063 | ||
5063 | if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { | 5064 | if (!test_bit(MD_RECOVERY_INTR, &mddev->recovery)) { |
@@ -5066,15 +5067,7 @@ static void raid5_finish_reshape(mddev_t *mddev) | |||
5066 | md_set_array_sectors(mddev, raid5_size(mddev, 0, 0)); | 5067 | md_set_array_sectors(mddev, raid5_size(mddev, 0, 0)); |
5067 | set_capacity(mddev->gendisk, mddev->array_sectors); | 5068 | set_capacity(mddev->gendisk, mddev->array_sectors); |
5068 | mddev->changed = 1; | 5069 | mddev->changed = 1; |
5069 | 5070 | 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 { | 5071 | } else { |
5079 | int d; | 5072 | int d; |
5080 | mddev->degraded = conf->raid_disks; | 5073 | mddev->degraded = conf->raid_disks; |
@@ -5106,12 +5099,18 @@ static void raid5_quiesce(mddev_t *mddev, int state) | |||
5106 | 5099 | ||
5107 | case 1: /* stop all writes */ | 5100 | case 1: /* stop all writes */ |
5108 | spin_lock_irq(&conf->device_lock); | 5101 | spin_lock_irq(&conf->device_lock); |
5109 | conf->quiesce = 1; | 5102 | /* '2' tells resync/reshape to pause so that all |
5103 | * active stripes can drain | ||
5104 | */ | ||
5105 | conf->quiesce = 2; | ||
5110 | wait_event_lock_irq(conf->wait_for_stripe, | 5106 | wait_event_lock_irq(conf->wait_for_stripe, |
5111 | atomic_read(&conf->active_stripes) == 0 && | 5107 | atomic_read(&conf->active_stripes) == 0 && |
5112 | atomic_read(&conf->active_aligned_reads) == 0, | 5108 | atomic_read(&conf->active_aligned_reads) == 0, |
5113 | conf->device_lock, /* nothing */); | 5109 | conf->device_lock, /* nothing */); |
5110 | conf->quiesce = 1; | ||
5114 | spin_unlock_irq(&conf->device_lock); | 5111 | spin_unlock_irq(&conf->device_lock); |
5112 | /* allow reshape to continue */ | ||
5113 | wake_up(&conf->wait_for_overlap); | ||
5115 | break; | 5114 | break; |
5116 | 5115 | ||
5117 | case 0: /* re-enable writes */ | 5116 | case 0: /* re-enable writes */ |