]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Merge branch 'master' in devel-3.0
authorNeilBrown <neilb@suse.de>
Tue, 10 Mar 2009 05:47:02 +0000 (16:47 +1100)
committerNeilBrown <neilb@suse.de>
Tue, 10 Mar 2009 05:47:02 +0000 (16:47 +1100)
1  2 
Makefile
Monitor.c
inventory
mdassemble.c
super1.c

diff --combined Makefile
index 30f45c79572814f9a055c9cf859f13cdd5b500c1,24ad694fdaef91756b8b0aa4dabbccd5ab3de44e..94a55d935ac695a97eae1adc7d36a312e7f3ae44
+++ b/Makefile
  # e.g.  make CXFLAGS=-O to optimise
  TCC = tcc
  UCLIBC_GCC = $(shell for nm in i386-uclibc-linux-gcc i386-uclibc-gcc; do which $$nm > /dev/null && { echo $$nm ; exit; } ; done; echo false No uclibc found )
 -DIET_GCC = diet gcc
 +#DIET_GCC = diet gcc
 +# sorry, but diet-libc doesn't know about posix_memalign, 
 +# so we cannot use it any more.
 +DIET_GCC = gcc -DHAVE_STDINT_H
  
  KLIBC=/home/src/klibc/klibc-0.77
  
@@@ -43,9 -40,6 +43,9 @@@ KLIBC_GCC = gcc -nostdinc -iwithprefix 
  CC = $(CROSS_COMPILE)gcc
  CXFLAGS = -ggdb
  CWFLAGS = -Wall -Werror -Wstrict-prototypes
 +ifdef WARN_UNUSED
 +CWFLAGS += -Wp,-D_FORTIFY_SOURCE=2 -O
 +endif
  
  ifdef DEBIAN
  CPPFLAGS= -DDEBIAN
@@@ -75,41 -69,34 +75,44 @@@ MAN8DIR = $(MANDIR)/man
  OBJS =  mdadm.o config.o mdstat.o  ReadMe.o util.o Manage.o Assemble.o Build.o \
        Create.o Detail.o Examine.o Grow.o Monitor.o dlink.o Kill.o Query.o \
        Incremental.o \
 -      mdopen.o super0.o super1.o bitmap.o restripe.o sysfs.o sha1.o \
 -      mapfile.o
 +      mdopen.o super0.o super1.o super-ddf.o super-intel.o bitmap.o \
 +      restripe.o sysfs.o sha1.o mapfile.o crc32.o sg_io.o msg.o \
 +      platform-intel.o probe_roms.o
 +
  SRCS =  mdadm.c config.c mdstat.c  ReadMe.c util.c Manage.c Assemble.c Build.c \
        Create.c Detail.c Examine.c Grow.c Monitor.c dlink.c Kill.c Query.c \
        Incremental.c \
 -      mdopen.c super0.c super1.c bitmap.c restripe.c sysfs.c sha1.c \
 -      mapfile.c
 +      mdopen.c super0.c super1.c super-ddf.c super-intel.c bitmap.c \
 +      restripe.c sysfs.c sha1.c mapfile.c crc32.c sg_io.c msg.c \
 +      platform-intel.c probe_roms.c
 +
 +MON_OBJS = mdmon.o monitor.o managemon.o util.o mdstat.o sysfs.o config.o \
 +      Kill.o sg_io.o dlink.o ReadMe.o super0.o super1.o super-intel.o \
 +      super-ddf.o sha1.o crc32.o msg.o Monitor.o bitmap.o \
 +      platform-intel.o probe_roms.o
 +
  
  STATICSRC = pwgr.c
  STATICOBJS = pwgr.o
  
  ASSEMBLE_SRCS := mdassemble.c Assemble.c Manage.c config.c dlink.c util.c \
 -      super0.c super1.c sha1.c sysfs.c
 -ASSEMBLE_AUTO_SRCS := mdopen.c mdstat.c
 +      super0.c super1.c super-ddf.c super-intel.c sha1.c crc32.c sg_io.c mdstat.c \
-       platform-intel.c probe_roms.c
- ASSEMBLE_AUTO_SRCS := mdopen.c sysfs.c
++      platform-intel.c probe_roms.c sysfs.c
++ASSEMBLE_AUTO_SRCS := mdopen.c
  ASSEMBLE_FLAGS:= $(CFLAGS) -DMDASSEMBLE
  ifdef MDASSEMBLE_AUTO
  ASSEMBLE_SRCS += $(ASSEMBLE_AUTO_SRCS)
  ASSEMBLE_FLAGS += -DMDASSEMBLE_AUTO
  endif
  
 -all : mdadm mdadm.man md.man mdadm.conf.man
 +all : mdadm mdmon mdadm.man md.man mdadm.conf.man
  
  everything: all mdadm.static swap_super test_stripe \
        mdassemble mdassemble.auto mdassemble.static mdassemble.man \
        mdadm.Os mdadm.O2
+ everything-test: all mdadm.static swap_super test_stripe \
+       mdassemble.auto mdassemble.static mdassemble.man \
+       mdadm.Os mdadm.O2
  # mdadm.uclibc and mdassemble.uclibc don't work on x86-64
  # mdadm.tcc doesn't work..
  
@@@ -132,10 -119,6 +135,10 @@@ mdadm.Os : $(SRCS) mdadm.
  mdadm.O2 : $(SRCS) mdadm.h
        gcc -o mdadm.O2 $(CFLAGS)  -DHAVE_STDINT_H -O2 $(SRCS)
  
 +mdmon : $(MON_OBJS)
 +      $(CC) $(LDFLAGS) -o mdmon $(MON_OBJS) $(LDLIBS)
 +msg.o: msg.c msg.h
 +
  test_stripe : restripe.c mdadm.h
        $(CC) $(CXFLAGS) $(LDFLAGS) -o test_stripe -DMAIN restripe.c
  
@@@ -173,15 -156,13 +176,15 @@@ mdadm.conf.man : mdadm.conf.
  mdassemble.man : mdassemble.8
        nroff -man mdassemble.8 > mdassemble.man
  
 -$(OBJS) : mdadm.h bitmap.h
 +$(OBJS) : mdadm.h mdmon.h bitmap.h
 +$(MON_OBJS) : mdadm.h mdmon.h bitmap.h
  
  sha1.o : sha1.c sha1.h md5.h
        $(CC) $(CFLAGS) -DHAVE_STDINT_H -o sha1.o -c sha1.c
  
 -install : mdadm install-man
 +install : mdadm mdmon install-man install-udev
        $(INSTALL) -D $(STRIP) -m 755 mdadm $(DESTDIR)$(BINDIR)/mdadm
 +      $(INSTALL) -D $(STRIP) -m 755 mdmon $(DESTDIR)$(BINDIR)/mdmon
  
  install-static : mdadm.static install-man
        $(INSTALL) -D $(STRIP) -m 755 mdadm.static $(DESTDIR)$(BINDIR)/mdadm
@@@ -200,9 -181,6 +203,9 @@@ install-man: mdadm.8 md.4 mdadm.conf.
        $(INSTALL) -D -m 644 md.4 $(DESTDIR)$(MAN4DIR)/md.4
        $(INSTALL) -D -m 644 mdadm.conf.5 $(DESTDIR)$(MAN5DIR)/mdadm.conf.5
  
 +install-udev: udev-md-raid.rules
 +      $(INSTALL) -D -m 644 udev-md-raid.rules $(DESTDIR)/lib/udev/rules.d/64-md-raid.rules
 +
  uninstall:
        rm -f $(DESTDIR)$(MAN8DIR)/mdadm.8 md.4 $(DESTDIR)$(MAN4DIR)/md.4 $(DESTDIR)$(MAN5DIR)/mdadm.conf.5 $(DESTDIR)$(BINDIR)/mdadm
  
@@@ -210,17 -188,16 +213,17 @@@ test: mdadm test_stripe swap_supe
        @echo "Please run 'sh ./test' as root"
  
  clean : 
 -      rm -f mdadm $(OBJS) $(STATICOBJS) core *.man mdadm.tcc mdadm.uclibc mdadm.static *.orig *.porig *.rej *.alt \
 +      rm -f mdadm mdmon $(OBJS) $(MON_OBJS) $(STATICOBJS) core *.man \
 +      mdadm.tcc mdadm.uclibc mdadm.static *.orig *.porig *.rej *.alt \
        mdadm.Os mdadm.O2 \
        mdassemble mdassemble.static mdassemble.auto mdassemble.uclibc \
        mdassemble.klibc swap_super \
-       init.cpio.gz mdadm.uclibc.static test_stripe
+       init.cpio.gz mdadm.uclibc.static test_stripe mdmon
  
  dist : clean
        ./makedist
  
- testdist : everything clean
+ testdist : everything-test clean
        ./makedist test
  
  TAGS :
diff --combined Monitor.c
index cbc5d0fe9ebf5ca3a2b6de6f06ad8276dd8d85d7,38256000668ded37368993cdf83a8fc390b5c4b3..af531294cc53c908ea7a1b88f7a1e0870c5c62bf
+++ b/Monitor.c
@@@ -165,10 -165,7 +165,10 @@@ int Monitor(mddev_dev_t devlist
        if (devlist == NULL) {
                mddev_ident_t mdlist = conf_get_ident(NULL);
                for (; mdlist; mdlist=mdlist->next) {
 -                      struct state *st = malloc(sizeof *st);
 +                      struct state *st;
 +                      if (mdlist->devname == NULL)
 +                              continue;
 +                      st = malloc(sizeof *st);
                        if (st == NULL)
                                continue;
                        st->devname = strdup(mdlist->devname);
                                        st->spare_group = NULL;
                                        st->expected_spares = -1;
                                        statelist = st;
+                                       if (test)
+                                               alert("TestMessage", st->devname, NULL, mailaddr, mailfrom, alert_cmd, dosyslog);
                                        alert("NewArray", st->devname, NULL, mailaddr, mailfrom, alert_cmd, dosyslog);
                                        new_found = 1;
                                }
@@@ -605,7 -604,10 +607,7 @@@ int Wait(char *dev
                        strerror(errno));
                return 2;
        }
 -      if (major(stb.st_rdev) == MD_MAJOR)
 -              devnum = minor(stb.st_rdev);
 -      else
 -              devnum = -1-(minor(stb.st_rdev)/64);
 +      devnum = stat2devnum(&stb);
  
        while(1) {
                struct mdstat_ent *ms = mdstat_read(1, 0);
                                break;
  
                if (!e || e->percent < 0) {
 +                      if (e && e->metadata_version &&
 +                          strncmp(e->metadata_version, "external:", 9) == 0) {
 +                              if (is_subarray(&e->metadata_version[9]))
 +                                      ping_monitor(&e->metadata_version[9]);
 +                              else
 +                                      ping_monitor(devnum2devname(devnum));
 +                      }
                        free_mdstat(ms);
                        return rv;
                }
                mdstat_wait(5);
        }
  }
 +
 +static char *clean_states[] = {
 +      "clear", "inactive", "readonly", "read-auto", "clean", NULL };
 +
 +int WaitClean(char *dev, int verbose)
 +{
 +      int fd;
 +      struct mdinfo *mdi;
 +      int rv = 1;
 +      int devnum;
 +
 +      fd = open(dev, O_RDONLY); 
 +      if (fd < 0) {
 +              if (verbose)
 +                      fprintf(stderr, Name ": Couldn't open %s: %s\n", dev, strerror(errno));
 +              return 1;
 +      }
 +
 +      devnum = fd2devnum(fd);
 +      mdi = sysfs_read(fd, devnum, GET_VERSION|GET_LEVEL|GET_SAFEMODE);
 +      if (!mdi) {
 +              if (verbose)
 +                      fprintf(stderr, Name ": Failed to read sysfs attributes for "
 +                              "%s\n", dev);
 +              close(fd);
 +              return 0;
 +      }
 +
 +      switch(mdi->array.level) {
 +      case LEVEL_LINEAR:
 +      case LEVEL_MULTIPATH:
 +      case 0:
 +              /* safemode delay is irrelevant for these levels */
 +              rv = 0;
 +              
 +      }
 +
 +      /* for internal metadata the kernel handles the final clean
 +       * transition, containers can never be dirty
 +       */
 +      if (!is_subarray(mdi->text_version))
 +              rv = 0;
 +
 +      /* safemode disabled ? */
 +      if (mdi->safe_mode_delay == 0)
 +              rv = 0;
 +
 +      if (rv) {
 +              int state_fd = sysfs_open(fd2devnum(fd), NULL, "array_state");
 +              char buf[20];
 +              fd_set fds;
 +              struct timeval tm;
 +
 +              /* minimize the safe_mode_delay and prepare to wait up to 5s
 +               * for writes to quiesce
 +               */
 +              sysfs_set_safemode(mdi, 1);
 +              tm.tv_sec = 5;
 +              tm.tv_usec = 0;
 +
 +              /* give mdmon a chance to checkpoint resync */
 +              sysfs_set_str(mdi, NULL, "sync_action", "idle");
 +
 +              FD_ZERO(&fds);
 +
 +              /* wait for array_state to be clean */
 +              while (1) {
 +                      rv = read(state_fd, buf, sizeof(buf));
 +                      if (rv < 0)
 +                              break;
 +                      if (sysfs_match_word(buf, clean_states) <= 4)
 +                              break;
 +                      FD_SET(state_fd, &fds);
 +                      rv = select(state_fd + 1, &fds, NULL, NULL, &tm);
 +                      if (rv < 0 && errno != EINTR)
 +                              break;
 +                      lseek(state_fd, 0, SEEK_SET);
 +              }
 +              if (rv < 0)
 +                      rv = 1;
 +              else if (ping_monitor(mdi->text_version) == 0) {
 +                      /* we need to ping to close the window between array
 +                       * state transitioning to clean and the metadata being
 +                       * marked clean
 +                       */
 +                      rv = 0;
 +              } else
 +                      rv = 1;
 +              if (rv && verbose)
 +                      fprintf(stderr, Name ": Error waiting for %s to be clean\n",
 +                              dev);
 +
 +              /* restore the original safe_mode_delay */
 +              sysfs_set_safemode(mdi, mdi->safe_mode_delay);
 +              close(state_fd);
 +      }
 +
 +      sysfs_free(mdi);
 +      close(fd);
 +
 +      return rv;
 +}
 +
 +
diff --combined inventory
index dffe802a70ca50d65caba803f3a16d596e6c9caf,32e082758cdaadc44f6f5dbb11005e6269b0afe1..f52ec025bba01d4a544c0a5e79ae05a551548e24
+++ b/inventory
@@@ -23,8 -23,7 +23,9 @@@ ANNOUNCE-2.6.
  ANNOUNCE-2.6.6
  ANNOUNCE-2.6.7
  ANNOUNCE-2.6.8
+ ANNOUNCE-2.6.9
 +ANNOUNCE-3.0-devel1
 +ANNOUNCE-3.0-devel2
  Assemble.c
  bitmap.c
  bitmap.h
@@@ -32,8 -31,6 +33,8 @@@ Build.
  ChangeLog
  config.c
  COPYING
 +crc32.c
 +crc32.h
  Create.c
  Detail.c
  dlink.c
@@@ -47,13 -44,10 +48,13 @@@ inventor
  kernel-patch-2.6.18
  kernel-patch-2.6.18.6
  kernel-patch-2.6.19
 +kernel-patch-2.6.25
 +kernel-patch-2.6.27
  Kill.c
  makedist
  Makefile
  Manage.c
 +managemon.c
  mapfile.c
  md.4
  md5.h
@@@ -65,8 -59,6 +66,8 @@@ mdadm.
  mdadm.spec
  mdassemble.8
  mdassemble.c
 +mdmon.c
 +mdmon.h
  mdopen.c
  md_p.h
  mdstat.c
@@@ -74,23 -66,17 +75,23 @@@ md_u.
  misc/
  misc/syslog-events
  mkinitramfs
 +monitor.c
  Monitor.c
 +msg.c
 +msg.h
  pwgr.c
  Query.c
  raid5extend.c
  ReadMe.c
  README.initramfs
  restripe.c
 +sg_io.c
  sha1.c
  sha1.h
  super0.c
  super1.c
 +super-ddf.c
 +super-intel.c
  swap_super.c
  sysfs.c
  test
@@@ -142,5 -128,4 +143,5 @@@ tests/chec
  tests/testdev
  tests/ToTest
  TODO
 +udev-md-raid.rules
  util.c
diff --combined mdassemble.c
index a680378a113c04778b54b93c73ba1cfc9be62dd9,b0d87b8362e7ceee98571d7ae9ceff12f71ba526..2b955c5bb718e22610d012cd85f2905f7169af24
@@@ -55,7 -55,7 +55,7 @@@ mapping_t pers[] = 
  
  #ifndef MDASSEMBLE_AUTO
  /* from mdopen.c */
 -int open_mddev(char *dev, int autof/*unused */)
 +int open_mddev(char *dev, int report_errors/*unused*/)
  {
        int mdfd = open(dev, O_RDWR);
        if (mdfd < 0)
        }
        return mdfd;
  }
- int sysfs_uevent(struct mdinfo *info, char *event)
- {
-       return 0;
- }
 +int create_mddev(char *dev, char *name, int autof/*unused*/, int trustworthy,
 +               char *chosen)
 +{
 +      return open_mddev(dev, 0);
 +}
  #endif
 +int map_update(struct map_ent **mpp, int devnum, char *metadata,
 +             int *uuid, char *path)
 +{
 +      return 0;
 +}
 +struct map_ent *map_by_name(struct map_ent **mpp, char *name)
 +{
 +      return NULL;
 +}
  
  int rv;
  int mdfd = -1;
@@@ -104,16 -86,19 +100,16 @@@ int main(int argc, char *argv[]) 
        } else
                for (; array_list; array_list = array_list->next) {
                        mdu_array_info_t array;
 -                      mdfd = open_mddev(array_list->devname, array_list->autof);
 -                      if (mdfd < 0) {
 -                              rv |= 1;
 -                              continue;
 -                      }
 -                      if (ioctl(mdfd, GET_ARRAY_INFO, &array) < 0) {
 -                              rv |= Assemble(array_list->st, array_list->devname, mdfd,
 -                                         array_list, NULL, NULL,
 -                                         readonly, runstop, NULL, NULL, verbose, force);
 -                      } else {
 +                      mdfd = open_mddev(array_list->devname, 0);
 +                      if (mdfd >= 0 && ioctl(mdfd, GET_ARRAY_INFO, &array) == 0) {
                                rv |= Manage_ro(array_list->devname, mdfd, -1); /* make it readwrite */
 +                              continue;
                        }
 -                      close(mdfd);
 +                      if (mdfd >= 0)
 +                              close(mdfd);
 +                      rv |= Assemble(array_list->st, array_list->devname,
 +                                     array_list, NULL, NULL,
 +                                     readonly, runstop, NULL, NULL, verbose, force);
                }
        return rv;
  }
diff --combined super1.c
index a4978e8cc5d5db2a58033b8125274d4bb6ba529c,134241249736f552412f7d943c51ee68682d22b3..d1b8a9478ef86da4375177c59312c3c3ef19dbf6
+++ b/super1.c
@@@ -141,71 -141,13 +141,71 @@@ static unsigned int calc_sb_1_csum(stru
        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 i;
        char *c;
        int l = homehost ? strlen(homehost) : 0;
        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)
                else printf("%d", role);
        }
        printf(")\n");
 +#endif
 +      printf("   Device Role : ");
 +      d = __le32_to_cpu(sb->dev_number);
 +      if (d < sb->raid_disks)
 +              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++) {
                int cnt = 0;
                        }
                }
                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]);
                        faulty++;
        }
        if (faulty) printf(" %d failed", faulty);
 +#endif
 +      printf(" ('A' == active, '.' == missing)");
        printf("\n");
  }
  
@@@ -428,11 -353,9 +428,11 @@@ static void brief_examine_super1(struc
        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 level=%s ",
 +             nm ? " /dev/md/":"", nm,
 +             c?c:"-unknown-");
        sb_offset = __le64_to_cpu(sb->super_offset);
        if (sb_offset <= 4)
                printf("metadata=1.1 ");
@@@ -531,6 -454,12 +531,6 @@@ static void export_detail_super1(struc
                }
        if (len)
                printf("MD_NAME=%.*s\n", len, sb->set_name);
 -      printf("MD_UUID=");
 -      for (i=0; i<16; i++) {
 -              if ((i&3)==0 && i != 0) printf(":");
 -              printf("%02x", sb->set_uuid[i]);
 -      }
 -      printf("\n");
  }
  
  #endif
@@@ -562,7 -491,7 +562,7 @@@ static void getinfo_super1(struct super
        int role;
  
        info->array.major_version = 1;
 -      info->array.minor_version = __le32_to_cpu(sb->feature_map);
 +      info->array.minor_version = st->minor_version;
        info->array.patch_version = 0;
        info->array.raid_disks = __le32_to_cpu(sb->raid_disks);
        info->array.level = __le32_to_cpu(sb->level);
                info->disk.raid_disk = role;
        }
        info->events = __le64_to_cpu(sb->events);
 +      sprintf(info->text_version, "1.%d", st->minor_version);
 +      info->safe_mode_delay = 200;
  
        memcpy(info->uuid, sb->set_uuid, 16);
  
@@@ -760,7 -687,7 +760,7 @@@ static int update_super1(struct superty
            __le64_to_cpu(sb->data_offset)) {
                /* set data_size to device size less data_offset */
                struct misc_dev_info *misc = (struct misc_dev_info*)
 -                      (st->sb + 1024 + sizeof(struct bitmap_super_s));
 +                      (st->sb + 1024 + 512);
                printf("Size was %llu\n", (unsigned long long)
                       __le64_to_cpu(sb->data_size));
                sb->data_size = __cpu_to_le64(
  static int init_super1(struct supertype *st, mdu_array_info_t *info,
                       unsigned long long size, char *name, char *homehost, int *uuid)
  {
 -      struct mdp_superblock_1 *sb = malloc(1024 + sizeof(bitmap_super_t) +
 -                                           sizeof(struct misc_dev_info));
 +      struct mdp_superblock_1 *sb;
        int spares;
        int rfd;
        char defname[10];
 +
 +      if (posix_memalign((void**)&sb, 512, (1024 + 512 + 
 +                         sizeof(struct misc_dev_info))) != 0) {
 +              fprintf(stderr, Name
 +                      ": %s could not allocate superblock\n", __func__);
 +              return 0;
 +      }
        memset(sb, 0, 1024);
  
        st->sb = sb;
 -      if (info->major_version == -1) {
 +      if (info == NULL) {
                /* zeroing superblock */
                return 0;
        }
        return 1;
  }
  
 +struct devinfo {
 +      int fd;
 +      char *devname;
 +      mdu_disk_info_t disk;
 +      struct devinfo *next;
 +};
 +#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;
        __u16 *rp = sb->dev_roles + dk->number;
 +      struct devinfo *di, **dip;
 +
        if ((dk->state & 6) == 6) /* active, sync */
                *rp = __cpu_to_le16(dk->raid_disk);
        else if ((dk->state & ~2) == 0) /* active or idle -> spare */
                *rp = 0xffff;
        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);
 +
 +      dip = (struct devinfo **)&st->info;
 +      while (*dip)
 +              dip = &(*dip)->next;
 +      di = malloc(sizeof(struct devinfo));
 +      di->fd = fd;
 +      di->devname = devname;
 +      di->disk = *dk;
 +      di->next = NULL;
 +      *dip = di;
 +
 +      return 0;
  }
 +#endif
  
  static void locate_bitmap1(struct supertype *st, int fd);
  
@@@ -956,9 -854,8 +960,9 @@@ static int store_super1(struct supertyp
                return 3;
  
        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)) {
                        (((char*)sb)+1024);
                if (__le32_to_cpu(bm->magic) == BITMAP_MAGIC) {
                        locate_bitmap1(st, fd);
 -                      if (write(fd, bm, sizeof(*bm)) != sizeof(*bm))
 +                      if (awrite(fd, bm, sizeof(*bm)) !=
 +                          sizeof(*bm))
                            return 5;
                }
        }
@@@ -990,133 -886,123 +994,133 @@@ static unsigned long choose_bm_space(un
        return 4*2;
  }
  
 -static int write_init_super1(struct supertype *st,
 -                           mdu_disk_info_t *dinfo, char *devname)
 +#ifndef MDASSEMBLE
 +static int write_init_super1(struct supertype *st)
  {
        struct mdp_superblock_1 *sb = st->sb;
        struct supertype refst;
 -      int fd = open(devname, O_RDWR | O_EXCL);
        int rfd;
 -      int rv;
 +      int rv = 0;
        int bm_space;
 -
 +      struct devinfo *di;
        unsigned long long dsize, array_size;
        long long sb_offset;
  
 +      for (di = st->info; di && ! rv ; di = di->next) {
 +              if (di->disk.state == 1)
 +                      continue;
 +              if (di->fd < 0)
 +                      continue;
  
 -      if (fd < 0) {
 -              fprintf(stderr, Name ": Failed to open %s to write superblock\n",
 -                      devname);
 -              return -1;
 -      }
 +              Kill(di->devname, 0, 1, 1);
 +              Kill(di->devname, 0, 1, 1);
  
 -      sb->dev_number = __cpu_to_le32(dinfo->number);
 -      if (dinfo->state & (1<<MD_DISK_WRITEMOSTLY))
 -              sb->devflags |= __cpu_to_le32(WriteMostly1);
 +              sb->dev_number = __cpu_to_le32(di->disk.number);
 +              if (di->disk.state & (1<<MD_DISK_WRITEMOSTLY))
 +                      sb->devflags |= __cpu_to_le32(WriteMostly1);
  
 -      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();
 -      }
 -      if (rfd >= 0) close(rfd);
 -      sb->events = 0;
 -
 -      refst =*st;
 -      refst.sb = NULL;
 -      if (load_super1(&refst, fd, NULL)==0) {
 -              struct mdp_superblock_1 *refsb = refst.sb;
 -
 -              memcpy(sb->device_uuid, refsb->device_uuid, 16);
 -              if (memcmp(sb->set_uuid, refsb->set_uuid, 16)==0) {
 -                      /* same array, so preserve events and dev_number */
 -                      sb->events = refsb->events;
 -                      /* bugs in 2.6.17 and earlier mean the dev_number
 -                       * chosen in Manage must be preserved
 -                       */
 -                      if (get_linux_version() >= 2006018)
 -                              sb->dev_number = refsb->dev_number;
 +              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();
 +              }
 +              if (rfd >= 0) close(rfd);
 +              sb->events = 0;
 +
 +              refst =*st;
 +              refst.sb = NULL;
 +              if (load_super1(&refst, di->fd, NULL)==0) {
 +                      struct mdp_superblock_1 *refsb = refst.sb;
 +
 +                      memcpy(sb->device_uuid, refsb->device_uuid, 16);
 +                      if (memcmp(sb->set_uuid, refsb->set_uuid, 16)==0) {
 +                              /* same array, so preserve events and
 +                               * dev_number */
 +                              sb->events = refsb->events;
 +                              /* bugs in 2.6.17 and earlier mean the
 +                               * dev_number chosen in Manage must be preserved
 +                               */
 +                              if (get_linux_version() >= 2006018)
 +                                      sb->dev_number = refsb->dev_number;
 +                      }
 +                      free(refsb);
                }
 -              free(refsb);
 -      }
 -
 -      if (!get_dev_size(fd, NULL, &dsize))
 -              return 1;
 -      dsize >>= 9;
  
 -      if (dsize < 24) {
 -              close(fd);
 -              return 2;
 -      }
 +              if (!get_dev_size(di->fd, NULL, &dsize))
 +                      return 1;
 +              dsize >>= 9;
  
 +              if (dsize < 24) {
 +                      close(di->fd);
 +                      return 2;
 +              }
  
 -      /*
 -       * Calculate the position of the superblock.
 -       * It is always aligned to a 4K boundary and
 -       * depending on minor_version, it can be:
 -       * 0: At least 8K, but less than 12K, from end of device
 -       * 1: At start of device
 -       * 2: 4K from start of device.
 -       * Depending on the array size, we might leave extra space
 -       * for a bitmap.
 -       */
 -      array_size = __le64_to_cpu(sb->size);
 -      /* work out how much space we left for a bitmap */
 -      bm_space = choose_bm_space(array_size);
  
 -      switch(st->minor_version) {
 -      case 0:
 -              sb_offset = dsize;
 -              sb_offset -= 8*2;
 -              sb_offset &= ~(4*2-1);
 -              sb->super_offset = __cpu_to_le64(sb_offset);
 -              sb->data_offset = __cpu_to_le64(0);
 +              /*
 +               * Calculate the position of the superblock.
 +               * It is always aligned to a 4K boundary and
 +               * depending on minor_version, it can be:
 +               * 0: At least 8K, but less than 12K, from end of device
 +               * 1: At start of device
 +               * 2: 4K from start of device.
 +               * Depending on the array size, we might leave extra space
 +               * for a bitmap.
 +               */
 +              array_size = __le64_to_cpu(sb->size);
 +              /* work out how much space we left for a bitmap */
 +              bm_space = choose_bm_space(array_size);
 +
 +              switch(st->minor_version) {
 +              case 0:
 +                      sb_offset = dsize;
 +                      sb_offset -= 8*2;
 +                      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;
 -              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);
 -              break;
 -      case 2:
 -              sb_offset = 4*2;
 -              sb->super_offset = __cpu_to_le64(4*2);
 -              if (4*2 + 4*2 + bm_space + __le64_to_cpu(sb->size) > 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 );
 -              break;
 -      default:
 -              return -EINVAL;
 -      }
 +                      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);
 +                      break;
 +              case 2:
 +                      sb_offset = 4*2;
 +                      sb->super_offset = __cpu_to_le64(4*2);
 +                      if (4*2 + 4*2 + bm_space + __le64_to_cpu(sb->size)
 +                          > 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 );
 +                      break;
 +              default:
 +                      return -EINVAL;
 +              }
  
  
 -      sb->sb_csum = calc_sb_1_csum(sb);
 -      rv = store_super1(st, fd);
 -      if (rv)
 -              fprintf(stderr, Name ": failed to write superblock to %s\n", devname);
 +              sb->sb_csum = calc_sb_1_csum(sb);
 +              rv = store_super1(st, di->fd);
 +              if (rv)
 +                      fprintf(stderr,
 +                              Name ": failed to write superblock to %s\n",
 +                              di->devname);
  
 -      if (rv == 0 && (__le32_to_cpu(sb->feature_map) & 1))
 -              rv = st->ss->write_bitmap(st, fd);
 -      close(fd);
 +              if (rv == 0 && (__le32_to_cpu(sb->feature_map) & 1))
 +                      rv = st->ss->write_bitmap(st, di->fd);
 +              close(di->fd);
 +              di->fd = -1;
 +      }
        return rv;
  }
 +#endif
  
  static int compare_super1(struct supertype *st, struct supertype *tst)
  {
                return 1;
  
        if (!first) {
 -              first = malloc(1024+sizeof(bitmap_super_t) +
 -                             sizeof(struct misc_dev_info));
 -              memcpy(first, second, 1024+sizeof(bitmap_super_t) +
 +              if (posix_memalign((void**)&first, 512,
 +                             1024 + 512 +
 +                             sizeof(struct misc_dev_info)) != 0) {
 +                      fprintf(stderr, Name
 +                              ": %s could not allocate superblock\n", __func__);
 +                      return 1;
 +              }
 +              memcpy(first, second, 1024 + 512 + 
                       sizeof(struct misc_dev_info));
                st->sb = first;
                return 0;
@@@ -1174,16 -1055,13 +1178,16 @@@ static int load_super1(struct supertyp
  
        free_super1(st);
  
 +      if (st->subarray[0])
 +              return 1;
 +
        if (st->ss == NULL || st->minor_version == -1) {
                int bestvers = -1;
                struct supertype tst;
                __u64 bestctime = 0;
                /* guess... choose latest ctime */
 +              memset(&tst, 0, sizeof(tst));
                tst.ss = &super1;
 -              tst.sb = NULL;
                for (tst.minor_version = 0; tst.minor_version <= 2 ; tst.minor_version++) {
                        switch(load_super1(&tst, fd, devname)) {
                        case 0: super = tst.sb;
                return 1;
        }
  
 -      super = malloc(1024 + sizeof(bitmap_super_t) +
 -                     sizeof(struct misc_dev_info));
 +      if (posix_memalign((void**)&super, 512,
 +                     1024 + 512 +
 +                     sizeof(struct misc_dev_info)) != 0) {
 +              fprintf(stderr, Name ": %s could not allocate superblock\n",
 +                      __func__);
 +              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);
  
        bsb = (struct bitmap_super_s *)(((char*)super)+1024);
  
 -      misc = (struct misc_dev_info*) (bsb+1);
 +      misc = (struct misc_dev_info*) (((char*)super)+1024+512);
        misc->device_size = dsize;
  
        /* Now check on the bitmap superblock */
         * should get that written out.
         */
        locate_bitmap1(st, fd);
 -      if (read(fd, ((char*)super)+1024, sizeof(struct bitmap_super_s))
 -          != sizeof(struct bitmap_super_s))
 +      if (aread(fd, ((char*)super)+1024, 512)
 +          != 512)
                goto no_bitmap;
  
        uuid_from_super1(st, uuid);
@@@ -1330,30 -1203,26 +1334,30 @@@ static struct supertype *match_metadata
        struct supertype *st = malloc(sizeof(*st));
        if (!st) return st;
  
 +      memset(st, 0, sizeof(*st));
        st->ss = &super1;
        st->max_devs = 384;
        st->sb = NULL;
 -      /* Eliminate pointless leading 0 from some versions of mdadm -D */
 -      if (strncmp(arg, "01.", 3) == 0)
 +      /* leading zeros can be safely ignored.  --detail generates them. */
 +      while (*arg == '0')
                arg++;
 -      if (strcmp(arg, "1.0") == 0) {
 +      if (strcmp(arg, "1.0") == 0 ||
 +          strcmp(arg, "1.00") == 0) {
                st->minor_version = 0;
                return st;
        }
 -      if (strcmp(arg, "1.1") == 0) {
 +      if (strcmp(arg, "1.1") == 0 ||
 +          strcmp(arg, "1.01") == 0) {
                st->minor_version = 1;
                return st;
        }
 -      if (strcmp(arg, "1.2") == 0) {
 +      if (strcmp(arg, "1.2") == 0 ||
 +          strcmp(arg, "1.02") == 0) {
                st->minor_version = 2;
                return st;
        }
        if (strcmp(arg, "1") == 0 ||
 -          strcmp(arg, "default/large") == 0) {
 +          strcmp(arg, "default") == 0) {
                st->minor_version = -1;
                return st;
        }
@@@ -1547,27 -1416,25 +1551,27 @@@ static int write_bitmap1(struct superty
        int rv = 0;
  
        int towrite, n;
 -      char buf[4096];
 +      char *buf = (char*)(((long)(abuf+4096))&~4095UL);
  
        locate_bitmap1(st, fd);
  
 -      if (write(fd, ((char*)sb)+1024, sizeof(bitmap_super_t)) !=
 -          sizeof(bitmap_super_t))
 -              return -2;
 +      memset(buf, 0xff, 4096);
 +      memcpy(buf, ((char*)sb)+1024, sizeof(bitmap_super_t));
 +
        towrite = __le64_to_cpu(bms->sync_size) / (__le32_to_cpu(bms->chunksize)>>9);
        towrite = (towrite+7) >> 3; /* bits to bytes */
 -      memset(buf, 0xff, sizeof(buf));
 +      towrite += sizeof(bitmap_super_t);
 +      towrite = ROUND_UP(towrite, 512);
        while (towrite > 0) {
                n = towrite;
 -              if (n > sizeof(buf))
 -                      n = sizeof(buf);
 +              if (n > 4096)
 +                      n = 4096;
                n = write(fd, buf, n);
                if (n > 0)
                        towrite -= n;
                else
                        break;
 +              memset(buf, 0xff, 4096);
        }
        fsync(fd);
        if (towrite)
@@@ -1583,40 -1450,6 +1587,40 @@@ static void free_super1(struct supertyp
        st->sb = NULL;
  }
  
 +#ifndef MDASSEMBLE
 +static int validate_geometry1(struct supertype *st, int level,
 +                            int layout, int raiddisks,
 +                            int chunk, unsigned long long size,
 +                            char *subdev, unsigned long long *freesize,
 +                            int verbose)
 +{
 +      unsigned long long ldsize;
 +      int fd;
 +
 +      if (level == LEVEL_CONTAINER)
 +              return 0;
 +      if (!subdev)
 +              return 1;
 +
 +      fd = open(subdev, O_RDONLY|O_EXCL, 0);
 +      if (fd < 0) {
 +              if (verbose)
 +                      fprintf(stderr, Name ": super1.x cannot open %s: %s\n",
 +                              subdev, strerror(errno));
 +              return 0;
 +      }
 +
 +      if (!get_dev_size(fd, subdev, &ldsize)) {
 +              close(fd);
 +              return 0;
 +      }
 +      close(fd);
 +
 +      *freesize = avail_size1(st, ldsize >> 9);
 +      return 1;
 +}
 +#endif /* MDASSEMBLE */
 +
  struct superswitch super1 = {
  #ifndef MDASSEMBLE
        .examine_super = examine_super1,
        .detail_super = detail_super1,
        .brief_detail_super = brief_detail_super1,
        .export_detail_super = export_detail_super1,
 +      .write_init_super = write_init_super1,
 +      .validate_geometry = validate_geometry1,
 +      .add_to_super = add_to_super1,
  #endif
        .match_home = match_home1,
        .uuid_from_super = uuid_from_super1,
        .getinfo_super = getinfo_super1,
        .update_super = update_super1,
        .init_super = init_super1,
 -      .add_to_super = add_to_super1,
        .store_super = store_super1,
 -      .write_init_super = write_init_super1,
        .compare_super = compare_super1,
        .load_super = load_super1,
        .match_metadata_desc = match_metadata_desc1,
        .locate_bitmap = locate_bitmap1,
        .write_bitmap = write_bitmap1,
        .free_super = free_super1,
 -      .major = 1,
  #if __BYTE_ORDER == BIG_ENDIAN
        .swapuuid = 0,
  #else
        .swapuuid = 1,
  #endif
 +      .name = "1.0",
  };