From: Krzysztof Wojcik Date: Tue, 25 Jan 2011 06:49:03 +0000 (+1100) Subject: Add raid10 -> raid0 takeover support X-Git-Tag: mdadm-3.2~58 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bb025c2f22c9c0cdf2d77c7a0e8298b3e3972538;p=thirdparty%2Fmdadm.git Add raid10 -> raid0 takeover support 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 Signed-off-by: NeilBrown --- diff --git a/Grow.c b/Grow.c index 42ef17ce..f79616c2 100644 --- 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; diff --git a/super-intel.c b/super-intel.c index 83fcb064..0178f289 100644 --- a/super-intel.c +++ b/super-intel.c @@ -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;