]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
DDF: container_content_ddf: handle RAID layout for RAID10
authormwilck@arcor.de <mwilck@arcor.de>
Fri, 1 Mar 2013 22:28:29 +0000 (23:28 +0100)
committerNeilBrown <neilb@suse.de>
Mon, 4 Mar 2013 05:10:38 +0000 (16:10 +1100)
This patch adds basic handling for the special case of RAID10.

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

index adad75ff64fa0d40a4c660b3b1bc7198ef6aff10..79c65e1c279488cadb44e0ce920d02b2f0f8f450 100644 (file)
@@ -3120,12 +3120,45 @@ static int check_secondary(const struct vcl *vc)
 
 #define NO_SUCH_REFNUM (0xFFFFFFFF)
 static unsigned int get_pd_index_from_refnum(const struct vcl *vc,
-                                            __u32 refnum, unsigned int nmax)
+                                            __u32 refnum, unsigned int nmax,
+                                            const struct vd_config **bvd,
+                                            unsigned int *idx)
 {
-       unsigned int i;
-       for (i = 0 ; i < nmax ; i++)
-               if (vc->conf.phys_refnum[i] == refnum)
-                       return i;
+       unsigned int i, j, n, sec, cnt;
+
+       cnt = __be16_to_cpu(vc->conf.prim_elmnt_count);
+       sec = (vc->conf.sec_elmnt_count == 1 ? 0 : vc->conf.sec_elmnt_seq);
+
+       for (i = 0, j = 0 ; i < nmax ; i++) {
+               /* j counts valid entries for this BVD */
+               if (vc->conf.phys_refnum[i] != 0xffffffff)
+                       j++;
+               if (vc->conf.phys_refnum[i] == refnum) {
+                       *bvd = &vc->conf;
+                       *idx = i;
+                       return sec * cnt + j - 1;
+               }
+       }
+       if (vc->other_bvds == NULL)
+               goto bad;
+
+       for (n = 1; n < vc->conf.sec_elmnt_count; n++) {
+               struct vd_config *vd = vc->other_bvds[n-1];
+               if (vd == NULL)
+                       continue;
+               sec = vd->sec_elmnt_seq;
+               for (i = 0, j = 0 ; i < nmax ; i++) {
+                       if (vd->phys_refnum[i] != 0xffffffff)
+                               j++;
+                       if (vd->phys_refnum[i] == refnum) {
+                               *bvd = vd;
+                               *idx = i;
+                               return sec * cnt + j - 1;
+                       }
+               }
+       }
+bad:
+       *bvd = NULL;
        return NO_SUCH_REFNUM;
 }
 
@@ -3166,11 +3199,26 @@ static struct mdinfo *container_content_ddf(struct supertype *st, char *subarray
                this->next = rest;
                rest = this;
 
-               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);
+               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);
+               }
                this->array.md_minor      = -1;
                this->array.major_version = -1;
                this->array.minor_version = -2;
@@ -3211,6 +3259,9 @@ static struct mdinfo *container_content_ddf(struct supertype *st, char *subarray
                for (pd = 0; pd < __be16_to_cpu(ddf->phys->used_pdes); pd++) {
                        struct mdinfo *dev;
                        struct dl *d;
+                       const struct vd_config *bvd;
+                       unsigned int iphys;
+                       __u64 *lba_offset;
                        int stt;
 
                        if (ddf->phys->entries[pd].refnum == 0xFFFFFFFF)
@@ -3222,7 +3273,8 @@ static struct mdinfo *container_content_ddf(struct supertype *st, char *subarray
                                continue;
 
                        i = get_pd_index_from_refnum(
-                               vc, ddf->phys->entries[pd].refnum, ddf->mppe);
+                               vc, ddf->phys->entries[pd].refnum,
+                               ddf->mppe, &bvd, &iphys);
                        if (i == NO_SUCH_REFNUM)
                                continue;
 
@@ -3248,8 +3300,9 @@ static struct mdinfo *container_content_ddf(struct supertype *st, char *subarray
                        dev->recovery_start = MaxSector;
 
                        dev->events = __be32_to_cpu(ddf->primary.seq);
-                       dev->data_offset = __be64_to_cpu(vc->lba_offset[i]);
-                       dev->component_size = __be64_to_cpu(vc->conf.blocks);
+                       lba_offset =  (__u64 *)&bvd->phys_refnum[ddf->mppe];
+                       dev->data_offset = __be64_to_cpu(lba_offset[iphys]);
+                       dev->component_size = __be64_to_cpu(bvd->blocks);
                        if (d->devname)
                                strcpy(dev->name, d->devname);
                }