]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Add raid10 -> raid0 takeover support
authorKrzysztof Wojcik <krzysztof.wojcik@intel.com>
Tue, 25 Jan 2011 06:49:03 +0000 (17:49 +1100)
committerNeilBrown <neilb@suse.de>
Tue, 25 Jan 2011 22:50:37 +0000 (08:50 +1000)
The patch introduces takeover from level 10 to level 0 for imsm
metadata. This patch contains procedures connected with preparing
and applying metadata update during 10 -> 0 takeover.
When performing takeover 10->0 mdmon should update the external
metadata (due to disk slot and level changes).
To achieve that mdadm calls reshape_super() and prepare
the "update_takeover" metadata update type.
Prepared update is processed by mdmon in process_update().

Signed-off-by: Krzysztof Wojcik <krzysztof.wojcik@intel.com>
Signed-off-by: NeilBrown <neilb@suse.de>
Grow.c
super-intel.c

diff --git a/Grow.c b/Grow.c
index 42ef17ce9f8ecef895dcb4bea84e2a7791911538..f79616c28d05c8cc2f9b0415ad425f16603072ee 100644 (file)
--- a/Grow.c
+++ b/Grow.c
@@ -1466,6 +1466,8 @@ int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
                        rv = 1;
                        goto release;
                }
+               /* FIXME this is added with no justification - why is it here */
+               ping_monitor(container);
        }
 
        info.array = array;
index 83fcb064f6abe896e6041b856babc02c00ca77db..0178f289f51f942a980fa125ec688fba8f9c8f4e 100644 (file)
@@ -299,6 +299,7 @@ enum imsm_update_type {
        update_rename_array,
        update_add_remove_disk,
        update_reshape_container_disks,
+       update_takeover
 };
 
 struct imsm_update_activate_spare {
@@ -319,6 +320,15 @@ struct geo_params {
        int raid_disks;
 };
 
+enum takeover_direction {
+       R10_TO_R0,
+       R0_TO_R10
+};
+struct imsm_update_takeover {
+       enum imsm_update_type type;
+       int subarray;
+       enum takeover_direction direction;
+};
 
 struct imsm_update_reshape {
        enum imsm_update_type type;
@@ -5758,6 +5768,58 @@ update_reshape_exit:
        return ret_val;
 }
 
+static int apply_takeover_update(struct imsm_update_takeover *u,
+                                struct intel_super *super)
+{
+       struct imsm_dev *dev = NULL;
+       struct imsm_map *map;
+       struct dl *dm, *du;
+       struct intel_dev *dv;
+
+       for (dv = super->devlist; dv; dv = dv->next)
+               if (dv->index == (unsigned int)u->subarray) {
+                       dev = dv->dev;
+                       break;
+               }
+
+       if (dev == NULL)
+               return 0;
+
+       map = get_imsm_map(dev, 0);
+
+       if (u->direction == R10_TO_R0) {
+               /* iterate through devices to mark removed disks as spare */
+               for (dm = super->disks; dm; dm = dm->next) {
+                       if (dm->disk.status & FAILED_DISK) {
+                               int idx = dm->index;
+                               /* update indexes on the disk list */
+/* FIXME this loop-with-the-loop looks wrong,  I'm not convinced
+   the index values will end up being correct.... NB */
+                               for (du = super->disks; du; du = du->next)
+                                       if (du->index > idx)
+                                               du->index--;
+                               /* mark as spare disk */
+                               dm->disk.status = SPARE_DISK;
+                               dm->index = -1;
+                       }
+               }
+
+               /* update map */
+               map->num_members = map->num_members / 2;
+               map->map_state = IMSM_T_STATE_NORMAL;
+               map->num_domains = 1;
+               map->raid_level = 0;
+               map->failed_disk_num = -1;
+       }
+
+       /* update disk order table */
+       for (du = super->disks; du; du = du->next)
+               if (du->index >= 0)
+                       set_imsm_ord_tbl_ent(map, du->index, du->index);
+
+       return 1;
+}
+
 static void imsm_process_update(struct supertype *st,
                                struct metadata_update *update)
 {
@@ -5800,6 +5862,13 @@ static void imsm_process_update(struct supertype *st,
        mpb = super->anchor;
 
        switch (type) {
+       case update_takeover: {
+               struct imsm_update_takeover *u = (void *)update->buf;
+               if (apply_takeover_update(u, super))
+                       super->updates_pending++;
+               break;
+       }
+
        case update_reshape_container_disks: {
                struct imsm_update_reshape *u = (void *)update->buf;
                if (apply_reshape_container_disks_update(
@@ -6650,6 +6719,35 @@ analyse_change_exit:
        return change;
 }
 
+int imsm_takeover(struct supertype *st, struct geo_params *geo)
+{
+       struct intel_super *super = st->sb;
+       struct imsm_update_takeover *u;
+
+       u = malloc(sizeof(struct imsm_update_takeover));
+       if (u == NULL)
+               return 1;
+
+       u->type = update_takeover;
+       u->subarray = super->current_vol;
+
+       /* 10->0 transition */
+       if (geo->level == 0)
+               u->direction = R10_TO_R0;
+
+       /* update metadata locally */
+       imsm_update_metadata_locally(st, u,
+                                       sizeof(struct imsm_update_takeover));
+       /* and possibly remotely */
+       if (st->update_tail)
+               append_metadata_update(st, u,
+                                       sizeof(struct imsm_update_takeover));
+       else
+               free(u);
+
+       return 0;
+}
+
 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)
@@ -6731,7 +6829,7 @@ static int imsm_reshape_super(struct supertype *st, long long size, int level,
                change = imsm_analyze_change(st, &geo);
                switch (change) {
                case CH_TAKEOVER:
-                       ret_val = 0;
+                       ret_val = imsm_takeover(st, &geo);
                        break;
                case CH_CHUNK_MIGR:
                        ret_val = 0;