]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Define imsm_analyze_change function
authorKrzysztof Wojcik <krzysztof.wojcik@intel.com>
Mon, 17 Jan 2011 01:52:36 +0000 (12:52 +1100)
committerNeilBrown <neilb@suse.de>
Mon, 17 Jan 2011 01:52:36 +0000 (12:52 +1100)
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>
super-intel.c

index cb2b51b62e8fae0bf5668506e779cc13c049b2e4..d86e8d8111de1748d203d965c06c9b4eba7f1edb 100644 (file)
@@ -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: