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 */ |
