summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2012-05-21 03:28:33 +0400
committerNeilBrown <neilb@suse.de>2012-05-21 03:28:33 +0400
commitdeb200d08590622d987718135a1e6323f83154aa (patch)
tree7baf2fc97e48d229d7a311f55bf0f96ce6e445ba
parentf8c9e74ff0832f2244d7991d2aea13851b20a622 (diff)
downloadlinux-deb200d08590622d987718135a1e6323f83154aa.tar.xz
md/raid10: split out interpretation of layout to separate function.
We will soon be interpreting the layout (and chunksize etc) from multiple places to support reshape. So split it out into separate function. Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r--drivers/md/raid10.c67
1 files changed, 49 insertions, 18 deletions
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 1c90005ab343..f102e88fc785 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -3253,26 +3253,64 @@ static void calc_sectors(struct r10conf *conf, sector_t size)
}
}
+enum geo_type {geo_new, geo_old, geo_start};
+static int setup_geo(struct geom *geo, struct mddev *mddev, enum geo_type new)
+{
+ int nc, fc, fo;
+ int layout, chunk, disks;
+ switch (new) {
+ case geo_old:
+ layout = mddev->layout;
+ chunk = mddev->chunk_sectors;
+ disks = mddev->raid_disks - mddev->delta_disks;
+ break;
+ case geo_new:
+ layout = mddev->new_layout;
+ chunk = mddev->new_chunk_sectors;
+ disks = mddev->raid_disks;
+ break;
+ default: /* avoid 'may be unused' warnings */
+ case geo_start: /* new when starting reshape - raid_disks not
+ * updated yet. */
+ layout = mddev->new_layout;
+ chunk = mddev->new_chunk_sectors;
+ disks = mddev->raid_disks + mddev->delta_disks;
+ break;
+ }
+ if (layout >> 17)
+ return -1;
+ if (chunk < (PAGE_SIZE >> 9) ||
+ !is_power_of_2(chunk))
+ return -2;
+ nc = layout & 255;
+ fc = (layout >> 8) & 255;
+ fo = layout & (1<<16);
+ geo->raid_disks = disks;
+ geo->near_copies = nc;
+ geo->far_copies = fc;
+ geo->far_offset = fo;
+ geo->chunk_mask = chunk - 1;
+ geo->chunk_shift = ffz(~chunk);
+ return nc*fc;
+}
+
static struct r10conf *setup_conf(struct mddev *mddev)
{
struct r10conf *conf = NULL;
- int nc, fc, fo;
int err = -EINVAL;
+ struct geom geo;
+ int copies;
+
+ copies = setup_geo(&geo, mddev, geo_new);
- if (mddev->new_chunk_sectors < (PAGE_SIZE >> 9) ||
- !is_power_of_2(mddev->new_chunk_sectors)) {
+ if (copies == -2) {
printk(KERN_ERR "md/raid10:%s: chunk size must be "
"at least PAGE_SIZE(%ld) and be a power of 2.\n",
mdname(mddev), PAGE_SIZE);
goto out;
}
- nc = mddev->new_layout & 255;
- fc = (mddev->new_layout >> 8) & 255;
- fo = mddev->new_layout & (1<<16);
-
- if ((nc*fc) <2 || (nc*fc) > mddev->raid_disks ||
- (mddev->new_layout >> 17)) {
+ if (copies < 2 || copies > mddev->raid_disks) {
printk(KERN_ERR "md/raid10:%s: unsupported raid10 layout: 0x%8x\n",
mdname(mddev), mddev->new_layout);
goto out;
@@ -3292,15 +3330,8 @@ static struct r10conf *setup_conf(struct mddev *mddev)
if (!conf->tmppage)
goto out;
-
- conf->geo.raid_disks = mddev->raid_disks;
- conf->geo.near_copies = nc;
- conf->geo.far_copies = fc;
- conf->copies = nc*fc;
- conf->geo.far_offset = fo;
- conf->geo.chunk_mask = mddev->new_chunk_sectors - 1;
- conf->geo.chunk_shift = ffz(~mddev->new_chunk_sectors);
-
+ conf->geo = geo;
+ conf->copies = copies;
conf->r10bio_pool = mempool_create(NR_RAID10_BIOS, r10bio_pool_alloc,
r10bio_pool_free, conf);
if (!conf->r10bio_pool)