From 80c3a6ce4ba4470379b9e6a4d9bcd9d2ee26ae03 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 17 Mar 2009 18:10:40 -0700 Subject: [PATCH] md: add 'size' as a personality method In preparation for giving userspace control over ->array_sectors we need to be able to retrieve the 'default' size, and the 'anticipated' size when a reshape is requested. For personalities that do not reshape emit a warning if anything but the default size is requested. In the raid5 case we need to update ->previous_raid_disks to make the new 'default' size available. Reviewed-by: Andre Noll Signed-off-by: Dan Williams --- drivers/md/faulty.c | 14 +++++++++++++- drivers/md/linear.c | 15 +++++++++++++-- drivers/md/md.h | 1 + drivers/md/multipath.c | 11 ++++++++++- drivers/md/raid0.c | 20 ++++++++++++++++---- drivers/md/raid1.c | 13 +++++++++++-- drivers/md/raid10.c | 24 ++++++++++++++++++++++-- drivers/md/raid5.c | 35 +++++++++++++++++++++++++---------- 8 files changed, 111 insertions(+), 22 deletions(-) diff --git a/drivers/md/faulty.c b/drivers/md/faulty.c index 18793c13727..d76c87f2a83 100644 --- a/drivers/md/faulty.c +++ b/drivers/md/faulty.c @@ -283,6 +283,17 @@ static int reconfig(mddev_t *mddev, int layout, int chunk_size) return 0; } +static sector_t faulty_size(mddev_t *mddev, sector_t sectors, int raid_disks) +{ + WARN_ONCE(raid_disks, + "%s does not support generic reshape\n", __func__); + + if (sectors == 0) + return mddev->dev_sectors; + + return sectors; +} + static int run(mddev_t *mddev) { mdk_rdev_t *rdev; @@ -301,7 +312,7 @@ static int run(mddev_t *mddev) list_for_each_entry(rdev, &mddev->disks, same_set) conf->rdev = rdev; - mddev->array_sectors = mddev->dev_sectors; + mddev->array_sectors = faulty_size(mddev, 0, 0); mddev->private = conf; reconfig(mddev, mddev->layout, -1); @@ -328,6 +339,7 @@ static struct mdk_personality faulty_personality = .stop = stop, .status = status, .reconfig = reconfig, + .size = faulty_size, }; static int __init raid_init(void) diff --git a/drivers/md/linear.c b/drivers/md/linear.c index d5d99290041..b6bb976123d 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c @@ -101,6 +101,16 @@ static int linear_congested(void *data, int bits) return ret; } +static sector_t linear_size(mddev_t *mddev, sector_t sectors, int raid_disks) +{ + linear_conf_t *conf = mddev_to_conf(mddev); + + WARN_ONCE(sectors || raid_disks, + "%s does not support generic reshape\n", __func__); + + return conf->array_sectors; +} + static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) { linear_conf_t *conf; @@ -253,7 +263,7 @@ static int linear_run (mddev_t *mddev) if (!conf) return 1; mddev->private = conf; - mddev->array_sectors = conf->array_sectors; + mddev->array_sectors = linear_size(mddev, 0, 0); blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec); mddev->queue->unplug_fn = linear_unplug; @@ -287,7 +297,7 @@ static int linear_add(mddev_t *mddev, mdk_rdev_t *rdev) newconf->prev = mddev_to_conf(mddev); mddev->private = newconf; mddev->raid_disks++; - mddev->array_sectors = newconf->array_sectors; + mddev->array_sectors = linear_size(mddev, 0, 0); set_capacity(mddev->gendisk, mddev->array_sectors); return 0; } @@ -385,6 +395,7 @@ static struct mdk_personality linear_personality = .stop = linear_stop, .status = linear_status, .hot_add_disk = linear_add, + .size = linear_size, }; static int __init linear_init (void) diff --git a/drivers/md/md.h b/drivers/md/md.h index 8034f62a9d2..d2c50da1ae7 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h @@ -312,6 +312,7 @@ struct mdk_personality int (*spare_active) (mddev_t *mddev); sector_t (*sync_request)(mddev_t *mddev, sector_t sector_nr, int *skipped, int go_faster); int (*resize) (mddev_t *mddev, sector_t sectors); + sector_t (*size) (mddev_t *mddev, sector_t sectors, int raid_disks); int (*check_reshape) (mddev_t *mddev); int (*start_reshape) (mddev_t *mddev); int (*reconfig) (mddev_t *mddev, int layout, int chunk_size); diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 87accf74e4b..a3f6d8668bb 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -406,6 +406,14 @@ static void multipathd (mddev_t *mddev) spin_unlock_irqrestore(&conf->device_lock, flags); } +static sector_t multipath_size(mddev_t *mddev, sector_t sectors, int raid_disks) +{ + WARN_ONCE(sectors || raid_disks, + "%s does not support generic reshape\n", __func__); + + return mddev->dev_sectors; +} + static int multipath_run (mddev_t *mddev) { multipath_conf_t *conf; @@ -502,7 +510,7 @@ static int multipath_run (mddev_t *mddev) /* * Ok, everything is just fine now */ - mddev->array_sectors = mddev->dev_sectors; + mddev->array_sectors = multipath_size(mddev, 0, 0); mddev->queue->unplug_fn = multipath_unplug; mddev->queue->backing_dev_info.congested_fn = multipath_congested; @@ -547,6 +555,7 @@ static struct mdk_personality multipath_personality = .error_handler = multipath_error, .hot_add_disk = multipath_add_disk, .hot_remove_disk= multipath_remove_disk, + .size = multipath_size, }; static int __init multipath_init (void) diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 9aebb4c93b6..bb0df6a1844 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -263,12 +263,25 @@ static int raid0_mergeable_bvec(struct request_queue *q, return max; } +static sector_t raid0_size(mddev_t *mddev, sector_t sectors, int raid_disks) +{ + sector_t array_sectors = 0; + mdk_rdev_t *rdev; + + WARN_ONCE(sectors || raid_disks, + "%s does not support generic reshape\n", __func__); + + list_for_each_entry(rdev, &mddev->disks, same_set) + array_sectors += rdev->sectors; + + return array_sectors; +} + static int raid0_run (mddev_t *mddev) { unsigned cur=0, i=0, nb_zone; s64 sectors; raid0_conf_t *conf; - mdk_rdev_t *rdev; if (mddev->chunk_size == 0) { printk(KERN_ERR "md/raid0: non-zero chunk size required.\n"); @@ -293,9 +306,7 @@ static int raid0_run (mddev_t *mddev) goto out_free_conf; /* calculate array device size */ - mddev->array_sectors = 0; - list_for_each_entry(rdev, &mddev->disks, same_set) - mddev->array_sectors += rdev->sectors; + mddev->array_sectors = raid0_size(mddev, 0, 0); printk(KERN_INFO "raid0 : md_size is %llu sectors.\n", (unsigned long long)mddev->array_sectors); @@ -511,6 +522,7 @@ static struct mdk_personality raid0_personality= .run = raid0_run, .stop = raid0_stop, .status = raid0_status, + .size = raid0_size, }; static int __init raid0_init (void) diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 7eaca320936..a2a83b0d5a9 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -1922,6 +1922,14 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i return nr_sectors; } +static sector_t raid1_size(mddev_t *mddev, sector_t sectors, int raid_disks) +{ + if (sectors) + return sectors; + + return mddev->dev_sectors; +} + static int run(mddev_t *mddev) { conf_t *conf; @@ -2051,7 +2059,7 @@ static int run(mddev_t *mddev) /* * Ok, everything is just fine now */ - mddev->array_sectors = mddev->dev_sectors; + mddev->array_sectors = raid1_size(mddev, 0, 0); mddev->queue->unplug_fn = raid1_unplug; mddev->queue->backing_dev_info.congested_fn = raid1_congested; @@ -2116,7 +2124,7 @@ static int raid1_resize(mddev_t *mddev, sector_t sectors) * any io in the removed space completes, but it hardly seems * worth it. */ - mddev->array_sectors = sectors; + mddev->array_sectors = raid1_size(mddev, sectors, 0); set_capacity(mddev->gendisk, mddev->array_sectors); mddev->changed = 1; if (mddev->array_sectors > mddev->dev_sectors && @@ -2270,6 +2278,7 @@ static struct mdk_personality raid1_personality = .spare_active = raid1_spare_active, .sync_request = sync_request, .resize = raid1_resize, + .size = raid1_size, .check_reshape = raid1_reshape, .quiesce = raid1_quiesce, }; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index c2059e25d03..5bf1b24ae80 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -2023,6 +2023,25 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i goto skipped; } +static sector_t +raid10_size(mddev_t *mddev, sector_t sectors, int raid_disks) +{ + sector_t size; + conf_t *conf = mddev_to_conf(mddev); + + if (!raid_disks) + raid_disks = mddev->raid_disks; + if (!sectors) + sectors = mddev->dev_sectors; + + size = sectors >> conf->chunk_shift; + sector_div(size, conf->far_copies); + size = size * raid_disks; + sector_div(size, conf->near_copies); + + return size << conf->chunk_shift; +} + static int run(mddev_t *mddev) { conf_t *conf; @@ -2174,8 +2193,8 @@ static int run(mddev_t *mddev) /* * Ok, everything is just fine now */ - mddev->array_sectors = size << conf->chunk_shift; - mddev->resync_max_sectors = size << conf->chunk_shift; + mddev->array_sectors = raid10_size(mddev, 0, 0); + mddev->resync_max_sectors = mddev->array_sectors; mddev->queue->unplug_fn = raid10_unplug; mddev->queue->backing_dev_info.congested_fn = raid10_congested; @@ -2261,6 +2280,7 @@ static struct mdk_personality raid10_personality = .spare_active = raid10_spare_active, .sync_request = sync_request, .quiesce = raid10_quiesce, + .size = raid10_size, }; static int __init raid_init(void) diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 70b50af2bcd..2cd619ff076 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -4166,6 +4166,20 @@ static struct attribute_group raid5_attrs_group = { .attrs = raid5_attrs, }; +static sector_t +raid5_size(mddev_t *mddev, sector_t sectors, int raid_disks) +{ + raid5_conf_t *conf = mddev_to_conf(mddev); + + if (!sectors) + sectors = mddev->dev_sectors; + if (!raid_disks) + raid_disks = conf->previous_raid_disks; + + sectors &= ~((sector_t)mddev->chunk_size/512 - 1); + return sectors * (raid_disks - conf->max_degraded); +} + static raid5_conf_t *setup_conf(mddev_t *mddev) { raid5_conf_t *conf; @@ -4460,8 +4474,7 @@ static int run(mddev_t *mddev) mddev->queue->backing_dev_info.congested_data = mddev; mddev->queue->backing_dev_info.congested_fn = raid5_congested; - mddev->array_sectors = mddev->dev_sectors * - (conf->previous_raid_disks - conf->max_degraded); + mddev->array_sectors = raid5_size(mddev, 0, 0); blk_queue_merge_bvec(mddev->queue, raid5_mergeable_bvec); @@ -4684,11 +4697,8 @@ static int raid5_resize(mddev_t *mddev, sector_t sectors) * any io in the removed space completes, but it hardly seems * worth it. */ - raid5_conf_t *conf = mddev_to_conf(mddev); - sectors &= ~((sector_t)mddev->chunk_size/512 - 1); - mddev->array_sectors = sectors * (mddev->raid_disks - - conf->max_degraded); + mddev->array_sectors = raid5_size(mddev, sectors, mddev->raid_disks); set_capacity(mddev->gendisk, mddev->array_sectors); mddev->changed = 1; if (sectors > mddev->dev_sectors && mddev->recovery_cp == MaxSector) { @@ -4824,10 +4834,12 @@ static void end_reshape(raid5_conf_t *conf) struct block_device *bdev; if (!test_bit(MD_RECOVERY_INTR, &conf->mddev->recovery)) { - conf->mddev->array_sectors = conf->mddev->dev_sectors * - (conf->raid_disks - conf->max_degraded); - set_capacity(conf->mddev->gendisk, conf->mddev->array_sectors); - conf->mddev->changed = 1; + mddev_t *mddev = conf->mddev; + + mddev->array_sectors = raid5_size(mddev, 0, conf->raid_disks); + set_capacity(mddev->gendisk, mddev->array_sectors); + mddev->changed = 1; + conf->previous_raid_disks = conf->raid_disks; bdev = bdget_disk(conf->mddev->gendisk, 0); if (bdev) { @@ -5076,6 +5088,7 @@ static struct mdk_personality raid6_personality = .spare_active = raid5_spare_active, .sync_request = sync_request, .resize = raid5_resize, + .size = raid5_size, #ifdef CONFIG_MD_RAID5_RESHAPE .check_reshape = raid5_check_reshape, .start_reshape = raid5_start_reshape, @@ -5098,6 +5111,7 @@ static struct mdk_personality raid5_personality = .spare_active = raid5_spare_active, .sync_request = sync_request, .resize = raid5_resize, + .size = raid5_size, #ifdef CONFIG_MD_RAID5_RESHAPE .check_reshape = raid5_check_reshape, .start_reshape = raid5_start_reshape, @@ -5122,6 +5136,7 @@ static struct mdk_personality raid4_personality = .spare_active = raid5_spare_active, .sync_request = sync_request, .resize = raid5_resize, + .size = raid5_size, #ifdef CONFIG_MD_RAID5_RESHAPE .check_reshape = raid5_check_reshape, .start_reshape = raid5_start_reshape,