]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super-ddf.c
Allow data-offset to be specified per-device for create
[thirdparty/mdadm.git] / super-ddf.c
index 3fba2ebfdb2910fcf857752aea56ef7d7d7e8d1c..4a6f623709d7316f374a7d3fb65388ccfe839193 100644 (file)
@@ -439,7 +439,6 @@ struct ddf_super {
 #define offsetof(t,f) ((size_t)&(((t*)0)->f))
 #endif
 
-
 static unsigned int calc_crc(void *buf, int len)
 {
        /* crcs are always at the same place as in the ddf_header */
@@ -543,34 +542,32 @@ static int load_ddf_headers(int fd, struct ddf_super *super, char *devname)
 
        if (lseek64(fd, dsize-512, 0) < 0) {
                if (devname)
-                       fprintf(stderr,
-                               Name": Cannot seek to anchor block on %s: %s\n",
-                               devname, strerror(errno));
+                       pr_err("Cannot seek to anchor block on %s: %s\n",
+                              devname, strerror(errno));
                return 1;
        }
        if (read(fd, &super->anchor, 512) != 512) {
                if (devname)
-                       fprintf(stderr,
-                               Name ": Cannot read anchor block on %s: %s\n",
-                               devname, strerror(errno));
+                       pr_err("Cannot read anchor block on %s: %s\n",
+                              devname, strerror(errno));
                return 1;
        }
        if (super->anchor.magic != DDF_HEADER_MAGIC) {
                if (devname)
-                       fprintf(stderr, Name ": no DDF anchor found on %s\n",
+                       pr_err("no DDF anchor found on %s\n",
                                devname);
                return 2;
        }
        if (calc_crc(&super->anchor, 512) != super->anchor.crc) {
                if (devname)
-                       fprintf(stderr, Name ": bad CRC on anchor on %s\n",
+                       pr_err("bad CRC on anchor on %s\n",
                                devname);
                return 2;
        }
        if (memcmp(super->anchor.revision, DDF_REVISION_0, 8) != 0 &&
            memcmp(super->anchor.revision, DDF_REVISION_2, 8) != 0) {
                if (devname)
-                       fprintf(stderr, Name ": can only support super revision"
+                       pr_err("can only support super revision"
                                " %.8s and earlier, not %.8s on %s\n",
                                DDF_REVISION_2, super->anchor.revision,devname);
                return 2;
@@ -579,9 +576,8 @@ static int load_ddf_headers(int fd, struct ddf_super *super, char *devname)
                            dsize >> 9,  1,
                            &super->primary, &super->anchor) == 0) {
                if (devname)
-                       fprintf(stderr,
-                               Name ": Failed to load primary DDF header "
-                               "on %s\n", devname);
+                       pr_err("Failed to load primary DDF header "
+                              "on %s\n", devname);
                return 2;
        }
        super->active = &super->primary;
@@ -652,7 +648,7 @@ static int load_ddf_local(int fd, struct ddf_super *super,
        if (posix_memalign((void**)&dl, 512,
                       sizeof(*dl) +
                       (super->max_part) * sizeof(dl->vlist[0])) != 0) {
-               fprintf(stderr, Name ": %s could not allocate disk info buffer\n",
+               pr_err("%s could not allocate disk info buffer\n",
                        __func__);
                return 1;
        }
@@ -661,7 +657,7 @@ static int load_ddf_local(int fd, struct ddf_super *super,
                     super->active->data_section_offset,
                     super->active->data_section_length,
                     0);
-       dl->devname = devname ? strdup(devname) : NULL;
+       dl->devname = devname ? xstrdup(devname) : NULL;
 
        fstat(fd, &stb);
        dl->major = major(stb.st_rdev);
@@ -706,12 +702,11 @@ static int load_ddf_local(int fd, struct ddf_super *super,
                                continue;
                        if (posix_memalign((void**)&dl->spare, 512,
                                       super->conf_rec_len*512) != 0) {
-                               fprintf(stderr, Name
-                                       ": %s could not allocate spare info buf\n",
-                                       __func__);
+                               pr_err("%s could not allocate spare info buf\n",
+                                      __func__);
                                return 1;
                        }
-                               
+
                        memcpy(dl->spare, vd, super->conf_rec_len*512);
                        continue;
                }
@@ -732,9 +727,8 @@ static int load_ddf_local(int fd, struct ddf_super *super,
                        if (posix_memalign((void**)&vcl, 512,
                                       (super->conf_rec_len*512 +
                                        offsetof(struct vcl, conf))) != 0) {
-                               fprintf(stderr, Name
-                                       ": %s could not allocate vcl buf\n",
-                                       __func__);
+                               pr_err("%s could not allocate vcl buf\n",
+                                      __func__);
                                return 1;
                        }
                        vcl->next = super->conflist;
@@ -782,25 +776,23 @@ static int load_super_ddf(struct supertype *st, int fd,
        /* 32M is a lower bound */
        if (dsize <= 32*1024*1024) {
                if (devname)
-                       fprintf(stderr,
-                               Name ": %s is too small for ddf: "
-                               "size is %llu sectors.\n",
-                               devname, dsize>>9);
+                       pr_err("%s is too small for ddf: "
+                              "size is %llu sectors.\n",
+                              devname, dsize>>9);
                return 1;
        }
        if (dsize & 511) {
                if (devname)
-                       fprintf(stderr,
-                               Name ": %s is an odd size for ddf: "
-                               "size is %llu bytes.\n",
-                               devname, dsize);
+                       pr_err("%s is an odd size for ddf: "
+                              "size is %llu bytes.\n",
+                              devname, dsize);
                return 1;
        }
 
        free_super_ddf(st);
 
        if (posix_memalign((void**)&super, 512, sizeof(*super))!= 0) {
-               fprintf(stderr, Name ": malloc of %zu failed.\n",
+               pr_err("malloc of %zu failed.\n",
                        sizeof(*super));
                return 1;
        }
@@ -818,9 +810,8 @@ static int load_super_ddf(struct supertype *st, int fd,
 
        if (rv) {
                if (devname)
-                       fprintf(stderr,
-                               Name ": Failed to load all information "
-                               "sections on %s\n", devname);
+                       pr_err("Failed to load all information "
+                              "sections on %s\n", devname);
                free(super);
                return rv;
        }
@@ -829,9 +820,8 @@ static int load_super_ddf(struct supertype *st, int fd,
 
        if (rv) {
                if (devname)
-                       fprintf(stderr,
-                               Name ": Failed to load all information "
-                               "sections on %s\n", devname);
+                       pr_err("Failed to load all information "
+                              "sections on %s\n", devname);
                free(super);
                return rv;
        }
@@ -893,8 +883,7 @@ static struct supertype *match_metadata_desc_ddf(char *arg)
                )
                return NULL;
 
-       st = malloc(sizeof(*st));
-       memset(st, 0, sizeof(*st));
+       st = xcalloc(1, sizeof(*st));
        st->container_dev = NoMdDev;
        st->ss = &super_ddf;
        st->max_devs = 512;
@@ -903,7 +892,6 @@ static struct supertype *match_metadata_desc_ddf(char *arg)
        return st;
 }
 
-
 #ifndef MDASSEMBLE
 
 static mapping_t ddf_state[] = {
@@ -1060,8 +1048,8 @@ static void examine_vd(int n, struct ddf_super *sb, char *guid)
                }
                printf(")\n");
                if (vc->chunk_shift != 255)
-               printf("   Chunk Size[%d] : %d sectors\n", n,
-                      1 << vc->chunk_shift);
+                       printf("   Chunk Size[%d] : %d sectors\n", n,
+                              1 << vc->chunk_shift);
                printf("   Raid Level[%d] : %s\n", n,
                       map_num(ddf_level, vc->prl)?:"-unknown-");
                if (vc->sec_elmnt_count != 1) {
@@ -1120,7 +1108,7 @@ static void examine_pds(struct ddf_super *sb)
                //printf("\n");
                printf("       %3d    %08x  ", i,
                       __be32_to_cpu(pd->refnum));
-               printf("%8lluK ", 
+               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) {
@@ -1223,7 +1211,6 @@ static void export_examine_super_ddf(struct supertype *st)
        printf("MD_LEVEL=container\n");
        printf("MD_UUID=%s\n", nbuf+5);
 }
-       
 
 static void detail_super_ddf(struct supertype *st, char *homehost)
 {
@@ -1302,7 +1289,7 @@ static void uuid_from_super_ddf(struct supertype *st, int uuid[4])
         *    not the device-set.
         *  uuid to recognise same set when adding a missing device back
         *    to an array.   This is a uuid for the device-set.
-        *  
+        *
         * For each of these we can make do with a truncated
         * or hashed uuid rather than the original, as long as
         * everyone agrees.
@@ -1336,6 +1323,7 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info, char *m
 {
        struct ddf_super *ddf = st->sb;
        int map_disks = info->array.raid_disks;
+       __u32 *cptr;
 
        if (ddf->currentconf) {
                getinfo_super_ddf_bvd(st, info, map);
@@ -1347,13 +1335,13 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info, char *m
        info->array.level         = LEVEL_CONTAINER;
        info->array.layout        = 0;
        info->array.md_minor      = -1;
-       info->array.ctime         = DECADE + __be32_to_cpu(*(__u32*)
-                                                        (ddf->anchor.guid+16));
+       cptr = (__u32 *)(ddf->anchor.guid + 16);
+       info->array.ctime         = DECADE + __be32_to_cpu(*cptr);
+
        info->array.utime         = 0;
        info->array.chunk_size    = 0;
        info->container_enough    = 1;
 
-
        info->disk.major = 0;
        info->disk.minor = 0;
        if (ddf->dlist) {
@@ -1361,8 +1349,8 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info, char *m
                info->disk.raid_disk = find_phys(ddf, ddf->dlist->disk.refnum);
 
                info->data_offset = __be64_to_cpu(ddf->phys->
-                                         entries[info->disk.raid_disk].
-                                         config_size);
+                                                 entries[info->disk.raid_disk].
+                                                 config_size);
                info->component_size = ddf->dlist->size - info->data_offset;
        } else {
                info->disk.number = -1;
@@ -1371,9 +1359,9 @@ static void getinfo_super_ddf(struct supertype *st, struct mdinfo *info, char *m
        }
        info->disk.state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE);
 
-
        info->recovery_start = MaxSector;
        info->reshape_active = 0;
+       info->recovery_blocked = 0;
        info->name[0] = 0;
 
        info->array.major_version = -1;
@@ -1406,6 +1394,7 @@ static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info, cha
        int j;
        struct dl *dl;
        int map_disks = info->array.raid_disks;
+       __u32 *cptr;
 
        memset(info, 0, sizeof(*info));
        /* FIXME this returns BVD info - what if we want SVD ?? */
@@ -1415,8 +1404,8 @@ static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info, cha
        info->array.layout        = rlq_to_layout(vc->conf.rlq, vc->conf.prl,
                                                  info->array.raid_disks);
        info->array.md_minor      = -1;
-       info->array.ctime         = DECADE +
-               __be32_to_cpu(*(__u32*)(vc->conf.guid+16));
+       cptr = (__u32 *)(vc->conf.guid + 16);
+       info->array.ctime         = DECADE + __be32_to_cpu(*cptr);
        info->array.utime         = DECADE + __be32_to_cpu(vc->conf.timestamp);
        info->array.chunk_size    = 512 << vc->conf.chunk_shift;
        info->custom_array_size   = 0;
@@ -1429,22 +1418,27 @@ static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info, cha
                        info->component_size = __be64_to_cpu(vc->conf.blocks);
        }
 
-       dl = ddf->dlist;
+       for (dl = ddf->dlist; dl ; dl = dl->next)
+               if (dl->raiddisk == ddf->currentdev)
+                       break;
+
        info->disk.major = 0;
        info->disk.minor = 0;
+       info->disk.state = 0;
        if (dl) {
                info->disk.major = dl->major;
                info->disk.minor = dl->minor;
+               info->disk.raid_disk = dl->raiddisk;
+               info->disk.number = dl->pdnum;
+               info->disk.state = (1<<MD_DISK_SYNC)|(1<<MD_DISK_ACTIVE);
        }
-//     info->disk.number = __be32_to_cpu(ddf->disk.refnum);
-//     info->disk.raid_disk = find refnum in the table and use index;
-//     info->disk.state = ???;
 
        info->container_member = ddf->currentconf->vcnum;
 
        info->recovery_start = MaxSector;
        info->resync_start = 0;
        info->reshape_active = 0;
+       info->recovery_blocked = 0;
        if (!(ddf->virt->entries[info->container_member].state
              & DDF_state_inconsistent)  &&
            (ddf->virt->entries[info->container_member].init_state
@@ -1472,7 +1466,7 @@ static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info, cha
                        map[j] = 0;
                        if (j <  info->array.raid_disks) {
                                int i = find_phys(ddf, vc->conf.phys_refnum[j]);
-                               if (i >= 0 && 
+                               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;
@@ -1480,7 +1474,6 @@ static void getinfo_super_ddf_bvd(struct supertype *st, struct mdinfo *info, cha
                }
 }
 
-
 static int update_super_ddf(struct supertype *st, struct mdinfo *info,
                            char *update,
                            char *devname, int verbose,
@@ -1575,12 +1568,12 @@ static int init_super_ddf_bvd(struct supertype *st,
                              mdu_array_info_t *info,
                              unsigned long long size,
                              char *name, char *homehost,
-                             int *uuid);
+                             int *uuid, unsigned long long data_offset);
 
 static int init_super_ddf(struct supertype *st,
                          mdu_array_info_t *info,
                          unsigned long long size, char *name, char *homehost,
-                         int *uuid)
+                         int *uuid, unsigned long long data_offset)
 {
        /* This is primarily called by Create when creating a new array.
         * We will then get add_to_super called for each component, and then
@@ -1616,11 +1609,17 @@ static int init_super_ddf(struct supertype *st,
        struct phys_disk *pd;
        struct virtual_disk *vd;
 
+       if (data_offset != INVALID_SECTORS) {
+               fprintf(stderr, Name ": data-offset not supported by DDF\n");
+               return 0;
+       }
+
        if (st->sb)
-               return init_super_ddf_bvd(st, info, size, name, homehost, uuid);
+               return init_super_ddf_bvd(st, info, size, name, homehost, uuid,
+                                         data_offset);
 
        if (posix_memalign((void**)&ddf, 512, sizeof(*ddf)) != 0) {
-               fprintf(stderr, Name ": %s could not allocate superblock\n", __func__);
+               pr_err("%s could not allocate superblock\n", __func__);
                return 0;
        }
        memset(ddf, 0, sizeof(*ddf));
@@ -1758,7 +1757,7 @@ static int init_super_ddf(struct supertype *st,
                strcpy((char*)ddf->controller.vendor_data, homehost);
 
        if (posix_memalign((void**)&pd, 512, pdsize) != 0) {
-               fprintf(stderr, Name ": %s could not allocate pd\n", __func__);
+               pr_err("%s could not allocate pd\n", __func__);
                return 0;
        }
        ddf->phys = pd;
@@ -1772,7 +1771,7 @@ static int init_super_ddf(struct supertype *st,
        memset(pd->pad, 0xff, 52);
 
        if (posix_memalign((void**)&vd, 512, vdsize) != 0) {
-               fprintf(stderr, Name ": %s could not allocate vd\n", __func__);
+               pr_err("%s could not allocate vd\n", __func__);
                return 0;
        }
        ddf->virt = vd;
@@ -1808,6 +1807,7 @@ static int level_to_prl(int level)
        default: return -1;
        }
 }
+
 static int layout_to_rlq(int level, int layout, int raiddisks)
 {
        switch(level) {
@@ -1911,16 +1911,14 @@ static struct extent *get_extents(struct ddf_super *ddf, struct dl *dl)
         * (dnum) of the given ddf.
         * Return a malloced array of 'struct extent'
 
-FIXME ignore DDF_Legacy devices?
+        * FIXME ignore DDF_Legacy devices?
 
         */
        struct extent *rv;
        int n = 0;
        unsigned int i, j;
 
-       rv = malloc(sizeof(struct extent) * (ddf->max_part + 2));
-       if (!rv)
-               return NULL;
+       rv = xmalloc(sizeof(struct extent) * (ddf->max_part + 2));
 
        for (i = 0; i < ddf->max_part; i++) {
                struct vcl *v = dl->vlist[i];
@@ -1947,7 +1945,7 @@ static int init_super_ddf_bvd(struct supertype *st,
                              mdu_array_info_t *info,
                              unsigned long long size,
                              char *name, char *homehost,
-                             int *uuid)
+                             int *uuid, unsigned long long data_offset)
 {
        /* We are creating a BVD inside a pre-existing container.
         * so st->sb is already set.
@@ -1961,9 +1959,9 @@ static int init_super_ddf_bvd(struct supertype *st,
 
        if (__be16_to_cpu(ddf->virt->populated_vdes)
            >= __be16_to_cpu(ddf->virt->max_vdes)) {
-               fprintf(stderr, Name": This ddf already has the "
-                       "maximum of %d virtual devices\n",
-                       __be16_to_cpu(ddf->virt->max_vdes));
+               pr_err("This ddf already has the "
+                      "maximum of %d virtual devices\n",
+                      __be16_to_cpu(ddf->virt->max_vdes));
                return 0;
        }
 
@@ -1973,9 +1971,9 @@ static int init_super_ddf_bvd(struct supertype *st,
                                char *n = ddf->virt->entries[venum].name;
 
                                if (strncmp(name, n, 16) == 0) {
-                                       fprintf(stderr, Name ": This ddf already"
-                                               " has an array called %s\n",
-                                               name);
+                                       pr_err("This ddf already"
+                                              " has an array called %s\n",
+                                              name);
                                        return 0;
                                }
                        }
@@ -1984,8 +1982,8 @@ static int init_super_ddf_bvd(struct supertype *st,
                if (all_ff(ddf->virt->entries[venum].guid))
                        break;
        if (venum == __be16_to_cpu(ddf->virt->max_vdes)) {
-               fprintf(stderr, Name ": Cannot find spare slot for "
-                       "virtual disk - DDF is corrupt\n");
+               pr_err("Cannot find spare slot for "
+                      "virtual disk - DDF is corrupt\n");
                return 0;
        }
        ve = &ddf->virt->entries[venum];
@@ -2014,7 +2012,7 @@ static int init_super_ddf_bvd(struct supertype *st,
        /* Now create a new vd_config */
        if (posix_memalign((void**)&vcl, 512,
                           (offsetof(struct vcl, conf) + ddf->conf_rec_len * 512)) != 0) {
-               fprintf(stderr, Name ": %s could not allocate vd_config\n", __func__);
+               pr_err("%s could not allocate vd_config\n", __func__);
                return 0;
        }
        vcl->lba_offset = (__u64*) &vcl->conf.phys_refnum[ddf->mppe];
@@ -2176,7 +2174,8 @@ static void add_to_super_ddf_bvd(struct supertype *st,
  * expanding a pre-existing container
  */
 static int add_to_super_ddf(struct supertype *st,
-                            mdu_disk_info_t *dk, int fd, char *devname)
+                           mdu_disk_info_t *dk, int fd, char *devname,
+                           unsigned long long data_offset)
 {
        struct ddf_super *ddf = st->sb;
        struct dl *dd;
@@ -2186,6 +2185,7 @@ static int add_to_super_ddf(struct supertype *st,
        struct phys_disk_entry *pde;
        unsigned int n, i;
        struct stat stb;
+       __u32 *tptr;
 
        if (ddf->currentconf) {
                add_to_super_ddf_bvd(st, dk, fd, devname);
@@ -2198,9 +2198,8 @@ static int add_to_super_ddf(struct supertype *st,
        fstat(fd, &stb);
        if (posix_memalign((void**)&dd, 512,
                           sizeof(*dd) + sizeof(dd->vlist[0]) * ddf->max_part) != 0) {
-               fprintf(stderr, Name
-                       ": %s could allocate buffer for new disk, aborting\n",
-                       __func__);
+               pr_err("%s could allocate buffer for new disk, aborting\n",
+                      __func__);
                return 1;
        }
        dd->major = major(stb.st_rdev);
@@ -2214,8 +2213,9 @@ 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) = random32();
-       *(__u32*)(dd->disk.guid + 20) = random32();
+       tptr = (__u32 *)(dd->disk.guid + 16);
+       *tptr++ = random32();
+       *tptr = random32();
 
        do {
                /* Cannot be bothered finding a CRC of some irrelevant details*/
@@ -2243,7 +2243,7 @@ static int add_to_super_ddf(struct supertype *st,
                           sizeof(struct phys_disk_entry));
                struct phys_disk *pd;
 
-               pd = malloc(len);
+               pd = xmalloc(len);
                pd->magic = DDF_PHYS_RECORDS_MAGIC;
                pd->used_pdes = __cpu_to_be16(n);
                pde = &pd->entries[0];
@@ -2301,7 +2301,7 @@ static int remove_from_super_ddf(struct supertype *st, mdu_disk_info_t *dk)
                           sizeof(struct phys_disk_entry));
                struct phys_disk *pd;
 
-               pd = malloc(len);
+               pd = xmalloc(len);
                pd->magic = DDF_PHYS_RECORDS_MAGIC;
                pd->used_pdes = __cpu_to_be16(dl->pdnum);
                pd->entries[0].state = __cpu_to_be16(DDF_Missing);
@@ -2315,8 +2315,7 @@ static int remove_from_super_ddf(struct supertype *st, mdu_disk_info_t *dk)
  * called when creating a container or adding another device to a
  * container.
  */
-
-static unsigned char null_conf[4096+512];
+#define NULL_CONF_SZ   4096
 
 static int __write_init_super_ddf(struct supertype *st)
 {
@@ -2329,6 +2328,12 @@ static int __write_init_super_ddf(struct supertype *st)
        int attempts = 0;
        int successes = 0;
        unsigned long long size, sector;
+       char *null_aligned;
+
+       if (posix_memalign((void**)&null_aligned, 4096, NULL_CONF_SZ) != 0) {
+               return -ENOMEM;
+       }
+       memset(null_aligned, 0xff, NULL_CONF_SZ);
 
        /* try to write updated metadata,
         * if we catch a failure move on to the next disk
@@ -2398,14 +2403,11 @@ static int __write_init_super_ddf(struct supertype *st)
                                if (write(fd, &c->conf, conf_size) < 0)
                                        break;
                        } else {
-                               char *null_aligned = (char*)((((unsigned long)null_conf)+511)&~511UL);
-                               if (null_conf[0] != 0xff)
-                                       memset(null_conf, 0xff, sizeof(null_conf));
                                unsigned int togo = conf_size;
-                               while (togo > sizeof(null_conf)-512) {
-                                       if (write(fd, null_aligned, sizeof(null_conf)-512) < 0)
+                               while (togo > NULL_CONF_SZ) {
+                                       if (write(fd, null_aligned, NULL_CONF_SZ) < 0)
                                                break;
-                                       togo -= sizeof(null_conf)-512;
+                                       togo -= NULL_CONF_SZ;
                                }
                                if (write(fd, null_aligned, togo) < 0)
                                        break;
@@ -2424,6 +2426,7 @@ static int __write_init_super_ddf(struct supertype *st)
                        continue;
                successes++;
        }
+       free(null_aligned);
 
        return attempts != successes;
 }
@@ -2459,7 +2462,7 @@ static int write_init_super_ddf(struct supertype *st)
 
                /* First the virtual disk.  We have a slightly fake header */
                len = sizeof(struct virtual_disk) + sizeof(struct virtual_entry);
-               vd = malloc(len);
+               vd = xmalloc(len);
                *vd = *ddf->virt;
                vd->entries[0] = ddf->virt->entries[currentconf->vcnum];
                vd->populated_vdes = __cpu_to_be16(currentconf->vcnum);
@@ -2467,23 +2470,24 @@ static int write_init_super_ddf(struct supertype *st)
 
                /* Then the vd_config */
                len = ddf->conf_rec_len * 512;
-               vc = malloc(len);
+               vc = xmalloc(len);
                memcpy(vc, &currentconf->conf, len);
                append_metadata_update(st, vc, len);
 
                /* 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);
+                       while (Kill(d->devname, NULL, 0, -1, 1) == 0);
                return __write_init_super_ddf(st);
        }
 }
 
 #endif
 
-static __u64 avail_size_ddf(struct supertype *st, __u64 devsize)
+static __u64 avail_size_ddf(struct supertype *st, __u64 devsize,
+                           unsigned long long data_offset)
 {
        /* We must reserve the last 32Meg */
        if (devsize <= 32*1024*2)
@@ -2507,7 +2511,7 @@ static int reserve_space(struct supertype *st, int raiddisks,
        int cnt = 0;
 
        for (dl = ddf->dlist; dl ; dl=dl->next) {
-               dl->raiddisk = -1;      
+               dl->raiddisk = -1;
                dl->esize = 0;
        }
        /* Now find largest extent on each device */
@@ -2540,7 +2544,7 @@ static int reserve_space(struct supertype *st, int raiddisks,
                free(e);
        }
        if (cnt < raiddisks) {
-               fprintf(stderr, Name ": not enough devices with space to create array.\n");
+               pr_err("not enough devices with space to create array.\n");
                return 0; /* No enough free spaces large enough */
        }
        if (size == 0) {
@@ -2551,7 +2555,7 @@ static int reserve_space(struct supertype *st, int raiddisks,
                                continue;
                        /* This is bigger than 'size', see if there are enough */
                        cnt = 0;
-                       for (dl2 = dl; dl2 ; dl2=dl2->next)
+                       for (dl2 = ddf->dlist; dl2 ; dl2=dl2->next)
                                if (dl2->esize >= dl->esize)
                                        cnt++;
                        if (cnt >= raiddisks)
@@ -2563,7 +2567,7 @@ static int reserve_space(struct supertype *st, int raiddisks,
                }
                *freesize = size;
                if (size < 32) {
-                       fprintf(stderr, Name ": not enough spare devices to create array.\n");
+                       pr_err("not enough spare devices to create array.\n");
                        return 0;
                }
        }
@@ -2573,31 +2577,32 @@ static int reserve_space(struct supertype *st, int raiddisks,
        for (dl = ddf->dlist ; dl && cnt < raiddisks ; dl=dl->next) {
                if (dl->esize < size)
                        continue;
-               
+
                dl->raiddisk = cnt;
                cnt++;
        }
        return 1;
 }
 
-
-
 static int
 validate_geometry_ddf_container(struct supertype *st,
                                int level, int layout, int raiddisks,
                                int chunk, unsigned long long size,
+                               unsigned long long data_offset,
                                char *dev, unsigned long long *freesize,
                                int verbose);
 
 static int validate_geometry_ddf_bvd(struct supertype *st,
                                     int level, int layout, int raiddisks,
                                     int *chunk, unsigned long long size,
+                                    unsigned long long data_offset,
                                     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,
+                                unsigned long long data_offset,
                                 char *dev, unsigned long long *freesize,
                                 int verbose)
 {
@@ -2615,12 +2620,13 @@ static int validate_geometry_ddf(struct supertype *st,
        if (chunk && *chunk == UnSet)
                *chunk = DEFAULT_CHUNK;
 
-
+       if (level == -1000000) level = LEVEL_CONTAINER;
        if (level == LEVEL_CONTAINER) {
                /* Must be a fresh device to add to a container */
                return validate_geometry_ddf_container(st, level, layout,
                                                       raiddisks, chunk?*chunk:0,
-                                                      size, dev, freesize,
+                                                      size, data_offset, dev,
+                                                      freesize,
                                                       verbose);
        }
 
@@ -2632,8 +2638,8 @@ static int validate_geometry_ddf(struct supertype *st,
                                break;
                if (ddf_level_num[i].num1 == MAXINT) {
                        if (verbose)
-                               fprintf(stderr, Name ": DDF does not support level %d arrays\n",
-                                       level);
+                               pr_err("DDF does not support level %d arrays\n",
+                                      level);
                        return 0;
                }
                /* Should check layout? etc */
@@ -2657,7 +2663,8 @@ static int validate_geometry_ddf(struct supertype *st,
                 * Should make a distinction one day.
                 */
                return validate_geometry_ddf_bvd(st, level, layout, raiddisks,
-                                                chunk, size, dev, freesize,
+                                                chunk, size, data_offset, dev,
+                                                freesize,
                                                 verbose);
        }
        /* This is the first device for the array.
@@ -2681,16 +2688,15 @@ static int validate_geometry_ddf(struct supertype *st,
                }
 
                if (verbose)
-                       fprintf(stderr,
-                               Name ": ddf: Cannot create this array "
-                               "on device %s - a container is required.\n",
-                               dev);
+                       pr_err("ddf: Cannot create this array "
+                              "on device %s - a container is required.\n",
+                              dev);
                return 0;
        }
        if (errno != EBUSY || (fd = open(dev, O_RDONLY, 0)) < 0) {
                if (verbose)
-                       fprintf(stderr, Name ": ddf: Cannot open %s: %s\n",
-                               dev, strerror(errno));
+                       pr_err("ddf: Cannot open %s: %s\n",
+                              dev, strerror(errno));
                return 0;
        }
        /* Well, it is in use by someone, maybe a 'ddf' container. */
@@ -2698,8 +2704,8 @@ static int validate_geometry_ddf(struct supertype *st,
        if (cfd < 0) {
                close(fd);
                if (verbose)
-                       fprintf(stderr, Name ": ddf: Cannot use %s: %s\n",
-                               dev, strerror(EBUSY));
+                       pr_err("ddf: Cannot use %s: %s\n",
+                              dev, strerror(EBUSY));
                return 0;
        }
        sra = sysfs_read(cfd, 0, GET_VERSION);
@@ -2716,6 +2722,7 @@ static int validate_geometry_ddf(struct supertype *st,
                        close(cfd);
                        return validate_geometry_ddf_bvd(st, level, layout,
                                                         raiddisks, chunk, size,
+                                                        data_offset,
                                                         dev, freesize,
                                                         verbose);
                }
@@ -2730,6 +2737,7 @@ static int
 validate_geometry_ddf_container(struct supertype *st,
                                int level, int layout, int raiddisks,
                                int chunk, unsigned long long size,
+                               unsigned long long data_offset,
                                char *dev, unsigned long long *freesize,
                                int verbose)
 {
@@ -2744,8 +2752,8 @@ validate_geometry_ddf_container(struct supertype *st,
        fd = open(dev, O_RDONLY|O_EXCL, 0);
        if (fd < 0) {
                if (verbose)
-                       fprintf(stderr, Name ": ddf: Cannot open %s: %s\n",
-                               dev, strerror(errno));
+                       pr_err("ddf: Cannot open %s: %s\n",
+                              dev, strerror(errno));
                return 0;
        }
        if (!get_dev_size(fd, dev, &ldsize)) {
@@ -2754,7 +2762,7 @@ validate_geometry_ddf_container(struct supertype *st,
        }
        close(fd);
 
-       *freesize = avail_size_ddf(st, ldsize >> 9);
+       *freesize = avail_size_ddf(st, ldsize >> 9, INVALID_SECTORS);
        if (*freesize == 0)
                return 0;
 
@@ -2764,6 +2772,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,
+                                    unsigned long long data_offset,
                                     char *dev, unsigned long long *freesize,
                                     int verbose)
 {
@@ -2777,7 +2786,7 @@ static int validate_geometry_ddf_bvd(struct supertype *st,
        /* ddf/bvd supports lots of things, but not containers */
        if (level == LEVEL_CONTAINER) {
                if (verbose)
-                       fprintf(stderr, Name ": DDF cannot create a container within an container\n");
+                       pr_err("DDF cannot create a container within an container\n");
                return 0;
        }
        /* We must have the container info already read in. */
@@ -2814,10 +2823,9 @@ static int validate_geometry_ddf_bvd(struct supertype *st,
                }
                if (dcnt < raiddisks) {
                        if (verbose)
-                               fprintf(stderr,
-                                       Name ": ddf: Not enough devices with "
-                                       "space for this array (%d < %d)\n",
-                                       dcnt, raiddisks);
+                               pr_err("ddf: Not enough devices with "
+                                      "space for this array (%d < %d)\n",
+                                      dcnt, raiddisks);
                        return 0;
                }
                return 1;
@@ -2834,22 +2842,22 @@ static int validate_geometry_ddf_bvd(struct supertype *st,
        }
        if (!dl) {
                if (verbose)
-                       fprintf(stderr, Name ": ddf: %s is not in the "
-                               "same DDF set\n",
-                               dev);
+                       pr_err("ddf: %s is not in the "
+                              "same DDF set\n",
+                              dev);
                return 0;
        }
        e = get_extents(ddf, dl);
        maxsize = 0;
        i = 0;
        if (e) do {
-               unsigned long long esize;
-               esize = e[i].start - pos;
-               if (esize >= maxsize)
-                       maxsize = esize;
-               pos = e[i].start + e[i].size;
-               i++;
-       } while (e[i-1].size);
+                       unsigned long long esize;
+                       esize = e[i].start - pos;
+                       if (esize >= maxsize)
+                               maxsize = esize;
+                       pos = e[i].start + e[i].size;
+                       i++;
+               } while (e[i-1].size);
        *freesize = maxsize;
        // FIXME here I am
 
@@ -2961,14 +2969,14 @@ static struct mdinfo *container_content_ddf(struct supertype *st, char *subarray
                unsigned int j;
                struct mdinfo *this;
                char *ep;
+               __u32 *cptr;
 
                if (subarray &&
                    (strtoul(subarray, &ep, 10) != vc->vcnum ||
                     *ep != '\0'))
                        continue;
 
-               this = malloc(sizeof(*this));
-               memset(this, 0, sizeof(*this));
+               this = xcalloc(1, sizeof(*this));
                this->next = rest;
                rest = this;
 
@@ -2980,8 +2988,8 @@ static struct mdinfo *container_content_ddf(struct supertype *st, char *subarray
                this->array.md_minor      = -1;
                this->array.major_version = -1;
                this->array.minor_version = -2;
-               this->array.ctime         = DECADE +
-                       __be32_to_cpu(*(__u32*)(vc->conf.guid+16));
+               cptr = (__u32 *)(vc->conf.guid + 16);
+               this->array.ctime         = DECADE + __be32_to_cpu(*cptr);
                this->array.utime         = DECADE +
                        __be32_to_cpu(vc->conf.timestamp);
                this->array.chunk_size    = 512 << vc->conf.chunk_shift;
@@ -3046,8 +3054,7 @@ static struct mdinfo *container_content_ddf(struct supertype *st, char *subarray
                                /* Haven't found that one yet, maybe there are others */
                                continue;
 
-                       dev = malloc(sizeof(*dev));
-                       memset(dev, 0, sizeof(*dev));
+                       dev = xcalloc(1, sizeof(*dev));
                        dev->next = this->devs;
                        this->devs = dev;
 
@@ -3276,29 +3283,29 @@ static void ddf_set_disk(struct active_array *a, int n, int state)
        if (working == a->info.array.raid_disks)
                state = DDF_state_optimal;
        else switch(vc->prl) {
-       case DDF_RAID0:
-       case DDF_CONCAT:
-       case DDF_JBOD:
-               state = DDF_state_failed;
-               break;
-       case DDF_RAID1:
-               if (working == 0)
-                       state = DDF_state_failed;
-               else if (working == 2 && state == DDF_state_degraded)
-                       state = DDF_state_part_optimal;
-               break;
-       case DDF_RAID4:
-       case DDF_RAID5:
-               if (working < a->info.array.raid_disks-1)
-                       state = DDF_state_failed;
-               break;
-       case DDF_RAID6:
-               if (working < a->info.array.raid_disks-2)
+               case DDF_RAID0:
+               case DDF_CONCAT:
+               case DDF_JBOD:
                        state = DDF_state_failed;
-               else if (working == a->info.array.raid_disks-1)
-                       state = DDF_state_part_optimal;
-               break;
-       }
+                       break;
+               case DDF_RAID1:
+                       if (working == 0)
+                               state = DDF_state_failed;
+                       else if (working == 2 && state == DDF_state_degraded)
+                               state = DDF_state_part_optimal;
+                       break;
+               case DDF_RAID4:
+               case DDF_RAID5:
+                       if (working < a->info.array.raid_disks-1)
+                               state = DDF_state_failed;
+                       break;
+               case DDF_RAID6:
+                       if (working < a->info.array.raid_disks-2)
+                               state = DDF_state_failed;
+                       else if (working == a->info.array.raid_disks-1)
+                               state = DDF_state_part_optimal;
+                       break;
+               }
 
        if (ddf->virt->entries[inst].state !=
            ((ddf->virt->entries[inst].state & ~DDF_state_mask)
@@ -3407,7 +3414,7 @@ static void ddf_process_update(struct supertype *st,
                        return;
                ddf->phys->entries[ent] = pd->entries[0];
                ddf->phys->used_pdes = __cpu_to_be16(1 +
-                                          __be16_to_cpu(ddf->phys->used_pdes));
+                                                    __be16_to_cpu(ddf->phys->used_pdes));
                ddf->updates_pending = 1;
                if (ddf->add_list) {
                        struct active_array *a;
@@ -3439,7 +3446,7 @@ static void ddf_process_update(struct supertype *st,
                        return;
                ddf->virt->entries[ent] = vd->entries[0];
                ddf->virt->populated_vdes = __cpu_to_be16(1 +
-                             __be16_to_cpu(ddf->virt->populated_vdes));
+                                                         __be16_to_cpu(ddf->virt->populated_vdes));
                ddf->updates_pending = 1;
                break;
 
@@ -3521,12 +3528,12 @@ static void ddf_process_update(struct supertype *st,
                                        ~__cpu_to_be16(DDF_Global_Spare);
                                if (!(ddf->phys->entries[dl->pdnum].type &
                                      __cpu_to_be16(DDF_Active_in_VD))) {
-                                           ddf->phys->entries[dl->pdnum].type |=
-                                                   __cpu_to_be16(DDF_Active_in_VD);
-                                           if (in_degraded)
-                                                   ddf->phys->entries[dl->pdnum].state |=
-                                                           __cpu_to_be16(DDF_Rebuilding);
-                                   }
+                                       ddf->phys->entries[dl->pdnum].type |=
+                                               __cpu_to_be16(DDF_Active_in_VD);
+                                       if (in_degraded)
+                                               ddf->phys->entries[dl->pdnum].state |=
+                                                       __cpu_to_be16(DDF_Rebuilding);
+                               }
                        }
                        if (dl->spare) {
                                ddf->phys->entries[dl->pdnum].type &=
@@ -3587,8 +3594,8 @@ static void ddf_prepare_update(struct supertype *st,
        __u32 *magic = (__u32*)update->buf;
        if (*magic == DDF_VD_CONF_MAGIC)
                if (posix_memalign(&update->space, 512,
-                              offsetof(struct vcl, conf)
-                              + ddf->conf_rec_len * 512) != 0)
+                                  offsetof(struct vcl, conf)
+                                  + ddf->conf_rec_len * 512) != 0)
                        update->space = NULL;
 }
 
@@ -3624,7 +3631,7 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a,
 
        for (d = a->info.devs ; d ; d = d->next) {
                if ((d->curr_state & DS_FAULTY) &&
-                       d->state_fd >= 0)
+                   d->state_fd >= 0)
                        /* wait for Removal to happen */
                        return NULL;
                if (d->state_fd >= 0)
@@ -3703,11 +3710,15 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a,
                        } else if (ddf->phys->entries[dl->pdnum].type &
                                   __cpu_to_be16(DDF_Global_Spare)) {
                                is_global = 1;
+                       } else if (!(ddf->phys->entries[dl->pdnum].state &
+                                    __cpu_to_be16(DDF_Failed))) {
+                               /* we can possibly use some of this */
+                               is_global = 1;
                        }
                        if ( ! (is_dedicated ||
                                (is_global && global_ok))) {
                                dprintf("%x:%x not suitable: %d %d\n", dl->major, dl->minor,
-                                      is_dedicated, is_global);
+                                       is_dedicated, is_global);
                                continue;
                        }
 
@@ -3739,10 +3750,7 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a,
                        }
 
                        /* Cool, we have a device with some space at pos */
-                       di = malloc(sizeof(*di));
-                       if (!di)
-                               continue;
-                       memset(di, 0, sizeof(*di));
+                       di = xcalloc(1, sizeof(*di));
                        di->disk.number = i;
                        di->disk.raid_disk = i;
                        di->disk.major = dl->major;
@@ -3774,22 +3782,12 @@ static struct mdinfo *ddf_activate_spare(struct active_array *a,
         * Create a metadata_update record to update the
         * phys_refnum and lba_offset values
         */
-       mu = malloc(sizeof(*mu));
-       if (mu && posix_memalign(&mu->space, 512, sizeof(struct vcl)) != 0) {
+       mu = xmalloc(sizeof(*mu));
+       if (posix_memalign(&mu->space, 512, sizeof(struct vcl)) != 0) {
                free(mu);
                mu = NULL;
        }
-       if (!mu) {
-               while (rv) {
-                       struct mdinfo *n = rv->next;
-
-                       free(rv);
-                       rv = n;
-               }
-               return NULL;
-       }
-               
-       mu->buf = malloc(ddf->conf_rec_len * 512);
+       mu->buf = xmalloc(ddf->conf_rec_len * 512);
        mu->len = ddf->conf_rec_len * 512;
        mu->space = NULL;
        mu->space_list = NULL;