From a3163bf0691494adbf2e2b99f1826ca5a849ee93 Mon Sep 17 00:00:00 2001 From: "mwilck@arcor.de" Date: Wed, 3 Jul 2013 22:27:52 +0200 Subject: [PATCH] DDF: layout_md2ddf: new md->DDF layout conversion Support for RAID 10 makes it necessary to rewrite the algorithm for deriving DDF layout from MD layout. The functions level_to_prl and layout_to_rlq are combined in a single function that takes md layout parameters and converts them to DDF. Signed-off-by: Martin Wilck Signed-off-by: NeilBrown --- super-ddf.c | 199 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 117 insertions(+), 82 deletions(-) diff --git a/super-ddf.c b/super-ddf.c index b95f4a08..c548ceb0 100644 --- a/super-ddf.c +++ b/super-ddf.c @@ -484,6 +484,110 @@ static unsigned int calc_crc(void *buf, int len) return __cpu_to_be32(newcrc); } +#define DDF_INVALID_LEVEL 0xff +#define DDF_NO_SECONDARY 0xff +static int err_bad_md_layout(const mdu_array_info_t *array) +{ + pr_err("RAID%d layout %x with %d disks is unsupported for DDF\n", + array->level, array->layout, array->raid_disks); + return DDF_INVALID_LEVEL; +} + +static int layout_md2ddf(const mdu_array_info_t *array, + struct vd_config *conf) +{ + __u16 prim_elmnt_count = __cpu_to_be16(array->raid_disks); + __u8 prl = DDF_INVALID_LEVEL, rlq = 0; + __u8 sec_elmnt_count = 1; + __u8 srl = DDF_NO_SECONDARY; + + switch (array->level) { + case LEVEL_LINEAR: + prl = DDF_CONCAT; + break; + case 0: + rlq = DDF_RAID0_SIMPLE; + prl = DDF_RAID0; + break; + case 1: + switch (array->raid_disks) { + case 2: + rlq = DDF_RAID1_SIMPLE; + break; + case 3: + rlq = DDF_RAID1_MULTI; + break; + default: + return err_bad_md_layout(array); + } + prl = DDF_RAID1; + break; + case 4: + if (array->layout != 0) + return err_bad_md_layout(array); + rlq = DDF_RAID4_N; + prl = DDF_RAID4; + break; + case 5: + switch (array->layout) { + case ALGORITHM_LEFT_ASYMMETRIC: + rlq = DDF_RAID5_N_RESTART; + break; + case ALGORITHM_RIGHT_ASYMMETRIC: + rlq = DDF_RAID5_0_RESTART; + break; + case ALGORITHM_LEFT_SYMMETRIC: + rlq = DDF_RAID5_N_CONTINUE; + break; + case ALGORITHM_RIGHT_SYMMETRIC: + /* not mentioned in standard */ + default: + return err_bad_md_layout(array); + } + prl = DDF_RAID5; + break; + case 6: + switch (array->layout) { + case ALGORITHM_ROTATING_N_RESTART: + rlq = DDF_RAID5_N_RESTART; + break; + case ALGORITHM_ROTATING_ZERO_RESTART: + rlq = DDF_RAID6_0_RESTART; + break; + case ALGORITHM_ROTATING_N_CONTINUE: + rlq = DDF_RAID5_N_CONTINUE; + break; + default: + return err_bad_md_layout(array); + } + prl = DDF_RAID6; + break; + case 10: + if (array->raid_disks % 2 == 0 && array->layout == 0x102) { + rlq = DDF_RAID1_SIMPLE; + prim_elmnt_count = __cpu_to_be16(2); + sec_elmnt_count = array->raid_disks / 2; + } else if (array->raid_disks % 3 == 0 + && array->layout == 0x103) { + rlq = DDF_RAID1_MULTI; + prim_elmnt_count = __cpu_to_be16(3); + sec_elmnt_count = array->raid_disks / 3; + } else + return err_bad_md_layout(array); + srl = DDF_2SPANNED; + prl = DDF_RAID1; + break; + default: + return err_bad_md_layout(array); + } + conf->prl = prl; + conf->prim_elmnt_count = prim_elmnt_count; + conf->rlq = rlq; + conf->srl = srl; + conf->sec_elmnt_count = sec_elmnt_count; + return 0; +} + static int err_bad_ddf_layout(const struct vd_config *conf) { pr_err("DDF RAID %u qualifier %u with %u disks is unsupported\n", @@ -1128,24 +1232,6 @@ static mapping_t ddf_sec_level[] = { }; #endif -struct num_mapping { - int num1, num2; -}; -static struct num_mapping ddf_level_num[] = { - { DDF_RAID0, 0 }, - { DDF_RAID1, 1 }, - { DDF_RAID3, LEVEL_UNSUPPORTED }, - { DDF_RAID4, 4 }, - { DDF_RAID5, 5 }, - { DDF_RAID1E, LEVEL_UNSUPPORTED }, - { DDF_JBOD, LEVEL_UNSUPPORTED }, - { DDF_CONCAT, LEVEL_LINEAR }, - { DDF_RAID5E, LEVEL_UNSUPPORTED }, - { DDF_RAID5EE, LEVEL_UNSUPPORTED }, - { DDF_RAID6, 6}, - { MAXINT, MAXINT } -}; - static int all_ff(const char *guid) { int i; @@ -2168,59 +2254,6 @@ static int chunk_to_shift(int chunksize) return ffs(chunksize/512)-1; } -static int level_to_prl(int level) -{ - switch (level) { - case LEVEL_LINEAR: return DDF_CONCAT; - case 0: return DDF_RAID0; - case 1: return DDF_RAID1; - case 4: return DDF_RAID4; - case 5: return DDF_RAID5; - case 6: return DDF_RAID6; - default: return -1; - } -} - -static int layout_to_rlq(int level, int layout, int raiddisks) -{ - switch(level) { - case 0: - return DDF_RAID0_SIMPLE; - case 1: - switch(raiddisks) { - case 2: return DDF_RAID1_SIMPLE; - case 3: return DDF_RAID1_MULTI; - default: return -1; - } - case 4: - switch(layout) { - case 0: return DDF_RAID4_N; - } - break; - case 5: - switch(layout) { - case ALGORITHM_LEFT_ASYMMETRIC: - return DDF_RAID5_N_RESTART; - case ALGORITHM_RIGHT_ASYMMETRIC: - return DDF_RAID5_0_RESTART; - case ALGORITHM_LEFT_SYMMETRIC: - return DDF_RAID5_N_CONTINUE; - case ALGORITHM_RIGHT_SYMMETRIC: - return -1; /* not mentioned in standard */ - } - case 6: - switch(layout) { - case ALGORITHM_ROTATING_N_RESTART: - return DDF_RAID5_N_RESTART; - case ALGORITHM_ROTATING_ZERO_RESTART: - return DDF_RAID6_0_RESTART; - case ALGORITHM_ROTATING_N_CONTINUE: - return DDF_RAID5_N_CONTINUE; - } - } - return -1; -} - #ifndef MDASSEMBLE struct extent { unsigned long long start, size; @@ -2338,13 +2371,15 @@ static int init_super_ddf_bvd(struct supertype *st, vc->timestamp = __cpu_to_be32(time(0)-DECADE); vc->seqnum = __cpu_to_be32(1); memset(vc->pad0, 0xff, 24); - vc->prim_elmnt_count = __cpu_to_be16(info->raid_disks); vc->chunk_shift = chunk_to_shift(info->chunk_size); - vc->prl = level_to_prl(info->level); - vc->rlq = layout_to_rlq(info->level, info->layout, info->raid_disks); - vc->sec_elmnt_count = 1; + if (layout_md2ddf(info, vc) == -1 || + __be16_to_cpu(vc->prim_elmnt_count) > ddf->mppe) { + pr_err("%s: unsupported RAID level/layout %d/%d with %d disks\n", + __func__, info->level, info->layout, info->raid_disks); + free(vcl); + return 0; + } vc->sec_elmnt_seq = 0; - vc->srl = 0; vc->blocks = __cpu_to_be64(info->size * 2); vc->array_blocks = __cpu_to_be64( calc_array_size(info->level, info->raid_disks, info->layout, @@ -3008,12 +3043,12 @@ static int validate_geometry_ddf(struct supertype *st, } if (!dev) { - /* Initial sanity check. Exclude illegal levels. */ - int i; - for (i=0; ddf_level_num[i].num1 != MAXINT; i++) - if (ddf_level_num[i].num2 == level) - break; - if (ddf_level_num[i].num1 == MAXINT) { + mdu_array_info_t array = { + .level = level, .layout = layout, + .raid_disks = raiddisks + }; + struct vd_config conf; + if (layout_md2ddf(&array, &conf) == -1) { if (verbose) pr_err("DDF does not support level %d arrays\n", level); -- 2.39.2