]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super-ddf.c
Merge branch 'master' into devel-3.2
[thirdparty/mdadm.git] / super-ddf.c
index be15e43ebc9b9f74f1a94bd7ada1d564e9531162..8c5456834ff7c294f0d9c66580dbf10e827fdca1 100644 (file)
@@ -760,7 +760,7 @@ static int load_ddf_local(int fd, struct ddf_super *super,
 
 #ifndef MDASSEMBLE
 static int load_super_ddf_all(struct supertype *st, int fd,
-                             void **sbp, char *devname, int keep_fd);
+                             void **sbp, char *devname);
 #endif
 
 static void free_super_ddf(struct supertype *st);
@@ -772,14 +772,6 @@ static int load_super_ddf(struct supertype *st, int fd,
        struct ddf_super *super;
        int rv;
 
-#ifndef MDASSEMBLE
-       /* if 'fd' is a container, load metadata from all the devices */
-       if (load_super_ddf_all(st, fd, &st->sb, devname, 1) == 0)
-               return 0;
-#endif
-       if (st->subarray[0])
-               return 1; /* FIXME Is this correct */
-
        if (get_dev_size(fd, devname, &dsize) == 0)
                return 1;
 
@@ -844,26 +836,6 @@ static int load_super_ddf(struct supertype *st, int fd,
                return rv;
        }
 
-       if (st->subarray[0]) {
-               unsigned long val;
-               struct vcl *v;
-               char *ep;
-
-               val = strtoul(st->subarray, &ep, 10);
-               if (*ep != '\0') {
-                       free(super);
-                       return 1;
-               }
-
-               for (v = super->conflist; v; v = v->next)
-                       if (v->vcnum == val)
-                               super->currentconf = v;
-               if (!super->currentconf) {
-                       free(super);
-                       return 1;
-               }
-       }
-
        /* Should possibly check the sections .... */
 
        st->sb = super;
@@ -872,7 +844,6 @@ static int load_super_ddf(struct supertype *st, int fd,
                st->minor_version = 0;
                st->max_devs = 512;
        }
-       st->loaded_container = 0;
        return 0;
 
 }
@@ -924,6 +895,7 @@ static struct supertype *match_metadata_desc_ddf(char *arg)
 
        st = malloc(sizeof(*st));
        memset(st, 0, sizeof(*st));
+       st->container_dev = NoMdDev;
        st->ss = &super_ddf;
        st->max_devs = 512;
        st->minor_version = 0;
@@ -1199,7 +1171,7 @@ static void examine_super_ddf(struct supertype *st, char *homehost)
        examine_pds(sb);
 }
 
-static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info);
+static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info, char *map);
 
 static void uuid_from_super_ddf(struct supertype *st, int uuid[4]);
 
@@ -1209,7 +1181,7 @@ static void brief_examine_super_ddf(struct supertype *st, int verbose)
         */
        struct mdinfo info;
        char nbuf[64];
-       getinfo_super_ddf(st, &info);
+       getinfo_super_ddf(st, &info, NULL);
        fname_from_uuid(st, &info, nbuf, ':');
 
        printf("ARRAY metadata=ddf UUID=%s\n", nbuf + 5);
@@ -1223,7 +1195,7 @@ static void brief_examine_subarrays_ddf(struct supertype *st, int verbose)
        struct mdinfo info;
        unsigned int i;
        char nbuf[64];
-       getinfo_super_ddf(st, &info);
+       getinfo_super_ddf(st, &info, NULL);
        fname_from_uuid(st, &info, nbuf, ':');
 
        for (i = 0; i < __be16_to_cpu(ddf->virt->max_vdes); i++) {
@@ -1245,7 +1217,7 @@ static void export_examine_super_ddf(struct supertype *st)
 {
        struct mdinfo info;
        char nbuf[64];
-       getinfo_super_ddf(st, &info);
+       getinfo_super_ddf(st, &info, NULL);
        fname_from_uuid(st, &info, nbuf, ':');
        printf("MD_METADATA=ddf\n");
        printf("MD_LEVEL=container\n");
@@ -1271,7 +1243,7 @@ static void brief_detail_super_ddf(struct supertype *st)
 //     struct ddf_super *ddf = st->sb;
        struct mdinfo info;
        char nbuf[64];
-       getinfo_super_ddf(st, &info);
+       getinfo_super_ddf(st, &info, NULL);
        fname_from_uuid(st, &info, nbuf,':');
        printf(" UUID=%s", nbuf + 5);
 }
@@ -1358,14 +1330,15 @@ static void uuid_from_super_ddf(struct supertype *st, int uuid[4])
        memcpy(uuid, buf, 4*4);
 }
 
-static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info);
+static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info, char *map);
 
-static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info)
+static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info, char *map)
 {
        struct ddf_super *ddf = st->sb;
+       int map_disks = info->array.raid_disks;
 
        if (ddf->currentconf) {
-               getinfo_super_ddf_bvd(st, info);
+               getinfo_super_ddf_bvd(st, info, map);
                return;
        }
 
@@ -1409,17 +1382,29 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info)
 
        uuid_from_super_ddf(st, info->uuid);
 
+       if (map) {
+               int i;
+               for (i = 0 ; i < map_disks; i++) {
+                       if (i < info->array.raid_disks &&
+                           (__be16_to_cpu(ddf->phys->entries[i].state) & DDF_Online) &&
+                           !(__be16_to_cpu(ddf->phys->entries[i].state) & DDF_Failed))
+                               map[i] = 1;
+                       else
+                               map[i] = 0;
+               }
+       }
 }
 
 static int rlq_to_layout(int rlq, int prl, int raiddisks);
 
-static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info)
+static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info, char *map)
 {
        struct ddf_super *ddf = st->sb;
        struct vcl *vc = ddf->currentconf;
        int cd = ddf->currentdev;
        int j;
        struct dl *dl;
+       int map_disks = info->array.raid_disks;
 
        /* FIXME this returns BVD info - what if we want SVD ?? */
 
@@ -1471,9 +1456,9 @@ static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info)
 
        info->array.major_version = -1;
        info->array.minor_version = -2;
-       sprintf(info->text_version, "/%s/%s",
+       sprintf(info->text_version, "/%s/%d",
                devnum2devname(st->container_dev),
-               st->subarray);
+               info->container_member);
        info->safe_mode_delay = 200;
 
        memcpy(info->name, ddf->virt->entries[info->container_member].name, 16);
@@ -1481,6 +1466,18 @@ static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info)
        for(j=0; j<16; j++)
                if (info->name[j] == ' ')
                        info->name[j] = 0;
+
+       if (map)
+               for (j = 0; j < map_disks; j++) {
+                       map[j] = 0;
+                       if (j <  info->array.raid_disks) {
+                               int i = find_phys(ddf, vc->conf.phys_refnum[j]);
+                               if (i >= 0 && 
+                                   (__be16_to_cpu(ddf->phys->entries[i].state) & DDF_Online) &&
+                                   !(__be16_to_cpu(ddf->phys->entries[i].state) & DDF_Failed))
+                                       map[i] = 1;
+                       }
+               }
 }
 
 
@@ -1526,28 +1523,27 @@ static int update_super_ddf(struct supertype *st, struct mdinfo *info,
 
        if (strcmp(update, "grow") == 0) {
                /* FIXME */
-       }
-       if (strcmp(update, "resync") == 0) {
+       } else if (strcmp(update, "resync") == 0) {
 //             info->resync_checkpoint = 0;
-       }
-       /* We ignore UUID updates as they make even less sense
-        * with DDF
-        */
-       if (strcmp(update, "homehost") == 0) {
+       } else if (strcmp(update, "homehost") == 0) {
                /* homehost is stored in controller->vendor_data,
                 * or it is when we are the vendor
                 */
 //             if (info->vendor_is_local)
 //                     strcpy(ddf->controller.vendor_data, homehost);
-       }
-       if (strcmp(update, "name") == 0) {
+               rv = -1;
+       } else if (strcmp(update, "name") == 0) {
                /* name is stored in virtual_entry->name */
 //             memset(ve->name, ' ', 16);
 //             strncpy(ve->name, info->name, 16);
-       }
-       if (strcmp(update, "_reshape_progress") == 0) {
+               rv = -1;
+       } else if (strcmp(update, "_reshape_progress") == 0) {
                /* We don't support reshape yet */
-       }
+       } else if (strcmp(update, "assemble") == 0 ) {
+               /* Do nothing, just succeed */
+               rv = 0;
+       } else
+               rv = -1;
 
 //     update_all_csum(ddf);
 
@@ -2023,7 +2019,6 @@ static int init_super_ddf_bvd(struct supertype *st,
        }
        vcl->lba_offset = (__u64*) &vcl->conf.phys_refnum[ddf->mppe];
        vcl->vcnum = venum;
-       sprintf(st->subarray, "%d", venum);
        vcl->block_sizes = NULL; /* FIXME not for CONCAT */
 
        vc = &vcl->conf;
@@ -2289,7 +2284,7 @@ static int add_to_super_ddf(struct supertype *st,
 
 static unsigned char null_conf[4096+512];
 
-static int __write_init_super_ddf(struct supertype *st, int do_close)
+static int __write_init_super_ddf(struct supertype *st)
 {
 
        struct ddf_super *ddf = st->sb;
@@ -2396,12 +2391,6 @@ static int __write_init_super_ddf(struct supertype *st, int do_close)
                successes++;
        }
 
-       if (do_close)
-               for (d = ddf->dlist; d; d=d->next) {
-                       close(d->fd);
-                       d->fd = -1;
-               }
-
        return attempts != successes;
 }
 
@@ -2454,7 +2443,7 @@ static int write_init_super_ddf(struct supertype *st)
                struct dl *d;
                for (d = ddf->dlist; d; d=d->next)
                        while (Kill(d->devname, NULL, 0, 1, 1) == 0);
-               return __write_init_super_ddf(st, 1);
+               return __write_init_super_ddf(st);
        }
 }
 
@@ -2568,13 +2557,13 @@ validate_geometry_ddf_container(struct supertype *st,
 
 static int validate_geometry_ddf_bvd(struct supertype *st,
                                     int level, int layout, int raiddisks,
-                                    int chunk, unsigned long long size,
+                                    int *chunk, unsigned long long size,
                                     char *dev, unsigned long long *freesize,
                                     int verbose);
 
 static int validate_geometry_ddf(struct supertype *st,
                                 int level, int layout, int raiddisks,
-                                int chunk, unsigned long long size,
+                                int *chunk, unsigned long long size,
                                 char *dev, unsigned long long *freesize,
                                 int verbose)
 {
@@ -2589,10 +2578,14 @@ static int validate_geometry_ddf(struct supertype *st,
         * If given BVDs, we make an SVD, changing all the GUIDs in the process.
         */
 
+       if (chunk && *chunk == UnSet)
+               *chunk = DEFAULT_CHUNK;
+
+
        if (level == LEVEL_CONTAINER) {
                /* Must be a fresh device to add to a container */
                return validate_geometry_ddf_container(st, level, layout,
-                                                      raiddisks, chunk,
+                                                      raiddisks, chunk?*chunk:0,
                                                       size, dev, freesize,
                                                       verbose);
        }
@@ -2619,7 +2612,7 @@ static int validate_geometry_ddf(struct supertype *st,
                         * chosen so that add_to_super/getinfo_super
                         * can return them.
                         */
-                       return reserve_space(st, raiddisks, size, chunk, freesize);
+                       return reserve_space(st, raiddisks, size, chunk?*chunk:0, freesize);
                }
                return 1;
        }
@@ -2683,7 +2676,7 @@ static int validate_geometry_ddf(struct supertype *st,
                 * and try to create a bvd
                 */
                struct ddf_super *ddf;
-               if (load_super_ddf_all(st, cfd, (void **)&ddf, NULL, 1) == 0) {
+               if (load_super_ddf_all(st, cfd, (void **)&ddf, NULL) == 0) {
                        st->sb = ddf;
                        st->container_dev = fd2devnum(cfd);
                        close(cfd);
@@ -2736,7 +2729,7 @@ validate_geometry_ddf_container(struct supertype *st,
 
 static int validate_geometry_ddf_bvd(struct supertype *st,
                                     int level, int layout, int raiddisks,
-                                    int chunk, unsigned long long size,
+                                    int *chunk, unsigned long long size,
                                     char *dev, unsigned long long *freesize,
                                     int verbose)
 {
@@ -2830,7 +2823,7 @@ static int validate_geometry_ddf_bvd(struct supertype *st,
 }
 
 static int load_super_ddf_all(struct supertype *st, int fd,
-                             void **sbp, char *devname, int keep_fd)
+                             void **sbp, char *devname)
 {
        struct mdinfo *sra;
        struct ddf_super *super;
@@ -2886,49 +2879,35 @@ static int load_super_ddf_all(struct supertype *st, int fd,
                int rv;
 
                sprintf(nm, "%d:%d", sd->disk.major, sd->disk.minor);
-               dfd = dev_open(nm, keep_fd? O_RDWR : O_RDONLY);
+               dfd = dev_open(nm, O_RDWR);
                if (dfd < 0)
                        return 2;
                rv = load_ddf_headers(dfd, super, NULL);
                if (rv == 0)
-                       rv = load_ddf_local(dfd, super, NULL, keep_fd);
-               if (!keep_fd) close(dfd);
+                       rv = load_ddf_local(dfd, super, NULL, 1);
                if (rv)
                        return 1;
        }
-       if (st->subarray[0]) {
-               unsigned long val;
-               struct vcl *v;
-               char *ep;
-
-               val = strtoul(st->subarray, &ep, 10);
-               if (*ep != '\0') {
-                       free(super);
-                       return 1;
-               }
-
-               for (v = super->conflist; v; v = v->next)
-                       if (v->vcnum == val)
-                               super->currentconf = v;
-               if (!super->currentconf) {
-                       free(super);
-                       return 1;
-               }
-       }
 
        *sbp = super;
        if (st->ss == NULL) {
                st->ss = &super_ddf;
                st->minor_version = 0;
                st->max_devs = 512;
-               st->container_dev = fd2devnum(fd);
        }
-       st->loaded_container = 1;
+       st->container_dev = fd2devnum(fd);
        return 0;
 }
+
+static int load_container_ddf(struct supertype *st, int fd,
+                             char *devname)
+{
+       return load_super_ddf_all(st, fd, &st->sb, devname);
+}
+
 #endif /* MDASSEMBLE */
 
-static struct mdinfo *container_content_ddf(struct supertype *st)
+static struct mdinfo *container_content_ddf(struct supertype *st, char *subarray)
 {
        /* Given a container loaded by load_super_ddf_all,
         * extract information about all the arrays into
@@ -2947,6 +2926,13 @@ static struct mdinfo *container_content_ddf(struct supertype *st)
                unsigned int i;
                unsigned int j;
                struct mdinfo *this;
+               char *ep;
+
+               if (subarray &&
+                   (strtoul(subarray, &ep, 10) != vc->vcnum ||
+                    *ep != '\0'))
+                       continue;
+
                this = malloc(sizeof(*this));
                memset(this, 0, sizeof(*this));
                this->next = rest;
@@ -3293,7 +3279,7 @@ static void ddf_sync_metadata(struct supertype *st)
        if (!ddf->updates_pending)
                return;
        ddf->updates_pending = 0;
-       __write_init_super_ddf(st, 0);
+       __write_init_super_ddf(st);
        dprintf("ddf: sync_metadata\n");
 }
 
@@ -3717,6 +3703,15 @@ static int ddf_level_to_layout(int level)
        }
 }
 
+static void default_geometry_ddf(struct supertype *st, int *level, int *layout, int *chunk)
+{
+       if (level && *level == UnSet)
+               *level = LEVEL_CONTAINER;
+
+       if (level && layout && *layout == UnSet)
+               *layout = ddf_level_to_layout(*level);
+}
+
 struct superswitch super_ddf = {
 #ifndef        MDASSEMBLE
        .examine_super  = examine_super_ddf,
@@ -3728,6 +3723,7 @@ struct superswitch super_ddf = {
        .validate_geometry = validate_geometry_ddf,
        .write_init_super = write_init_super_ddf,
        .add_to_super   = add_to_super_ddf,
+       .load_container = load_container_ddf,
 #endif
        .match_home     = match_home_ddf,
        .uuid_from_super= uuid_from_super_ddf,
@@ -3744,7 +3740,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,
+       .default_geometry = default_geometry_ddf,
 
        .external       = 1,