]> git.ipfire.org Git - thirdparty/mdadm.git/blobdiff - super1.c
(no commit message)
[thirdparty/mdadm.git] / super1.c
index 4cfd786009a6c9a8b24c944d0fea9f44f04b3321..f3be7cef40e697f14f7dca222f961cdd9573cdd9 100644 (file)
--- a/super1.c
+++ b/super1.c
@@ -1,7 +1,7 @@
 /*
  * mdadm - manage Linux "md" devices aka RAID arrays.
  *
- * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
+ * Copyright (C) 2001-2009 Neil Brown <neilb@suse.de>
  *
  *
  *    This program is free software; you can redistribute it and/or modify
  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  *    Author: Neil Brown
- *    Email: <neilb@cse.unsw.edu.au>
- *    Paper: Neil Brown
- *           School of Computer Science and Engineering
- *           The University of New South Wales
- *           Sydney, 2052
- *           Australia
+ *    Email: <neilb@suse.de>
  */
 
 #include "mdadm.h"
@@ -81,8 +76,8 @@ struct mdp_superblock_1 {
        __u64   utime;          /* 40 bits second, 24 btes microseconds */
        __u64   events;         /* incremented when superblock updated */
        __u64   resync_offset;  /* data before this offset (from data_offset) known to be in sync */
-       __u32   sb_csum;        /* checksum upto devs[max_dev] */
-       __u32   max_dev;        /* size of devs[] array to consider */
+       __u32   sb_csum;        /* checksum upto dev_roles[max_dev] */
+       __u32   max_dev;        /* size of dev_roles[] array to consider */
        __u8    pad3[64-32];    /* set to 0 when writing */
 
        /* device state information. Indexed by dev_number.
@@ -141,13 +136,72 @@ static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb)
        return __cpu_to_le32(csum);
 }
 
+static char abuf[4096+4096];
+static int aread(int fd, void *buf, int len)
+{
+       /* aligned read.
+        * On devices with a 4K sector size, we need to read
+        * the full sector and copy relevant bits into
+        * the buffer
+        */
+       int bsize;
+       char *b;
+       int n;
+       if (ioctl(fd, BLKSSZGET, &bsize) != 0 ||
+           bsize <= len)
+               return read(fd, buf, len);
+       if (bsize > 4096)
+               return -1;
+       b = (char*)(((long)(abuf+4096))&~4095UL);
+
+       n = read(fd, b, bsize);
+       if (n <= 0)
+               return n;
+       lseek(fd, len - n, 1);
+       if (n > len)
+               n = len;
+       memcpy(buf, b, n);
+       return n;
+}
+
+static int awrite(int fd, void *buf, int len)
+{
+       /* aligned write.
+        * On devices with a 4K sector size, we need to write
+        * the full sector.  We pre-read if the sector is larger
+        * than the write.
+        * The address must be sector-aligned.
+        */
+       int bsize;
+       char *b;
+       int n;
+       if (ioctl(fd, BLKSSZGET, &bsize) != 0 ||
+           bsize <= len)
+               return write(fd, buf, len);
+       if (bsize > 4096)
+               return -1;
+       b = (char*)(((long)(abuf+4096))&~4095UL);
+
+       n = read(fd, b, bsize);
+       if (n <= 0)
+               return n;
+       lseek(fd, -n, 1);
+       memcpy(b, buf, len);
+       n = write(fd, b, bsize);
+       if (n <= 0)
+               return n;
+       lseek(fd, len - n, 1);
+       return len;
+}
+
 #ifndef MDASSEMBLE
 static void examine_super1(struct supertype *st, char *homehost)
 {
        struct mdp_superblock_1 *sb = st->sb;
        time_t atime;
        int d;
-       int faulty;
+       int role;
+       int delta_extra = 0;
        int i;
        char *c;
        int l = homehost ? strlen(homehost) : 0;
@@ -230,13 +284,11 @@ static void examine_super1(struct supertype *st, char *homehost)
                       human_size(__le64_to_cpu(sb->reshape_position)<<9));
                if (__le32_to_cpu(sb->delta_disks)) {
                        printf("  Delta Devices : %d", __le32_to_cpu(sb->delta_disks));
-                       if (__le32_to_cpu(sb->delta_disks))
-                               printf(" (%d->%d)\n",
-                                      __le32_to_cpu(sb->raid_disks)-__le32_to_cpu(sb->delta_disks),
-                                      __le32_to_cpu(sb->raid_disks));
-                       else
-                               printf(" (%d->%d)\n", __le32_to_cpu(sb->raid_disks),
-                                      __le32_to_cpu(sb->raid_disks)+__le32_to_cpu(sb->delta_disks));
+                       printf(" (%d->%d)\n",
+                              __le32_to_cpu(sb->raid_disks)-__le32_to_cpu(sb->delta_disks),
+                              __le32_to_cpu(sb->raid_disks));
+                       if ((int)__le32_to_cpu(sb->delta_disks) < 0)
+                               delta_extra = -__le32_to_cpu(sb->delta_disks);
                }
                if (__le32_to_cpu(sb->new_level) != __le32_to_cpu(sb->level)) {
                        c = map_num(pers, __le32_to_cpu(sb->new_level));
@@ -247,6 +299,10 @@ static void examine_super1(struct supertype *st, char *homehost)
                                c = map_num(r5layout, __le32_to_cpu(sb->new_layout));
                                printf("     New Layout : %s\n", c?c:"-unknown-");
                        }
+                       if (__le32_to_cpu(sb->level) == 6) {
+                               c = map_num(r6layout, __le32_to_cpu(sb->new_layout));
+                               printf("     New Layout : %s\n", c?c:"-unknown-");
+                       }
                        if (__le32_to_cpu(sb->level) == 10) {
                                printf("     New Layout :");
                                print_r10_layout(__le32_to_cpu(sb->new_layout));
@@ -278,6 +334,10 @@ static void examine_super1(struct supertype *st, char *homehost)
                c = map_num(r5layout, __le32_to_cpu(sb->layout));
                printf("         Layout : %s\n", c?c:"-unknown-");
        }
+       if (__le32_to_cpu(sb->level) == 6) {
+               c = map_num(r6layout, __le32_to_cpu(sb->layout));
+               printf("         Layout : %s\n", c?c:"-unknown-");
+       }
        if (__le32_to_cpu(sb->level) == 10) {
                int lo = __le32_to_cpu(sb->layout);
                printf("         Layout :");
@@ -298,6 +358,8 @@ static void examine_super1(struct supertype *st, char *homehost)
        default: break;
        }
        printf("\n");
+#if 0
+       /* This turns out to just be confusing */
        printf("    Array Slot : %d (", __le32_to_cpu(sb->dev_number));
        for (i= __le32_to_cpu(sb->max_dev); i> 0 ; i--)
                if (__le16_to_cpu(sb->dev_roles[i-1]) != 0xffff)
@@ -310,8 +372,20 @@ static void examine_super1(struct supertype *st, char *homehost)
                else printf("%d", role);
        }
        printf(")\n");
+#endif
+       printf("   Device Role : ");
+       d = __le32_to_cpu(sb->dev_number);
+       if (d < __le32_to_cpu(sb->max_dev))
+               role = __le16_to_cpu(sb->dev_roles[d]);
+       else
+               role = 0xFFFF;
+       if (role >= 0xFFFE)
+               printf("spare\n");
+       else
+               printf("Active device %d\n", role);
+
        printf("   Array State : ");
-       for (d=0; d<__le32_to_cpu(sb->raid_disks); d++) {
+       for (d=0; d<__le32_to_cpu(sb->raid_disks) + delta_extra; d++) {
                int cnt = 0;
                int me = 0;
                int i;
@@ -324,10 +398,11 @@ static void examine_super1(struct supertype *st, char *homehost)
                        }
                }
                if (cnt > 1) printf("?");
-               else if (cnt == 1 && me) printf("U");
-               else if (cnt == 1) printf("u");
-               else printf ("_");
+               else if (cnt == 1) printf("A");
+               else printf (".");
        }
+#if 0
+       /* This is confusing too */
        faulty = 0;
        for (i=0; i< __le32_to_cpu(sb->max_dev); i++) {
                int role = __le16_to_cpu(sb->dev_roles[i]);
@@ -335,11 +410,13 @@ static void examine_super1(struct supertype *st, char *homehost)
                        faulty++;
        }
        if (faulty) printf(" %d failed", faulty);
+#endif
+       printf(" ('A' == active, '.' == missing)");
        printf("\n");
 }
 
 
-static void brief_examine_super1(struct supertype *st)
+static void brief_examine_super1(struct supertype *st, int verbose)
 {
        struct mdp_superblock_1 *sb = st->sb;
        int i;
@@ -353,17 +430,21 @@ static void brief_examine_super1(struct supertype *st)
        else if (sb->set_name[0])
                nm = sb->set_name;
        else
-               nm = "??";
+               nm = NULL;
 
-       printf("ARRAY /dev/md/%s level=%s ", nm, c?c:"-unknown-");
+       printf("ARRAY%s%s", nm ? " /dev/md/":"", nm);
+       if (verbose && c)
+               printf(" level=%s", c);
        sb_offset = __le64_to_cpu(sb->super_offset);
        if (sb_offset <= 4)
-               printf("metadata=1.1 ");
+               printf(" metadata=1.1 ");
        else if (sb_offset <= 8)
-               printf("metadata=1.2 ");
+               printf(" metadata=1.2 ");
        else
-               printf("metadata=1.0 ");
-       printf("num-devices=%d UUID=", __le32_to_cpu(sb->raid_disks));
+               printf(" metadata=1.0 ");
+       if (verbose)
+               printf("num-devices=%d ", __le32_to_cpu(sb->raid_disks));
+       printf("UUID=");
        for (i=0; i<16; i++) {
                if ((i&3)==0 && i != 0) printf(":");
                printf("%02x", sb->set_uuid[i]);
@@ -513,7 +594,7 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info)
        info->disk.raid_disk = -1;
        switch(role) {
        case 0xFFFF:
-               info->disk.state = 2; /* spare: ACTIVE, not sync, not faulty */
+               info->disk.state = 0; /* spare: not active, not sync, not faulty */
                break;
        case 0xFFFE:
                info->disk.state = 1; /* faulty */
@@ -531,6 +612,11 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info)
        strncpy(info->name, sb->set_name, 32);
        info->name[32] = 0;
 
+       if (sb->feature_map & __le32_to_cpu(MD_FEATURE_RECOVERY_OFFSET))
+               info->recovery_start = __le32_to_cpu(sb->recovery_offset);
+       else
+               info->recovery_start = MaxSector;
+
        if (sb->feature_map & __le32_to_cpu(MD_FEATURE_RESHAPE_ACTIVE)) {
                info->reshape_active = 1;
                info->reshape_progress = __le64_to_cpu(sb->reshape_position);
@@ -538,6 +624,8 @@ static void getinfo_super1(struct supertype *st, struct mdinfo *info)
                info->delta_disks = __le32_to_cpu(sb->delta_disks);
                info->new_layout = __le32_to_cpu(sb->new_layout);
                info->new_chunk = __le32_to_cpu(sb->new_chunk)<<9;
+               if (info->delta_disks < 0)
+                       info->array.raid_disks -= info->delta_disks;
        } else
                info->reshape_active = 0;
 
@@ -576,9 +664,9 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
                switch(__le32_to_cpu(sb->level)) {
                case 5: case 4: case 6:
                        /* need to force clean */
-                       if (sb->resync_offset != ~0ULL)
+                       if (sb->resync_offset != MaxSector)
                                rv = 1;
-                       sb->resync_offset = ~0ULL;
+                       sb->resync_offset = MaxSector;
                }
        }
        if (strcmp(update, "assemble")==0) {
@@ -608,11 +696,11 @@ static int update_super1(struct supertype *st, struct mdinfo *info,
 
                if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 ||
                    read(rfd, sb->device_uuid, 16) != 16) {
-                       *(__u32*)(sb->device_uuid) = random();
-                       *(__u32*)(sb->device_uuid+4) = random();
-                       *(__u32*)(sb->device_uuid+8) = random();
-                       *(__u32*)(sb->device_uuid+12) = random();
+                       __u32 r[4] = {random(), random(), random(), random()};
+                       memcpy(sb->device_uuid, r, 16);
                }
+               if (rfd >= 0)
+                       close(rfd);
 
                sb->dev_roles[i] =
                        __cpu_to_le16(info->disk.raid_disk);
@@ -737,10 +825,8 @@ static int init_super1(struct supertype *st, mdu_array_info_t *info,
        else {
                if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 ||
                    read(rfd, sb->set_uuid, 16) != 16) {
-                       *(__u32*)(sb->set_uuid) = random();
-                       *(__u32*)(sb->set_uuid+4) = random();
-                       *(__u32*)(sb->set_uuid+8) = random();
-                       *(__u32*)(sb->set_uuid+12) = random();
+                       __u32 r[4] = {random(), random(), random(), random()};
+                       memcpy(sb->set_uuid, r, 16);
                }
                if (rfd >= 0) close(rfd);
        }
@@ -774,7 +860,7 @@ static int init_super1(struct supertype *st, mdu_array_info_t *info,
        sb->utime = sb->ctime;
        sb->events = __cpu_to_le64(1);
        if (info->state & (1<<MD_SB_CLEAN))
-               sb->resync_offset = ~0ULL;
+               sb->resync_offset = MaxSector;
        else
                sb->resync_offset = 0;
        sb->max_dev = __cpu_to_le32((1024- sizeof(struct mdp_superblock_1))/
@@ -794,7 +880,7 @@ struct devinfo {
 };
 #ifndef MDASSEMBLE
 /* Add a device to the superblock being created */
-static void add_to_super1(struct supertype *st, mdu_disk_info_t *dk,
+static int add_to_super1(struct supertype *st, mdu_disk_info_t *dk,
                          int fd, char *devname)
 {
        struct mdp_superblock_1 *sb = st->sb;
@@ -808,6 +894,10 @@ static void add_to_super1(struct supertype *st, mdu_disk_info_t *dk,
        else
                *rp = 0xfffe;
 
+       if (dk->number >= __le32_to_cpu(sb->max_dev) &&
+           __le32_to_cpu(sb->max_dev) < 384)
+               sb->max_dev = __cpu_to_le32(dk->number+1);
+
        sb->dev_number = __cpu_to_le32(dk->number);
        sb->sb_csum = calc_sb_1_csum(sb);
 
@@ -820,6 +910,8 @@ static void add_to_super1(struct supertype *st, mdu_disk_info_t *dk,
        di->disk = *dk;
        di->next = NULL;
        *dip = di;
+
+       return 0;
 }
 #endif
 
@@ -879,7 +971,7 @@ static int store_super1(struct supertype *st, int fd)
        sbsize = sizeof(*sb) + 2 * __le32_to_cpu(sb->max_dev);
        sbsize = (sbsize+511)&(~511UL);
 
-       if (write(fd, sb, sbsize) != sbsize)
+       if (awrite(fd, sb, sbsize) != sbsize)
                return 4;
 
        if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) {
@@ -887,8 +979,8 @@ static int store_super1(struct supertype *st, int fd)
                        (((char*)sb)+1024);
                if (__le32_to_cpu(bm->magic) == BITMAP_MAGIC) {
                        locate_bitmap1(st, fd);
-                       if (write(fd, bm, ROUND_UP(sizeof(*bm),512)) !=
-                           ROUND_UP(sizeof(*bm),512))
+                       if (awrite(fd, bm, sizeof(*bm)) !=
+                           sizeof(*bm))
                            return 5;
                }
        }
@@ -902,6 +994,8 @@ static unsigned long choose_bm_space(unsigned long devsize)
 {
        /* if the device is bigger than 8Gig, save 64k for bitmap usage,
         * if bigger than 200Gig, save 128k
+        * NOTE: result must be multiple of 4K else bad things happen
+        * on 4K-sector devices.
         */
        if (devsize < 64*2) return 0;
        if (devsize - 64*2 >= 200*1024*1024*2)
@@ -919,6 +1013,7 @@ static int write_init_super1(struct supertype *st)
        int rfd;
        int rv = 0;
        int bm_space;
+       unsigned long long reserved;
        struct devinfo *di;
        unsigned long long dsize, array_size;
        long long sb_offset;
@@ -929,8 +1024,8 @@ static int write_init_super1(struct supertype *st)
                if (di->fd < 0)
                        continue;
 
-               Kill(di->devname, 0, 1, 1);
-               Kill(di->devname, 0, 1, 1);
+               while (Kill(di->devname, NULL, 0, 1, 1) == 0)
+                       ;
 
                sb->dev_number = __cpu_to_le32(di->disk.number);
                if (di->disk.state & (1<<MD_DISK_WRITEMOSTLY))
@@ -938,12 +1033,12 @@ static int write_init_super1(struct supertype *st)
 
                if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 ||
                    read(rfd, sb->device_uuid, 16) != 16) {
-                       *(__u32*)(sb->device_uuid) = random();
-                       *(__u32*)(sb->device_uuid+4) = random();
-                       *(__u32*)(sb->device_uuid+8) = random();
-                       *(__u32*)(sb->device_uuid+12) = random();
+                       __u32 r[4] = {random(), random(), random(), random()};
+                       memcpy(sb->device_uuid, r, 16);
                }
-               if (rfd >= 0) close(rfd);
+               if (rfd >= 0)
+                       close(rfd);
+
                sb->events = 0;
 
                refst =*st;
@@ -996,16 +1091,23 @@ static int write_init_super1(struct supertype *st)
                        sb_offset &= ~(4*2-1);
                        sb->super_offset = __cpu_to_le64(sb_offset);
                        sb->data_offset = __cpu_to_le64(0);
-               if (sb_offset - bm_space < array_size)
-                       bm_space = sb_offset - array_size;
+                       if (sb_offset - bm_space < array_size)
+                               bm_space = sb_offset - array_size;
                        sb->data_size = __cpu_to_le64(sb_offset - bm_space);
                        break;
                case 1:
                        sb->super_offset = __cpu_to_le64(0);
-                       if (4*2 + bm_space + __le64_to_cpu(sb->size) > dsize)
-                               bm_space = dsize - __le64_to_cpu(sb->size) -4*2;
-                       sb->data_offset = __cpu_to_le64(bm_space + 4*2);
-                       sb->data_size = __cpu_to_le64(dsize - bm_space - 4*2);
+                       reserved = bm_space + 4*2;
+                       /* Try for multiple of 1Meg so it is nicely aligned */
+                       #define ONE_MEG (2*1024)
+                       reserved = ((reserved + ONE_MEG-1)/ONE_MEG) * ONE_MEG;
+                       if (reserved + __le64_to_cpu(sb->size) > dsize)
+                               reserved = dsize - __le64_to_cpu(sb->size);
+                       /* force 4K alignment */
+                       reserved &= ~7ULL;
+
+                       sb->data_offset = __cpu_to_le64(reserved);
+                       sb->data_size = __cpu_to_le64(dsize - reserved);
                        break;
                case 2:
                        sb_offset = 4*2;
@@ -1014,9 +1116,18 @@ static int write_init_super1(struct supertype *st)
                            > dsize)
                                bm_space = dsize - __le64_to_cpu(sb->size)
                                        - 4*2 - 4*2;
-                       sb->data_offset = __cpu_to_le64(4*2 + 4*2 + bm_space);
-                       sb->data_size = __cpu_to_le64(dsize - 4*2 - 4*2
-                                                     - bm_space );
+
+                       reserved = bm_space + 4*2 + 4*2;
+                       /* Try for multiple of 1Meg so it is nicely aligned */
+                       #define ONE_MEG (2*1024)
+                       reserved = ((reserved + ONE_MEG-1)/ONE_MEG) * ONE_MEG;
+                       if (reserved + __le64_to_cpu(sb->size) > dsize)
+                               reserved = dsize - __le64_to_cpu(sb->size);
+                       /* force 4K alignment */
+                       reserved &= ~7ULL;
+
+                       sb->data_offset = __cpu_to_le64(reserved);
+                       sb->data_size = __cpu_to_le64(dsize - reserved);
                        break;
                default:
                        return -EINVAL;
@@ -1185,7 +1296,7 @@ static int load_super1(struct supertype *st, int fd, char *devname)
                return 1;
        }
 
-       if (read(fd, super, 1024) != 1024) {
+       if (aread(fd, super, 1024) != 1024) {
                if (devname)
                        fprintf(stderr, Name ": Cannot read superblock on %s\n",
                                devname);
@@ -1230,7 +1341,7 @@ static int load_super1(struct supertype *st, int fd, char *devname)
         * should get that written out.
         */
        locate_bitmap1(st, fd);
-       if (read(fd, ((char*)super)+1024, 512)
+       if (aread(fd, ((char*)super)+1024, 512)
            != 512)
                goto no_bitmap;
 
@@ -1264,11 +1375,14 @@ static struct supertype *match_metadata_desc1(char *arg)
                return st;
        }
        if (strcmp(arg, "1.1") == 0 ||
-           strcmp(arg, "1.01") == 0) {
+           strcmp(arg, "1.01") == 0 ||
+           strcmp(arg, "") == 0 /* no metadata */
+               ) {
                st->minor_version = 1;
                return st;
        }
        if (strcmp(arg, "1.2") == 0 ||
+           strcmp(arg, "default") == 0 ||
            strcmp(arg, "1.02") == 0) {
                st->minor_version = 2;
                return st;
@@ -1305,10 +1419,19 @@ static __u64 avail_size1(struct supertype *st, __u64 devsize)
        }
 #endif
 
+       if (st->minor_version < 0)
+               /* not specified, so time to set default */
+               st->minor_version = 2;
+       if (super == NULL && st->minor_version > 0) {
+               /* haven't committed to a size yet, so allow some
+                * slack for alignment of data_offset.
+                * We haven't access to device details so allow
+                * 1 Meg if bigger than 1Gig
+                */
+               if (devsize > 1024*1024*2)
+                       devsize -= 1024*2;
+       }
        switch(st->minor_version) {
-       case -1: /* no specified.  Now time to set default */
-               st->minor_version = 0;
-               /* FALL THROUGH */
        case 0:
                /* at end */
                return ((devsize - 8*2 ) & ~(4*2-1));
@@ -1350,8 +1473,8 @@ add_internal_bitmap1(struct supertype *st,
 
        switch(st->minor_version) {
        case 0:
-               /* either 3K after the superblock, or some amount of space
-                * before.
+               /* either 3K after the superblock (when hot-add),
+                * or some amount of space before.
                 */
                if (may_change) {
                        /* We are creating array, so we *know* how much room has
@@ -1359,11 +1482,6 @@ add_internal_bitmap1(struct supertype *st,
                         */
                        offset = 0;
                        room = choose_bm_space(__le64_to_cpu(sb->size));
-                       if (room == 4*2) {
-                               /* make it 3K after the superblock */
-                               room = 3*2;
-                               offset = 2;
-                       }
                } else {
                        room = __le64_to_cpu(sb->super_offset)
                                - __le64_to_cpu(sb->data_offset)
@@ -1411,16 +1529,25 @@ add_internal_bitmap1(struct supertype *st,
                min_chunk *= 2;
                bits = (bits+1)/2;
        }
-       if (chunk == UnSet)
+       if (chunk == UnSet) {
+               /* For practical purpose, 64Meg is a good
+                * default chunk size for internal bitmaps.
+                */
                chunk = min_chunk;
-       else if (chunk < min_chunk)
+               if (chunk < 64*1024*1024)
+                       chunk = 64*1024*1024;
+       } else if (chunk < min_chunk)
                return 0; /* chunk size too small */
        if (chunk == 0) /* rounding problem */
                return 0;
 
        if (offset == 0) {
+               /* start bitmap on a 4K boundary with enough space for
+                * the bitmap
+                */
                bits = (size*512) / chunk + 1;
-               room = ((bits+7)/8 + sizeof(bitmap_super_t) +511)/512;
+               room = ((bits+7)/8 + sizeof(bitmap_super_t) +4095)/4096;
+               room *= 8; /* convert 4K blocks to sectors */
                offset = -room;
        }
 
@@ -1468,8 +1595,7 @@ static int write_bitmap1(struct supertype *st, int fd)
        int rv = 0;
 
        int towrite, n;
-       char abuf[4096+512];
-       char *buf = (char*)(((long)(abuf+512))&~511UL);
+       char *buf = (char*)(((long)(abuf+4096))&~4095UL);
 
        locate_bitmap1(st, fd);
 
@@ -1515,8 +1641,11 @@ static int validate_geometry1(struct supertype *st, int level,
        unsigned long long ldsize;
        int fd;
 
-       if (level == LEVEL_CONTAINER)
+       if (level == LEVEL_CONTAINER) {
+               if (verbose)
+                       fprintf(stderr, Name ": 1.x metadata does not support containers\n");
                return 0;
+       }
        if (!subdev)
                return 1;
 
@@ -1570,4 +1699,5 @@ struct superswitch super1 = {
 #else
        .swapuuid = 1,
 #endif
+       .name = "1.x",
 };