]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super-ddf.c
teach imsm and ddf what st->subarray means at load_super time
[thirdparty/mdadm.git] / super-ddf.c
index f621f4df3922ac43b5932a16a7e40cc982006538..517a586420ae44130d46822bf2a03139803af115 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * mdadm - manage Linux "md" devices aka RAID arrays.
  *
- * Copyright (C) 2006-2007 Neil Brown <neilb@suse.de>
+ * Copyright (C) 2006-2009 Neil Brown <neilb@suse.de>
  *
  *
  *    This program is free software; you can redistribute it and/or modify
@@ -643,6 +643,7 @@ static int load_ddf_local(int fd, struct ddf_super *super,
        struct stat stb;
        char *conf;
        int i;
+       int confsec;
        int vnum;
        int max_virt_disks = __be16_to_cpu(super->active->max_vd_entries);
        unsigned long long dsize;
@@ -693,11 +694,11 @@ static int load_ddf_local(int fd, struct ddf_super *super,
                            0);
 
        vnum = 0;
-       for (i = 0;
-            i < __be32_to_cpu(super->active->config_section_length);
-            i += super->conf_rec_len) {
+       for (confsec = 0;
+            confsec < __be32_to_cpu(super->active->config_section_length);
+            confsec += super->conf_rec_len) {
                struct vd_config *vd =
-                       (struct vd_config *)((char*)conf + i*512);
+                       (struct vd_config *)((char*)conf + confsec*512);
                struct vcl *vcl;
 
                if (vd->magic == DDF_SPARE_ASSIGN_MAGIC) {
@@ -781,22 +782,20 @@ static int load_super_ddf(struct supertype *st, int fd,
 
        /* 32M is a lower bound */
        if (dsize <= 32*1024*1024) {
-               if (devname) {
+               if (devname)
                        fprintf(stderr,
                                Name ": %s is too small for ddf: "
                                "size is %llu sectors.\n",
                                devname, dsize>>9);
-                       return 1;
-               }
+               return 1;
        }
        if (dsize & 511) {
-               if (devname) {
+               if (devname)
                        fprintf(stderr,
                                Name ": %s is an odd size for ddf: "
                                "size is %llu bytes.\n",
                                devname, dsize);
-                       return 1;
-               }
+               return 1;
        }
 
        if (posix_memalign((void**)&super, 512, sizeof(*super))!= 0) {
@@ -836,6 +835,18 @@ static int load_super_ddf(struct supertype *st, int fd,
                return rv;
        }
 
+       if (st->subarray[0]) {
+               struct vcl *v;
+
+               for (v = super->conflist; v; v = v->next)
+                       if (v->vcnum == atoi(st->subarray))
+                               super->currentconf = v;
+               if (!super->currentconf) {
+                       free(super);
+                       return 1;
+               }
+       }
+
        /* Should possibly check the sections .... */
 
        st->sb = super;
@@ -1000,7 +1011,7 @@ static void print_guid(char *guid, int tstamp)
                printf("%02X", guid[i]&255);
        }
 
-       printf(" (");
+       printf("\n                  (");
        while (l && guid[l-1] == ' ')
                l--;
        for (i=0 ; i<l ; i++) {
@@ -1062,9 +1073,9 @@ static void examine_vd(int n, struct ddf_super *sb, char *guid)
                               map_num(ddf_sec_level, vc->srl) ?: "-unknown-");
                }
                printf("  Device Size[%d] : %llu\n", n,
-                      __be64_to_cpu(vc->blocks)/2);
+                      (unsigned long long)__be64_to_cpu(vc->blocks)/2);
                printf("   Array Size[%d] : %llu\n", n,
-                      __be64_to_cpu(vc->array_blocks)/2);
+                      (unsigned long long)__be64_to_cpu(vc->array_blocks)/2);
        }
 }
 
@@ -1100,7 +1111,7 @@ static void examine_pds(struct ddf_super *sb)
        int i;
        struct dl *dl;
        printf(" Physical Disks : %d\n", cnt);
-       printf("      Number    RefNo    Size       Device    Type/State\n");
+       printf("      Number    RefNo      Size       Device      Type/State\n");
 
        for (i=0 ; i<cnt ; i++) {
                struct phys_disk_entry *pd = &sb->phys->entries[i];
@@ -1111,18 +1122,19 @@ static void examine_pds(struct ddf_super *sb)
                //printf("\n");
                printf("       %3d    %08x  ", i,
                       __be32_to_cpu(pd->refnum));
-               printf("%lluK ",  __be64_to_cpu(pd->config_size)>>1);
+               printf("%8lluK ", 
+                      (unsigned long long)__be64_to_cpu(pd->config_size)>>1);
                for (dl = sb->dlist; dl ; dl = dl->next) {
                        if (dl->disk.refnum == pd->refnum) {
                                char *dv = map_dev(dl->major, dl->minor, 0);
                                if (dv) {
-                                       printf("%-10s", dv);
+                                       printf("%-15s", dv);
                                        break;
                                }
                        }
                }
                if (!dl)
-                       printf("%10s","");
+                       printf("%15s","");
                printf(" %s%s%s%s%s",
                       (type&2) ? "active":"",
                       (type&4) ? "Global-Spare":"",
@@ -1162,7 +1174,7 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info);
 
 static void uuid_from_super_ddf(struct supertype *st, int uuid[4]);
 
-static void brief_examine_super_ddf(struct supertype *st)
+static void brief_examine_super_ddf(struct supertype *st, int verbose)
 {
        /* We just write a generic DDF ARRAY entry
         */
@@ -1172,7 +1184,6 @@ static void brief_examine_super_ddf(struct supertype *st)
        char nbuf[64];
        getinfo_super_ddf(st, &info);
        fname_from_uuid(st, &info, nbuf, ':');
-       printf("ARRAY metadata=ddf UUID=%s\n", nbuf + 5);
 
        for (i=0; i<__be16_to_cpu(ddf->virt->max_vdes); i++) {
                struct virtual_entry *ve = &ddf->virt->entries[i];
@@ -1187,7 +1198,20 @@ static void brief_examine_super_ddf(struct supertype *st)
                printf("ARRAY container=%s member=%d UUID=%s\n",
                       nbuf+5, i, nbuf1+5);
        }
+       printf("ARRAY metadata=ddf UUID=%s\n", nbuf + 5);
+}
+
+static void export_examine_super_ddf(struct supertype *st)
+{
+       struct mdinfo info;
+       char nbuf[64];
+       getinfo_super_ddf(st, &info);
+       fname_from_uuid(st, &info, nbuf, ':');
+       printf("MD_METADATA=ddf\n");
+       printf("MD_LEVEL=container\n");
+       printf("MD_UUID=%s\n", nbuf+5);
 }
+       
 
 static void detail_super_ddf(struct supertype *st, char *homehost)
 {
@@ -1323,6 +1347,7 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info)
                info->component_size = ddf->dlist->size - info->data_offset;
        } else {
                info->disk.number = -1;
+               info->disk.raid_disk = -1;
 //             info->disk.raid_disk = find refnum in the table and use index;
        }
        info->disk.state = (1 << MD_DISK_SYNC);
@@ -1361,6 +1386,7 @@ static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info)
                __be32_to_cpu(*(__u32*)(vc->conf.guid+16));
        info->array.utime         = DECADE + __be32_to_cpu(vc->conf.timestamp);
        info->array.chunk_size    = 512 << vc->conf.chunk_shift;
+       info->custom_array_size   = 0;
 
        if (cd >= 0 && cd < ddf->mppe) {
                info->data_offset         = __be64_to_cpu(vc->lba_offset[cd]);
@@ -1481,10 +1507,20 @@ static int update_super_ddf(struct supertype *st, struct mdinfo *info,
        return rv;
 }
 
+__u32 random32(void)
+{
+       __u32 rv;
+       int rfd = open("/dev/urandom", O_RDONLY);
+       if (rfd < 0 || read(rfd, &rv, 4) != 4)
+               rv = random();
+       if (rfd >= 0)
+               close(rfd);
+       return rv;
+}
+
 static void make_header_guid(char *guid)
 {
        __u32 stamp;
-       int rfd;
        /* Create a DDF Header of Virtual Disk GUID */
 
        /* 24 bytes of fiction required.
@@ -1499,11 +1535,8 @@ static void make_header_guid(char *guid)
        memcpy(guid+12, &stamp, 4);
        stamp = __cpu_to_be32(time(0) - DECADE);
        memcpy(guid+16, &stamp, 4);
-       rfd = open("/dev/urandom", O_RDONLY);
-       if (rfd < 0 || read(rfd, &stamp, 4) != 4)
-               stamp = random();
+       stamp = random32();
        memcpy(guid+20, &stamp, 4);
-       if (rfd >= 0) close(rfd);
 }
 
 static int init_super_ddf_bvd(struct supertype *st,
@@ -1759,20 +1792,25 @@ static int layout_to_rlq(int level, int layout, int raiddisks)
                }
                break;
        case 5:
-       case 6:
                switch(layout) {
                case ALGORITHM_LEFT_ASYMMETRIC:
                        return DDF_RAID5_N_RESTART;
                case ALGORITHM_RIGHT_ASYMMETRIC:
-                       if (level == 5)
-                               return DDF_RAID5_0_RESTART;
-                       else
-                               return DDF_RAID6_0_RESTART;
+                       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;
 }
@@ -1807,11 +1845,11 @@ static int rlq_to_layout(int rlq, int prl, int raiddisks)
        case DDF_RAID6:
                switch(rlq) {
                case DDF_RAID5_N_RESTART:
-                       return ALGORITHM_LEFT_ASYMMETRIC;
+                       return ALGORITHM_ROTATING_N_RESTART;
                case DDF_RAID6_0_RESTART:
-                       return ALGORITHM_RIGHT_ASYMMETRIC;
+                       return ALGORITHM_ROTATING_ZERO_RESTART;
                case DDF_RAID5_N_CONTINUE:
-                       return ALGORITHM_LEFT_SYMMETRIC;
+                       return ALGORITHM_ROTATING_N_CONTINUE;
                default:
                        return -1;
                }
@@ -1977,7 +2015,7 @@ static int init_super_ddf_bvd(struct supertype *st,
        memset(vc->vendor, 0xff, 32);
 
        memset(vc->phys_refnum, 0xff, 4*ddf->mppe);
-       memset(vc->phys_refnum+(ddf->mppe * 4), 0x00, 8*ddf->mppe);
+       memset(vc->phys_refnum+ddf->mppe, 0x00, 8*ddf->mppe);
 
        vcl->next = ddf->conflist;
        ddf->conflist = vcl;
@@ -2131,12 +2169,12 @@ static int add_to_super_ddf(struct supertype *st,
        tm = localtime(&now);
        sprintf(dd->disk.guid, "%8s%04d%02d%02d",
                T10, tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday);
-       *(__u32*)(dd->disk.guid + 16) = random();
-       *(__u32*)(dd->disk.guid + 20) = random();
+       *(__u32*)(dd->disk.guid + 16) = random32();
+       *(__u32*)(dd->disk.guid + 20) = random32();
 
        do {
                /* Cannot be bothered finding a CRC of some irrelevant details*/
-               dd->disk.refnum = random();
+               dd->disk.refnum = random32();
                for (i = __be16_to_cpu(ddf->active->max_pd_entries) - 1;
                     i >= 0; i--)
                        if (ddf->phys->entries[i].refnum == dd->disk.refnum)
@@ -2628,6 +2666,8 @@ validate_geometry_ddf_container(struct supertype *st,
        close(fd);
 
        *freesize = avail_size_ddf(st, ldsize >> 9);
+       if (*freesize == 0)
+               return 0;
 
        return 1;
 }
@@ -2734,8 +2774,14 @@ static int load_super_ddf_all(struct supertype *st, int fd,
        int seq;
        char nm[20];
        int dfd;
+       int devnum = fd2devnum(fd);
+       enum sysfs_read_flags flags;
 
-       sra = sysfs_read(fd, 0, GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE);
+       flags = GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE;
+       if (mdmon_running(devnum))
+               flags |= SKIP_GONE_DEVS;
+
+       sra = sysfs_read(fd, 0, flags);
        if (!sra)
                return 1;
        if (sra->array.major_version != -1 ||
@@ -2892,7 +2938,8 @@ static struct mdinfo *container_content_ddf(struct supertype *st)
                                if (d->disk.refnum == vc->conf.phys_refnum[i])
                                        break;
                        if (d == NULL)
-                               break;
+                               /* Haven't found that one yet, maybe there are others */
+                               continue;
 
                        dev = malloc(sizeof(*dev));
                        memset(dev, 0, sizeof(*dev));
@@ -3531,10 +3578,28 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a,
 }
 #endif /* MDASSEMBLE */
 
+static int ddf_level_to_layout(int level)
+{
+       switch(level) {
+       case 0:
+       case 1:
+               return 0;
+       case 5:
+               return ALGORITHM_LEFT_SYMMETRIC;
+       case 6:
+               return ALGORITHM_ROTATING_N_CONTINUE;
+       case 10:
+               return 0x102;
+       default:
+               return UnSet;
+       }
+}
+
 struct superswitch super_ddf = {
 #ifndef        MDASSEMBLE
        .examine_super  = examine_super_ddf,
        .brief_examine_super = brief_examine_super_ddf,
+       .export_examine_super = export_examine_super_ddf,
        .detail_super   = detail_super_ddf,
        .brief_detail_super = brief_detail_super_ddf,
        .validate_geometry = validate_geometry_ddf,
@@ -3556,6 +3621,7 @@ struct superswitch super_ddf = {
        .free_super     = free_super_ddf,
        .match_metadata_desc = match_metadata_desc_ddf,
        .container_content = container_content_ddf,
+       .default_layout = ddf_level_to_layout,
 
        .external       = 1,