summaryrefslogtreecommitdiff
path: root/super-intel.c
diff options
context:
space:
mode:
authorKrzysztof Wojcik <krzysztof.wojcik@intel.com>2011-01-17 12:52:36 +1100
committerNeilBrown <neilb@suse.de>2011-01-17 12:52:36 +1100
commit471bceb68151d322a97810a52f07512beadf4bd7 (patch)
treebf1c68eaf58e28073f1c4a44bce2c0aae330d85c /super-intel.c
parent300f503323bc601ec7f5e30cc798c3a711c6d373 (diff)
Define imsm_analyze_change function
Function intended to use for single volume migration. Function analyze transition and validate if it is supported. Signed-off-by: Krzysztof Wojcik <krzysztof.wojcik@intel.com> Signed-off-by: NeilBrown <neilb@suse.de>
Diffstat (limited to 'super-intel.c')
-rw-r--r--super-intel.c146
1 files changed, 131 insertions, 15 deletions
diff --git a/super-intel.c b/super-intel.c
index cb2b51b6..d86e8d81 100644
--- a/super-intel.c
+++ b/super-intel.c
@@ -6547,16 +6547,113 @@ static void imsm_update_metadata_locally(struct supertype *st,
}
}
-/*******************************************************************************
+/***************************************************************************
* Function: imsm_analyze_change
-* Description: Function analyze and validate change for single volume migration
+* Description: Function analyze change for single volume
+* and validate if transition is supported
* Parameters: Geometry parameters, supertype structure
* Returns: Operation type code on success, -1 if fail
-********************************************************************************/
-enum imsm_reshape_type imsm_analyze_change(
- struct supertype *st, struct geo_params *geo)
+****************************************************************************/
+enum imsm_reshape_type imsm_analyze_change(struct supertype *st,
+ struct geo_params *geo)
{
- return -1;
+ struct mdinfo info;
+ int change = -1;
+ int check_devs = 0;
+
+ getinfo_super_imsm_volume(st, &info, NULL);
+
+ if ((geo->level != info.array.level) &&
+ (geo->level >= 0) &&
+ (geo->level != UnSet)) {
+ switch (info.array.level) {
+ case 0:
+ if (geo->level == 5) {
+ change = CH_LEVEL_MIGRATION;
+ check_devs = 1;
+ }
+ if (geo->level == 10) {
+ change = CH_TAKEOVER;
+ check_devs = 1;
+ }
+ break;
+ case 5:
+ if (geo->level != 0)
+ change = CH_LEVEL_MIGRATION;
+ break;
+ case 10:
+ if (geo->level == 0) {
+ change = CH_TAKEOVER;
+ check_devs = 1;
+ }
+ break;
+ }
+ if (change == -1) {
+ fprintf(stderr,
+ Name " Error. Level Migration from %d to %d "
+ "not supported!\n",
+ info.array.level, geo->level);
+ goto analyse_change_exit;
+ }
+ } else
+ geo->level = info.array.level;
+
+ if ((geo->layout != info.array.layout)
+ && ((geo->layout != UnSet) && (geo->layout != -1))) {
+ change = CH_LEVEL_MIGRATION;
+ if ((info.array.layout == 0)
+ && (info.array.level == 5)
+ && (geo->layout == 5)) {
+ /* reshape 5 -> 4 */
+ } else if ((info.array.layout == 5)
+ && (info.array.level == 5)
+ && (geo->layout == 0)) {
+ /* reshape 4 -> 5 */
+ geo->layout = 0;
+ geo->level = 5;
+ } else {
+ fprintf(stderr,
+ Name " Error. Layout Migration from %d to %d "
+ "not supported!\n",
+ info.array.layout, geo->layout);
+ change = -1;
+ goto analyse_change_exit;
+ }
+ } else
+ geo->layout = info.array.layout;
+
+ if ((geo->chunksize > 0) && (geo->chunksize != UnSet)
+ && (geo->chunksize != info.array.chunk_size))
+ change = CH_CHUNK_MIGR;
+ else
+ geo->chunksize = info.array.chunk_size;
+
+ if (!validate_geometry_imsm(st,
+ geo->level,
+ geo->layout,
+ geo->raid_disks,
+ (geo->chunksize / 1024),
+ geo->size,
+ 0, 0, 1))
+ change = -1;
+
+ if (check_devs) {
+ struct intel_super *super = st->sb;
+ struct imsm_super *mpb = super->anchor;
+
+ if (mpb->num_raid_devs > 1) {
+ fprintf(stderr,
+ Name " Error. Cannot perform operation on %s"
+ "- for this operation it MUST be single "
+ "array in container\n",
+ geo->dev_name);
+ change = -1;
+ }
+ }
+
+analyse_change_exit:
+
+ return change;
}
static int imsm_reshape_super(struct supertype *st, long long size, int level,
@@ -6616,22 +6713,41 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level,
}
} else {
/* On volume level we support following operations
- * - takeover: raid10 -> raid0; raid0 -> raid10
- * - chunk size migration
- * - migration: raid5 -> raid0; raid0 -> raid5
- */
- int change;
+ * - takeover: raid10 -> raid0; raid0 -> raid10
+ * - chunk size migration
+ * - migration: raid5 -> raid0; raid0 -> raid5
+ */
+ struct intel_super *super = st->sb;
+ struct intel_dev *dev = super->devlist;
+ int change, devnum;
dprintf("imsm: info: Volume operation\n");
+ /* find requested device */
+ while (dev) {
+ imsm_find_array_minor_by_subdev(dev->index, st->container_dev, &devnum);
+ if (devnum == geo.dev_id)
+ break;
+ dev = dev->next;
+ }
+ if (dev == NULL) {
+ fprintf(stderr, Name " Cannot find %s (%i) subarray\n",
+ geo.dev_name, geo.dev_id);
+ goto exit_imsm_reshape_super;
+ }
+ super->current_vol = dev->index;
change = imsm_analyze_change(st, &geo);
switch (change) {
- case CH_TAKEOVER:
+ case CH_TAKEOVER:
+ ret_val = 0;
break;
- case CH_CHUNK_MIGR:
+ case CH_CHUNK_MIGR:
+ ret_val = 0;
break;
- case CH_LEVEL_MIGRATION:
+ case CH_LEVEL_MIGRATION:
+ ret_val = 0;
break;
+ default:
+ ret_val = 1;
}
- ret_val = 0;
}
exit_imsm_reshape_super: