>From 218f21b2d6f55798ea7df2f82668fdf51f4b158a Mon Sep 17 00:00:00 2001 From: Marcin Labun <marcin.labun@xxxxxxxxx> Date: Tue, 11 Jan 2011 16:01:59 +0100 Subject: [PATCH 4/4] imsm: support for raid0 <-> raid5 migration Support for raid0 to raid5 and raid5 to raid0 migration in imsm. This is work in progress. Signed-off-by: Marcin Labun <marcin.labun@xxxxxxxxx> --- super-intel.c | 147 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 143 insertions(+), 4 deletions(-) diff --git a/super-intel.c b/super-intel.c index d3da6f9..3a471c3 100644 --- a/super-intel.c +++ b/super-intel.c @@ -317,6 +317,9 @@ struct imsm_update_reshape { enum imsm_update_type type; int old_raid_disks; int new_raid_disks; + int new_level; + int new_chunksize; + long long new_size; int new_disks[1]; /* new_raid_disks - old_raid_disks makedev number */ }; @@ -5816,6 +5819,7 @@ static int apply_reshape_container_disks_update(struct imsm_update_reshape *u, newdev->vol.curr_migr_unit = 0; newdev->vol.migr_type = MIGR_GEN_MIGR; newmap->num_members = u->new_raid_disks; + newmap->raid_level = u->new_level; for (i = 0; i < delta_disks; i++) { set_imsm_ord_tbl_ent(newmap, u->old_raid_disks + i, @@ -6421,6 +6425,18 @@ static int imsm_find_array_minor_by_subdev(int subdev, int container, int *minor return 0; } + +static int imsm_reshape_is_allowed_on_subarray(struct supertype *st, + struct geo_params *geo, + int *old_raid_disks) +{ + /* needs to convert requested geo to IMSM valid geometry + * all unset value shall be converted to current array values + */ + dprintf("\tSub-array operation operation allowed\n"); + return 1; +} + static int imsm_reshape_is_allowed_on_container(struct supertype *st, struct geo_params *geo, int *old_raid_disks) @@ -6569,12 +6585,14 @@ static int imsm_create_metadata_update_for_reshape( u->type = update_reshape_container_disks; u->old_raid_disks = old_raid_disks; u->new_raid_disks = geo->raid_disks; - + u->new_level = geo->level; + u->new_chunksize = geo->chunksize; + u->new_size = geo->size; /* now get spare disks list */ spares = get_spares_for_grow(st); - if (spares == NULL + if (((spares == NULL) && (delta_disks != 0)) || delta_disks > spares->array.spare_disks) { dprintf("imsm: ERROR: Cannot get spare devices.\n"); goto abort; @@ -6618,6 +6636,75 @@ abort: } +static int allocate_space_list(struct intel_super *super, struct imsm_update_reshape *u, void ***space_list) +{ + /* Every raid device in the container is about to + * gain some more devices, and we will enter a + * reconfiguration. + * So each 'imsm_map' will be bigger, and the imsm_vol + * will now hold 2 of them. + * Thus we need new 'struct imsm_dev' allocations sized + * as sizeof_imsm_dev but with more devices in both maps. + */ + struct intel_dev *dl; + void **space_tail = (void**)space_list; + + dprintf("imsm: allocate_space_list() for update_reshape\n"); + + for (dl = super->devlist; dl; dl = dl->next) { + int size = sizeof_imsm_dev(dl->dev, 1); + void *s; + if (u->new_raid_disks > u->old_raid_disks) + size += sizeof(__u32)*2* + (u->new_raid_disks - u->old_raid_disks); + s = malloc(size); + if (!s) + return 1; + *space_tail = s; + space_tail = s; + *space_tail = NULL; + } + return 0; +} + +// static int reallocate_anchor_for_update(struct intel_super *super, struct imsm_update_reshape *u); +/* + * Check if there is enouht spare and reallocate anchor if neccessary + * Return: + * 1 - no enouth space for new request + * 0 - anchor ready for updates + */ +static int reallocate_anchor_for_update(struct intel_super *super, struct imsm_update_reshape *u) +{ + /* reallocate anchor + */ + size_t buf_len = super->len; + size_t len = disks_to_mpb_size(u->new_raid_disks); + struct imsm_super *mpb = super->anchor; + void *new_anchor; + + dprintf("imsm: realocate anchore\n"); + + if (__le32_to_cpu(mpb->mpb_size) + len > buf_len) { + buf_len = ROUND_UP(__le32_to_cpu(mpb->mpb_size) + len, 512); + if (posix_memalign(&new_anchor, + 512, buf_len) == 0) { + memcpy(new_anchor, super->buf, super->len); + free(super->buf); + super->buf = new_anchor; + super->len = buf_len; + } else + return 1; + + } + return 0; +} + +/* + * Reshape IMSM metadata - prepare metadata update + * 0 - update successfully reshaped + * 1 - reshape start failed - abort the process + */ static int imsm_reshape_super(struct supertype *st, long long size, int level, int layout, int chunksize, int raid_disks, char *backup, char *dev, int verbose) @@ -6643,6 +6730,9 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level, dprintf("\tfor level : %i\n", geo.level); dprintf("\tfor raid_disks : %i\n", geo.raid_disks); + dprintf("\tfor layout : %i\n", geo.layout); + dprintf("\tfor size : %llu\n", geo.size); + dprintf("\tfor chunksize : %i\n", geo.chunksize); if (experimental() == 0) return ret_val; @@ -6734,8 +6824,57 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level, } else fprintf(stderr, Name "imsm: Operation is not allowed " "on this container\n"); - } else - fprintf(stderr, Name "imsm: not a container operation\n"); + } else { + struct imsm_update_reshape *u = NULL; + int len; + struct intel_super *super = st->sb; + void **space_list=NULL; + + int old_raid_disks = 0; + + dprintf("imsm: subarray reshape\n"); + if (imsm_reshape_is_allowed_on_subarray(st, &geo, &old_raid_disks) == 0) { + dprintf("imsm: reshape not allowed\n"); + goto exit_imsm_reshape_super; + } + + len = imsm_create_metadata_update_for_reshape(st, &geo, old_raid_disks, &u); + + if (len <= 0) { + dprintf("imsm: Cannot prepare update\n"); + goto exit_imsm_reshape_super; + } + + if (mdmon_running(st->container_dev)) { + ret_val = 0; + append_metadata_update(st, u, len); + goto exit_imsm_reshape_super; + } + /* no mdmon - apply update + */ + + dprintf("imsm:prepare space list for update_reshape\n"); + ret_val = allocate_space_list(super, u, &space_list); + if (ret_val == 0) { + ret_val = apply_reshape_container_disks_update(u, super, &space_list); + /* processed if reshape applied */ + if (ret_val == 1) { + ret_val = reallocate_anchor_for_update(super, u); + if (ret_val == 0) + super->updates_pending++; + } + else + /* set error code */ + ret_val = 1; + } + /* release memory */ + while (space_list) { + void *space = space_list; + space_list = *space_list; + free(space); + } + free(u); + } exit_imsm_reshape_super: dprintf("imsm: reshape_super Exit code = %i\n", ret_val); -- 1.6.4.2 -- To unsubscribe from this list: send the line "unsubscribe linux-raid" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html