]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super-ddf.c
Provide a mdstat_ent to subarray helper
[thirdparty/mdadm.git] / super-ddf.c
index fe83642f779c13f0ad15c52f3a2329b62c0c5fca..98c9d58b4b486c17a1ac15406768357d28c08cba 100644 (file)
@@ -396,7 +396,7 @@ struct ddf_super {
        struct phys_disk        *phys;
        struct virtual_disk     *virt;
        int pdsize, vdsize;
-       int max_part, mppe, conf_rec_len;
+       unsigned int max_part, mppe, conf_rec_len;
        int currentdev;
        int updates_pending;
        struct vcl {
@@ -406,7 +406,7 @@ struct ddf_super {
                                struct vcl      *next;
                                __u64           *lba_offset; /* location in 'conf' of
                                                              * the lba table */
-                               int     vcnum; /* index into ->virt */
+                               unsigned int    vcnum; /* index into ->virt */
                                __u64           *block_sizes; /* NULL if all the same */
                        };
                };
@@ -440,7 +440,7 @@ struct ddf_super {
 #endif
 
 
-static int calc_crc(void *buf, int len)
+static unsigned int calc_crc(void *buf, int len)
 {
        /* crcs are always at the same place as in the ddf_header */
        struct ddf_header *ddf = buf;
@@ -522,12 +522,12 @@ static void *load_section(int fd, struct ddf_super *super, void *buf,
        else
                offset += __be64_to_cpu(super->active->secondary_lba);
 
-       if (lseek64(fd, offset<<9, 0) != (offset<<9)) {
+       if ((unsigned long long)lseek64(fd, offset<<9, 0) != (offset<<9)) {
                if (dofree)
                        free(buf);
                return NULL;
        }
-       if (read(fd, buf, len<<9) != (len<<9)) {
+       if ((unsigned long long)read(fd, buf, len<<9) != (len<<9)) {
                if (dofree)
                        free(buf);
                return NULL;
@@ -642,10 +642,10 @@ static int load_ddf_local(int fd, struct ddf_super *super,
        struct dl *dl;
        struct stat stb;
        char *conf;
-       int i;
-       int confsec;
+       unsigned int i;
+       unsigned int confsec;
        int vnum;
-       int max_virt_disks = __be16_to_cpu(super->active->max_vd_entries);
+       unsigned int max_virt_disks = __be16_to_cpu(super->active->max_vd_entries);
        unsigned long long dsize;
 
        /* First the local disk info */
@@ -673,11 +673,11 @@ static int load_ddf_local(int fd, struct ddf_super *super,
        if (get_dev_size(fd, devname, &dsize))
                dl->size = dsize >> 9;
        dl->spare = NULL;
-       for (i=0 ; i < super->max_part ; i++)
+       for (i = 0 ; i < super->max_part ; i++)
                dl->vlist[i] = NULL;
        super->dlist = dl;
        dl->pdnum = -1;
-       for (i=0; i < __be16_to_cpu(super->active->max_pd_entries); i++)
+       for (i = 0; i < __be16_to_cpu(super->active->max_pd_entries); i++)
                if (memcmp(super->phys->entries[i].guid,
                           dl->disk.guid, DDF_GUID_LEN) == 0)
                        dl->pdnum = i;
@@ -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);
@@ -774,15 +774,17 @@ static int load_super_ddf(struct supertype *st, int fd,
 
 #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)
+       if (load_super_ddf_all(st, fd, &st->sb, devname) == 0)
                return 0;
 #endif
-       if (st->subarray[0])
-               return 1; /* FIXME Is this correct */
 
        if (get_dev_size(fd, devname, &dsize) == 0)
                return 1;
 
+       if (test_partition(fd))
+               /* DDF is not allowed on partitions */
+               return 1;
+
        /* 32M is a lower bound */
        if (dsize <= 32*1024*1024) {
                if (devname)
@@ -840,18 +842,6 @@ 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;
@@ -860,7 +850,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;
 
 }
@@ -903,6 +892,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;
@@ -1042,7 +1032,7 @@ static void examine_vd(int n, struct ddf_super *sb, char *guid)
        struct vcl *vcl;
 
        for (vcl = sb->conflist ; vcl ; vcl = vcl->next) {
-               int i;
+               unsigned int i;
                struct vd_config *vc = &vcl->conf;
 
                if (calc_crc(vc, crl*512) != vc->crc)
@@ -1053,7 +1043,7 @@ static void examine_vd(int n, struct ddf_super *sb, char *guid)
                /* Ok, we know about this VD, let's give more details */
                printf(" Raid Devices[%d] : %d (", n,
                       __be16_to_cpu(vc->prim_elmnt_count));
-               for (i=0; i<__be16_to_cpu(vc->prim_elmnt_count); i++) {
+               for (i = 0; i < __be16_to_cpu(vc->prim_elmnt_count); i++) {
                        int j;
                        int cnt = __be16_to_cpu(sb->phys->used_pdes);
                        for (j=0; j<cnt; j++)
@@ -1175,7 +1165,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]);
 
@@ -1185,7 +1175,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);
@@ -1197,12 +1187,12 @@ static void brief_examine_subarrays_ddf(struct supertype *st, int verbose)
         */
        struct ddf_super *ddf = st->sb;
        struct mdinfo info;
-       int i;
+       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++) {
+       for (i = 0; i < __be16_to_cpu(ddf->virt->max_vdes); i++) {
                struct virtual_entry *ve = &ddf->virt->entries[i];
                struct vcl vcl;
                char nbuf1[64];
@@ -1221,7 +1211,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");
@@ -1247,7 +1237,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);
 }
@@ -1260,7 +1250,11 @@ static int match_home_ddf(struct supertype *st, char *homehost)
         * the hostname
         */
        struct ddf_super *ddf = st->sb;
-       int len = strlen(homehost);
+       unsigned int len;
+
+       if (!homehost)
+               return 0;
+       len = strlen(homehost);
 
        return (memcmp(ddf->controller.guid, T10, 8) == 0 &&
                len < sizeof(ddf->controller.vendor_data) &&
@@ -1269,7 +1263,7 @@ static int match_home_ddf(struct supertype *st, char *homehost)
 }
 
 #ifndef MDASSEMBLE
-static struct vd_config *find_vdcr(struct ddf_super *ddf, int inst)
+static struct vd_config *find_vdcr(struct ddf_super *ddf, unsigned int inst)
 {
        struct vcl *v;
 
@@ -1285,8 +1279,8 @@ static int find_phys(struct ddf_super *ddf, __u32 phys_refnum)
        /* Find the entry in phys_disk which has the given refnum
         * and return it's index
         */
-       int i;
-       for (i=0; i < __be16_to_cpu(ddf->phys->max_pdes); i++)
+       unsigned int i;
+       for (i = 0; i < __be16_to_cpu(ddf->phys->max_pdes); i++)
                if (ddf->phys->entries[i].refnum == phys_refnum)
                        return i;
        return -1;
@@ -1330,14 +1324,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;
        }
 
@@ -1349,6 +1344,7 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info)
                                                         (ddf->anchor.guid+16));
        info->array.utime         = 0;
        info->array.chunk_size    = 0;
+       info->container_enough    = 1;
 
 
        info->disk.major = 0;
@@ -1369,6 +1365,7 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info)
        info->disk.state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
 
 
+       info->recovery_start = MaxSector;
        info->reshape_active = 0;
        info->name[0] = 0;
 
@@ -1379,17 +1376,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 ?? */
 
@@ -1404,7 +1413,7 @@ static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info)
        info->array.chunk_size    = 512 << vc->conf.chunk_shift;
        info->custom_array_size   = 0;
 
-       if (cd >= 0 && cd < ddf->mppe) {
+       if (cd >= 0 && (unsigned)cd < ddf->mppe) {
                info->data_offset         = __be64_to_cpu(vc->lba_offset[cd]);
                if (vc->block_sizes)
                        info->component_size = vc->block_sizes[cd];
@@ -1427,22 +1436,23 @@ static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info)
 
        info->container_member = ddf->currentconf->vcnum;
 
+       info->recovery_start = MaxSector;
        info->resync_start = 0;
+       info->reshape_active = 0;
        if (!(ddf->virt->entries[info->container_member].state
              & DDF_state_inconsistent)  &&
            (ddf->virt->entries[info->container_member].init_state
             & DDF_initstate_mask)
            == DDF_init_full)
-               info->resync_start = ~0ULL;
+               info->resync_start = MaxSector;
 
        uuid_from_super_ddf(st, info->uuid);
 
-       info->container_member = atoi(st->subarray);
        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);
@@ -1450,6 +1460,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;
+                       }
+               }
 }
 
 
@@ -1495,28 +1517,24 @@ 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;
+       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;
+       if (strcmp(update, "_reshape_progress") == 0) {
                /* We don't support reshape yet */
-       }
+       } else
+               rv = -1;
 
 //     update_all_csum(ddf);
 
@@ -1739,7 +1757,7 @@ static int init_super_ddf(struct supertype *st,
 
        memset(pd, 0xff, pdsize);
        memset(pd, 0, sizeof(*pd));
-       pd->magic = DDF_PHYS_DATA_MAGIC;
+       pd->magic = DDF_PHYS_RECORDS_MAGIC;
        pd->used_pdes = __cpu_to_be16(0);
        pd->max_pdes = __cpu_to_be16(max_phys_disks);
        memset(pd->pad, 0xff, 52);
@@ -1889,7 +1907,7 @@ FIXME ignore DDF_Legacy devices?
         */
        struct extent *rv;
        int n = 0;
-       int i, j;
+       unsigned int i, j;
 
        rv = malloc(sizeof(struct extent) * (ddf->max_part + 2));
        if (!rv)
@@ -1899,7 +1917,7 @@ FIXME ignore DDF_Legacy devices?
                struct vcl *v = dl->vlist[i];
                if (v == NULL)
                        continue;
-               for (j=0; j < v->conf.prim_elmnt_count; j++)
+               for (j = 0; j < v->conf.prim_elmnt_count; j++)
                        if (v->conf.phys_refnum[j] == dl->disk.refnum) {
                                /* This device plays role 'j' in  'v'. */
                                rv[n].start = __be64_to_cpu(v->lba_offset[j]);
@@ -1927,7 +1945,7 @@ static int init_super_ddf_bvd(struct supertype *st,
         * We need to create a new vd_config and a new virtual_entry
         */
        struct ddf_super *ddf = st->sb;
-       int venum;
+       unsigned int venum;
        struct virtual_entry *ve;
        struct vcl *vcl;
        struct vd_config *vc;
@@ -1979,7 +1997,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;
@@ -2048,8 +2065,8 @@ static void add_to_super_ddf_bvd(struct supertype *st,
        struct ddf_super *ddf = st->sb;
        struct vd_config *vc;
        __u64 *lba_offset;
-       int working;
-       int i;
+       unsigned int working;
+       unsigned int i;
        unsigned long long blocks, pos, esize;
        struct extent *ex;
 
@@ -2094,7 +2111,7 @@ static void add_to_super_ddf_bvd(struct supertype *st,
        vc->phys_refnum[dk->raid_disk] = dl->disk.refnum;
        lba_offset[dk->raid_disk] = __cpu_to_be64(pos);
 
-       for (i=0; i < ddf->max_part ; i++)
+       for (i = 0; i < ddf->max_part ; i++)
                if (dl->vlist[i] == NULL)
                        break;
        if (i == ddf->max_part)
@@ -2111,7 +2128,7 @@ static void add_to_super_ddf_bvd(struct supertype *st,
         */
        working = 0;
 
-       for (i=0; i < __be16_to_cpu(vc->prim_elmnt_count); i++)
+       for (i = 0; i < __be16_to_cpu(vc->prim_elmnt_count); i++)
                if (vc->phys_refnum[i] != 0xffffffff)
                        working++;
 
@@ -2145,7 +2162,7 @@ static int add_to_super_ddf(struct supertype *st,
        struct tm *tm;
        unsigned long long size;
        struct phys_disk_entry *pde;
-       int n, i;
+       unsigned int n, i;
        struct stat stb;
 
        if (ddf->currentconf) {
@@ -2181,11 +2198,11 @@ static int add_to_super_ddf(struct supertype *st,
        do {
                /* Cannot be bothered finding a CRC of some irrelevant details*/
                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)
+               for (i = __be16_to_cpu(ddf->active->max_pd_entries);
+                    i > 0; i--)
+                       if (ddf->phys->entries[i-1].refnum == dd->disk.refnum)
                                break;
-       } while (i >= 0);
+       } while (i > 0);
 
        dd->disk.forced_ref = 1;
        dd->disk.forced_guid = 1;
@@ -2328,7 +2345,7 @@ static int __write_init_super_ddf(struct supertype *st, int do_close)
                                char *null_aligned = (char*)((((unsigned long)null_conf)+511)&~511UL);
                                if (null_conf[0] != 0xff)
                                        memset(null_conf, 0xff, sizeof(null_conf));
-                               int togo = conf_size;
+                               unsigned int togo = conf_size;
                                while (togo > sizeof(null_conf)-512) {
                                        if (write(fd, null_aligned, sizeof(null_conf)-512) < 0)
                                                break;
@@ -2406,8 +2423,12 @@ static int write_init_super_ddf(struct supertype *st)
 
                /* FIXME I need to close the fds! */
                return 0;
-       } else 
+       } else {        
+               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);
+       }
 }
 
 #endif
@@ -2635,7 +2656,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);
@@ -2753,8 +2774,8 @@ static int validate_geometry_ddf_bvd(struct supertype *st,
        if ((S_IFMT & stb.st_mode) != S_IFBLK)
                return 0;
        for (dl = ddf->dlist ; dl ; dl = dl->next) {
-               if (dl->major == major(stb.st_rdev) &&
-                   dl->minor == minor(stb.st_rdev))
+               if (dl->major == (int)major(stb.st_rdev) &&
+                   dl->minor == (int)minor(stb.st_rdev))
                        break;
        }
        if (!dl) {
@@ -2782,7 +2803,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;
@@ -2791,14 +2812,8 @@ 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;
-
-       flags = GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE;
-       if (mdmon_running(devnum))
-               flags |= SKIP_GONE_DEVS;
 
-       sra = sysfs_read(fd, 0, flags);
+       sra = sysfs_read(fd, 0, GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE);
        if (!sra)
                return 1;
        if (sra->array.major_version != -1 ||
@@ -2844,38 +2859,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]) {
-               struct vcl *v;
 
-               for (v = super->conflist; v; v = v->next)
-                       if (v->vcnum == atoi(st->subarray))
-                               super->currentconf = v;
-               if (!super->currentconf)
-                       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
@@ -2891,9 +2903,16 @@ static struct mdinfo *container_content_ddf(struct supertype *st)
 
        for (vc = ddf->conflist ; vc ; vc=vc->next)
        {
-               int i;
-               int j;
+               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;
@@ -2921,7 +2940,7 @@ static struct mdinfo *container_content_ddf(struct supertype *st)
                        this->resync_start = 0;
                } else {
                        this->array.state = 1;
-                       this->resync_start = ~0ULL;
+                       this->resync_start = MaxSector;
                }
                memcpy(this->name, ddf->virt->entries[i].name, 16);
                this->name[16]=0;
@@ -2942,7 +2961,7 @@ static struct mdinfo *container_content_ddf(struct supertype *st)
                        devnum2devname(st->container_dev),
                        this->container_member);
 
-               for (i=0 ; i < ddf->mppe ; i++) {
+               for (i = 0 ; i < ddf->mppe ; i++) {
                        struct mdinfo *dev;
                        struct dl *d;
 
@@ -2968,6 +2987,7 @@ static struct mdinfo *container_content_ddf(struct supertype *st)
                        dev->disk.minor = d->minor;
                        dev->disk.raid_disk = i;
                        dev->disk.state = (1<<MD_DISK_SYNC)|(1<<MD_DISK_ACTIVE);
+                       dev->recovery_start = MaxSector;
 
                        dev->events = __be32_to_cpu(ddf->primary.seq);
                        dev->data_offset = __be64_to_cpu(vc->lba_offset[i]);
@@ -3066,7 +3086,7 @@ static int ddf_set_array_state(struct active_array *a, int consistent)
        if (consistent == 2) {
                /* Should check if a recovery should be started FIXME */
                consistent = 1;
-               if (!is_resync_complete(a))
+               if (!is_resync_complete(&a->info))
                        consistent = 0;
        }
        if (consistent)
@@ -3078,9 +3098,9 @@ static int ddf_set_array_state(struct active_array *a, int consistent)
 
        old = ddf->virt->entries[inst].init_state;
        ddf->virt->entries[inst].init_state &= ~DDF_initstate_mask;
-       if (is_resync_complete(a))
+       if (is_resync_complete(&a->info))
                ddf->virt->entries[inst].init_state |= DDF_init_full;
-       else if (a->resync_start == 0)
+       else if (a->info.resync_start == 0)
                ddf->virt->entries[inst].init_state |= DDF_init_not;
        else
                ddf->virt->entries[inst].init_state |= DDF_init_quick;
@@ -3088,7 +3108,7 @@ static int ddf_set_array_state(struct active_array *a, int consistent)
                ddf->updates_pending = 1;
 
        dprintf("ddf mark %d %s %llu\n", inst, consistent?"clean":"dirty",
-               a->resync_start);
+               a->info.resync_start);
        return consistent;
 }
 
@@ -3109,7 +3129,7 @@ static int ddf_set_array_state(struct active_array *a, int consistent)
 static void ddf_set_disk(struct active_array *a, int n, int state)
 {
        struct ddf_super *ddf = a->container->sb;
-       int inst = a->info.container_member;
+       unsigned int inst = a->info.container_member;
        struct vd_config *vc = find_vdcr(ddf, inst);
        int pd = find_phys(ddf, vc->phys_refnum[n]);
        int i, st, working;
@@ -3250,8 +3270,8 @@ static void ddf_process_update(struct supertype *st,
        struct vd_config *vc;
        struct vcl *vcl;
        struct dl *dl;
-       int mppe;
-       int ent;
+       unsigned int mppe;
+       unsigned int ent;
 
        dprintf("Process update %x\n", *magic);
 
@@ -3310,7 +3330,7 @@ static void ddf_process_update(struct supertype *st,
                dprintf("len %d %d\n", update->len, ddf->conf_rec_len);
 
                mppe = __be16_to_cpu(ddf->anchor.max_primary_element_entries);
-               if (update->len != ddf->conf_rec_len * 512)
+               if ((unsigned)update->len != ddf->conf_rec_len * 512)
                        return;
                vc = (struct vd_config*)update->buf;
                for (vcl = ddf->conflist; vcl ; vcl = vcl->next)
@@ -3337,8 +3357,8 @@ static void ddf_process_update(struct supertype *st,
                }
                /* Now make sure vlist is correct for each dl. */
                for (dl = ddf->dlist; dl; dl = dl->next) {
-                       int dn;
-                       int vn = 0;
+                       unsigned int dn;
+                       unsigned int vn = 0;
                        for (vcl = ddf->conflist; vcl ; vcl = vcl->next)
                                for (dn=0; dn < ddf->mppe ; dn++)
                                        if (vcl->conf.phys_refnum[dn] ==
@@ -3473,7 +3493,7 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a,
                        int is_global = 0;
                        int is_dedicated = 0;
                        struct extent *ex;
-                       int j;
+                       unsigned int j;
                        /* If in this array, skip */
                        for (d2 = a->info.devs ; d2 ; d2 = d2->next)
                                if (d2->disk.major == dl->major &&
@@ -3547,6 +3567,7 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a,
                        di->disk.major = dl->major;
                        di->disk.minor = dl->minor;
                        di->disk.state = 0;
+                       di->recovery_start = 0;
                        di->data_offset = pos;
                        di->component_size = a->info.component_size;
                        di->container_member = dl->pdnum;
@@ -3633,6 +3654,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,