]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
DDF: layout_ddf2md: new DDF->md RAID layout conversion
authormwilck@arcor.de <mwilck@arcor.de>
Wed, 3 Jul 2013 20:27:51 +0000 (22:27 +0200)
committerNeilBrown <neilb@suse.de>
Mon, 8 Jul 2013 05:28:31 +0000 (15:28 +1000)
layout_ddf2md() is a new RAID layout conversion routine.
It obsoletes the previous separate routines for obtaining
md level and layout (map_num1, rlq_to_layout).

Signed-off-by: Martin Wilck <mwilck@arcor.de>
Signed-off-by: NeilBrown <neilb@suse.de>
super-ddf.c

index 0f955be1c5d79f5d6588b8b986abb8aa51b98fcc..b95f4a088dafb2f47a826b9bbbeadac9f7bf5e67 100644 (file)
@@ -484,6 +484,102 @@ static unsigned int calc_crc(void *buf, int len)
        return __cpu_to_be32(newcrc);
 }
 
+static int err_bad_ddf_layout(const struct vd_config *conf)
+{
+       pr_err("DDF RAID %u qualifier %u with %u disks is unsupported\n",
+              conf->prl, conf->rlq, __be16_to_cpu(conf->prim_elmnt_count));
+       return -1;
+}
+
+static int layout_ddf2md(const struct vd_config *conf,
+                        mdu_array_info_t *array)
+{
+       int level = LEVEL_UNSUPPORTED;
+       int layout = 0;
+       int raiddisks = __be16_to_cpu(conf->prim_elmnt_count);
+
+       if (conf->sec_elmnt_count > 1) {
+               /* see also check_secondary() */
+               if (conf->prl != DDF_RAID1 ||
+                   (conf->srl != DDF_2STRIPED && conf->srl != DDF_2SPANNED)) {
+                       pr_err("Unsupported secondary RAID level %u/%u\n",
+                              conf->prl, conf->srl);
+                       return -1;
+               }
+               if (raiddisks == 2 && conf->rlq == DDF_RAID1_SIMPLE)
+                       layout = 0x102;
+               else if  (raiddisks == 3 && conf->rlq == DDF_RAID1_MULTI)
+                       layout = 0x103;
+               else
+                       return err_bad_ddf_layout(conf);
+               raiddisks *= conf->sec_elmnt_count;
+               level = 10;
+               goto good;
+       }
+
+       switch (conf->prl) {
+       case DDF_CONCAT:
+               level = LEVEL_LINEAR;
+               break;
+       case DDF_RAID0:
+               if (conf->rlq != DDF_RAID0_SIMPLE)
+                       return err_bad_ddf_layout(conf);
+               level = 0;
+               break;
+       case DDF_RAID1:
+               if (!((conf->rlq == DDF_RAID1_SIMPLE && raiddisks == 2) ||
+                     (conf->rlq == DDF_RAID1_MULTI && raiddisks == 3)))
+                       return err_bad_ddf_layout(conf);
+               level = 1;
+               break;
+       case DDF_RAID4:
+               if (conf->rlq != DDF_RAID4_N)
+                       return err_bad_ddf_layout(conf);
+               level = 4;
+               break;
+       case DDF_RAID5:
+               switch (conf->rlq) {
+               case DDF_RAID5_N_RESTART:
+                       layout = ALGORITHM_LEFT_ASYMMETRIC;
+                       break;
+               case DDF_RAID5_0_RESTART:
+                       layout = ALGORITHM_RIGHT_ASYMMETRIC;
+                       break;
+               case DDF_RAID5_N_CONTINUE:
+                       layout = ALGORITHM_LEFT_SYMMETRIC;
+                       break;
+               default:
+                       return err_bad_ddf_layout(conf);
+               }
+               level = 5;
+               break;
+       case DDF_RAID6:
+               switch (conf->rlq) {
+               case DDF_RAID5_N_RESTART:
+                       layout = ALGORITHM_ROTATING_N_RESTART;
+                       break;
+               case DDF_RAID6_0_RESTART:
+                       layout = ALGORITHM_ROTATING_ZERO_RESTART;
+                       break;
+               case DDF_RAID5_N_CONTINUE:
+                       layout = ALGORITHM_ROTATING_N_CONTINUE;
+                       break;
+               default:
+                       return err_bad_ddf_layout(conf);
+               }
+               level = 6;
+               break;
+       default:
+               return err_bad_ddf_layout(conf);
+       };
+
+good:
+       array->level = level;
+       array->layout = layout;
+       array->raid_disks = raiddisks;
+       return 0;
+}
+
 static int load_ddf_header(int fd, unsigned long long lba,
                           unsigned long long size,
                           int type,
@@ -1050,15 +1146,6 @@ static struct num_mapping ddf_level_num[] = {
        { MAXINT, MAXINT }
 };
 
-static int map_num1(struct num_mapping *map, int num)
-{
-       int i;
-       for (i=0 ; map[i].num1 != MAXINT; i++)
-               if (map[i].num1 == num)
-                       break;
-       return map[i].num2;
-}
-
 static int all_ff(const char *guid)
 {
        int i;
@@ -1638,8 +1725,6 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info, char *m
        }
 }
 
-static int rlq_to_layout(int rlq, int prl, int raiddisks);
-
 static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info, char *map)
 {
        struct ddf_super *ddf = st->sb;
@@ -1651,12 +1736,8 @@ static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info, cha
        __u32 *cptr;
 
        memset(info, 0, sizeof(*info));
-       /* FIXME this returns BVD info - what if we want SVD ?? */
-
-       info->array.raid_disks    = __be16_to_cpu(vc->conf.prim_elmnt_count);
-       info->array.level         = map_num1(ddf_level_num, vc->conf.prl);
-       info->array.layout        = rlq_to_layout(vc->conf.rlq, vc->conf.prl,
-                                                 info->array.raid_disks);
+       if (layout_ddf2md(&vc->conf, &info->array) == -1)
+               return;
        info->array.md_minor      = -1;
        cptr = (__u32 *)(vc->conf.guid + 16);
        info->array.ctime         = DECADE + __be32_to_cpu(*cptr);
@@ -2140,48 +2221,6 @@ static int layout_to_rlq(int level, int layout, int raiddisks)
        return -1;
 }
 
-static int rlq_to_layout(int rlq, int prl, int raiddisks)
-{
-       switch(prl) {
-       case DDF_RAID0:
-               return 0; /* hopefully rlq == DDF_RAID0_SIMPLE */
-       case DDF_RAID1:
-               return 0; /* hopefully rlq == SIMPLE or MULTI depending
-                            on raiddisks*/
-       case DDF_RAID4:
-               switch(rlq) {
-               case DDF_RAID4_N:
-                       return 0;
-               default:
-                       /* not supported */
-                       return -1; /* FIXME this isn't checked */
-               }
-       case DDF_RAID5:
-               switch(rlq) {
-               case DDF_RAID5_N_RESTART:
-                       return ALGORITHM_LEFT_ASYMMETRIC;
-               case DDF_RAID5_0_RESTART:
-                       return ALGORITHM_RIGHT_ASYMMETRIC;
-               case DDF_RAID5_N_CONTINUE:
-                       return ALGORITHM_LEFT_SYMMETRIC;
-               default:
-                       return -1;
-               }
-       case DDF_RAID6:
-               switch(rlq) {
-               case DDF_RAID5_N_RESTART:
-                       return ALGORITHM_ROTATING_N_RESTART;
-               case DDF_RAID6_0_RESTART:
-                       return ALGORITHM_ROTATING_ZERO_RESTART;
-               case DDF_RAID5_N_CONTINUE:
-                       return ALGORITHM_ROTATING_N_CONTINUE;
-               default:
-                       return -1;
-               }
-       }
-       return -1;
-}
-
 #ifndef MDASSEMBLE
 struct extent {
        unsigned long long start, size;
@@ -3433,26 +3472,8 @@ static struct mdinfo *container_content_ddf(struct supertype *st, char *subarray
                this->next = rest;
                rest = this;
 
-               if (vc->conf.sec_elmnt_count == 1) {
-                       this->array.level = map_num1(ddf_level_num,
-                                                    vc->conf.prl);
-                       this->array.raid_disks =
-                               __be16_to_cpu(vc->conf.prim_elmnt_count);
-                       this->array.layout =
-                               rlq_to_layout(vc->conf.rlq, vc->conf.prl,
-                                             this->array.raid_disks);
-               } else {
-                       /* The only supported layout is RAID 10.
-                        * Compatibility has been checked in check_secondary()
-                        * above.
-                        */
-                       this->array.level = 10;
-                       this->array.raid_disks =
-                               __be16_to_cpu(vc->conf.prim_elmnt_count)
-                               * vc->conf.sec_elmnt_count;
-                       this->array.layout = 0x100 |
-                               __be16_to_cpu(vc->conf.prim_elmnt_count);
-               }
+               if (layout_ddf2md(&vc->conf, &this->array))
+                       continue;
                this->array.md_minor      = -1;
                this->array.major_version = -1;
                this->array.minor_version = -2;