]> git.ipfire.org Git - thirdparty/mdadm.git/commitdiff
Merge branch 'master' into devel-3.0
authorNeilBrown <neilb@suse.de>
Mon, 2 Feb 2009 00:09:09 +0000 (11:09 +1100)
committerNeilBrown <neilb@suse.de>
Mon, 2 Feb 2009 00:09:09 +0000 (11:09 +1100)
1  2 
Detail.c
Makefile
ReadMe.c
bitmap.c
mdadm.h

diff --combined Detail.c
index 9be9cfd808b0def053fbfb576c6fae2262e180df,8f86ead88c1ef995d791ddd008907741ea2cc2fe..dea605eae82978cbc31d49e3ceb3f41b325d72b6
+++ b/Detail.c
@@@ -30,7 -30,6 +30,7 @@@
  #include      "mdadm.h"
  #include      "md_p.h"
  #include      "md_u.h"
 +#include      <dirent.h>
  
  int Detail(char *dev, int brief, int export, int test, char *homehost)
  {
@@@ -57,8 -56,6 +57,8 @@@
        int max_disks = MD_SB_DISKS; /* just a default */
        struct mdinfo info;
        struct mdinfo *sra;
 +      char *member = NULL;
 +      char *container = NULL;
  
        int rv = test ? 4 : 1;
        int avail_disks = 0;
                stb.st_rdev = 0;
        rv = 0;
  
 -      if (st) max_disks = st->max_devs;
 +      if (st)
 +              max_disks = st->max_devs;
 +
 +      if (sra && is_subarray(sra->text_version) &&
 +              strchr(sra->text_version+1, '/')) {
 +              /* This is a subarray of some container.
 +               * We want the name of the container, and the member
 +               */
 +              char *s = strchr(sra->text_version+1, '/');
 +              int dn;
 +              *s++ = '\0';
 +              member = s;
 +              dn = devname2devnum(sra->text_version+1);
 +              container = map_dev(dev2major(dn), dev2minor(dn), 1);
 +      }
  
        /* try to load a superblock */
        for (d= 0; d<max_disks; d++) {
                        continue;
                if ((dv=map_dev(disk.major, disk.minor, 1))) {
                        if ((!st || !st->sb) &&
 -                          (disk.state & (1<<MD_DISK_ACTIVE))) {
 +                          (array.raid_disks == 0 || 
 +                           (disk.state & (1<<MD_DISK_ACTIVE)))) {
                                /* try to read the superblock from this device
                                 * to get more info
                                 */
                                if (fd2 >=0 && st &&
                                    st->ss->load_super(st, fd2, NULL) == 0) {
                                        st->ss->getinfo_super(st, &info);
 -                                      if (info.array.ctime != array.ctime ||
 -                                          info.array.level != array.level)
 +                                      if (array.raid_disks != 0 && /* container */
 +                                          (info.array.ctime != array.ctime ||
 +                                           info.array.level != array.level))
                                                st->ss->free_super(st);
                                }
                                if (fd2 >= 0) close(fd2);
        c = map_num(pers, array.level);
  
        if (export) {
 -              if (c)
 -                      printf("MD_LEVEL=%s\n", c);
 -              printf("MD_DEVICES=%d\n", array.raid_disks);
 -              if (sra && sra->array.major_version < 0)
 -                      printf("MD_METADATA=%s\n", sra->text_version);
 -              else
 -                      printf("MD_METADATA=%d.%02d\n",
 -                             array.major_version, array.minor_version);
 +              if (array.raid_disks) {
 +                      if (c)
 +                              printf("MD_LEVEL=%s\n", c);
 +                      printf("MD_DEVICES=%d\n", array.raid_disks);
 +              } else {
 +                      printf("MD_LEVEL=container\n");
 +                      printf("MD_DEVICES=%d\n", array.nr_disks);
 +              }
 +              if (container) {
 +                      printf("MD_CONTAINER=%s\n", container);
 +                      printf("MD_MEMBER=%s\n", member);
 +              } else {
 +                      if (sra && sra->array.major_version < 0)
 +                              printf("MD_METADATA=%s\n", sra->text_version);
 +                      else
 +                              printf("MD_METADATA=%d.%02d\n",
 +                                     array.major_version, array.minor_version);
 +              }
 +              
 +              if (st && st->sb) {
 +                      struct mdinfo info;
 +                      char nbuf[64];
 +                      struct map_ent *mp, *map = NULL;
 +                      st->ss->getinfo_super(st, &info);
 +                      fname_from_uuid(st, &info, nbuf, ':');
 +                      printf("MD_UUID=%s\n", nbuf+5);
 +                      mp = map_by_uuid(&map, info.uuid);
 +                      if (mp && mp->path &&
 +                          strncmp(mp->path, "/dev/md/", 8) == 0)
 +                              printf("MD_DEVNAME=%s\n", mp->path+8);
  
 -              if (st && st->sb)
 -                      st->ss->export_detail_super(st);
 +                      if (st->ss->export_detail_super)
 +                              st->ss->export_detail_super(st);
 +              } else {
 +                      struct map_ent *mp, *map = NULL;
 +                      mp = map_by_devnum(&map, fd2devnum(fd));
 +                      if (mp && mp->path &&
 +                          strncmp(mp->path, "/dev/md/", 8) == 0)
 +                              printf("MD_DEVNAME=%s\n", mp->path+8);
 +              }
                goto out;
        }
  
        if (brief) {
                mdu_bitmap_file_t bmf;
 -              printf("ARRAY %s level=%s num-devices=%d", dev,
 -                     c?c:"-unknown-",
 -                     array.raid_disks );
 -              if (sra && sra->array.major_version < 0)
 -                      printf(" metadata=%s", sra->text_version);
 +              if (array.raid_disks)
 +                      printf("ARRAY %s level=%s num-devices=%d", dev,
 +                             c?c:"-unknown-",
 +                             array.raid_disks );
                else
 -                      printf(" metadata=%d.%02d",
 -                             array.major_version, array.minor_version);
 +                      printf("ARRAY %s level=container num-devices=%d",
 +                             dev, array.nr_disks);
 +
 +              if (container) {
 +                      printf(" container=%s", container);
 +                      printf(" member=%s", member);
 +              } else {
 +                      if (sra && sra->array.major_version < 0)
 +                              printf(" metadata=%s", sra->text_version);
 +                      else
 +                              printf(" metadata=%d.%02d",
 +                                     array.major_version, array.minor_version);
 +              }
  
                /* Only try GET_BITMAP_FILE for 0.90.01 and later */
                if (vers >= 9001 &&
  
                printf("%s:\n", dev);
  
 +              if (container)
 +                      printf("      Container : %s, member %s\n", container, member);
 +              else {
                if (sra && sra->array.major_version < 0)
                        printf("        Version : %s\n", sra->text_version);
                else
                        printf("        Version : %d.%02d\n",
                               array.major_version, array.minor_version);
 +              }
  
                atime = array.ctime;
 -              printf("  Creation Time : %.24s\n", ctime(&atime));
 +              if (atime)
 +                      printf("  Creation Time : %.24s\n", ctime(&atime));
                if (array.raid_disks == 0) c = "container";
                printf("     Raid Level : %s\n", c?c:"-unknown-");
                if (larray_size)
                                unsigned long long dsize = get_component_size(fd);
                                if (dsize > 0)
                                        printf("  Used Dev Size : %llu%s\n",
-                                              dsize,
-                                        human_size((long long)dsize<<10));
+                                              dsize/2,
+                                        human_size((long long)dsize<<9));
                                else
                                        printf("  Used Dev Size : unknown\n");
                        } else
                                printf("  Used Dev Size : %d%s\n", array.size,
                                       human_size((long long)array.size<<10));
                }
 -              printf("   Raid Devices : %d\n", array.raid_disks);
 +              if (array.raid_disks)
 +                      printf("   Raid Devices : %d\n", array.raid_disks);
                printf("  Total Devices : %d\n", array.nr_disks);
 -              printf("Preferred Minor : %d\n", array.md_minor);
 +              if (!container && 
 +                  ((sra == NULL && array.major_version == 0) ||
 +                   (sra && sra->array.major_version == 0)))
 +                      printf("Preferred Minor : %d\n", array.md_minor);
                if (sra == NULL || sra->array.major_version >= 0)
                        printf("    Persistence : Superblock is %spersistent\n",
                               array.not_persistent?"not ":"");
                } else if (array.state & (1<<MD_SB_BITMAP_PRESENT))
                        printf("  Intent Bitmap : Internal\n\n");
                atime = array.utime;
 -              printf("    Update Time : %.24s\n", ctime(&atime));
 -              printf("          State : %s%s%s%s\n",
 -                     (array.state&(1<<MD_SB_CLEAN))?"clean":"active",
 -                     array.active_disks < array.raid_disks? ", degraded":"",
 -                     (!e || e->percent < 0) ? "" :
 -                      (e->resync) ? ", resyncing": ", recovering",
 -                     larray_size ? "": ", Not Started");
 -              printf(" Active Devices : %d\n", array.active_disks);
 +              if (atime)
 +                      printf("    Update Time : %.24s\n", ctime(&atime));
 +              if (array.raid_disks)
 +                      printf("          State : %s%s%s%s\n",
 +                             (array.state&(1<<MD_SB_CLEAN))?"clean":"active",
 +                             array.active_disks < array.raid_disks? ", degraded":"",
 +                             (!e || e->percent < 0) ? "" :
 +                             (e->resync) ? ", resyncing": ", recovering",
 +                             larray_size ? "": ", Not Started");
 +              if (array.raid_disks)
 +                      printf(" Active Devices : %d\n", array.active_disks);
                printf("Working Devices : %d\n", array.working_disks);
 -              printf(" Failed Devices : %d\n", array.failed_disks);
 -              printf("  Spare Devices : %d\n", array.spare_disks);
 +              if (array.raid_disks) {
 +                      printf(" Failed Devices : %d\n", array.failed_disks);
 +                      printf("  Spare Devices : %d\n", array.spare_disks);
 +              }
                printf("\n");
                if (array.level == 5) {
                        c = map_num(r5layout, array.layout);
@@@ -378,45 -306,7 +378,45 @@@ This is pretty borin
                if (st && st->sb)
                        st->ss->detail_super(st, homehost);
  
 -              printf("    Number   Major   Minor   RaidDevice State\n");
 +              if (array.raid_disks == 0 && sra && sra->array.major_version == -1
 +                  && sra->array.minor_version == -2 && sra->text_version[0] != '/') {
 +                      /* This looks like a container.  Find any active arrays
 +                       * That claim to be a member.
 +                       */
 +                      DIR *dir = opendir("/sys/block");
 +                      struct dirent *de;
 +
 +                      printf("  Member Arrays :");
 +
 +                      while (dir && (de = readdir(dir)) != NULL) {
 +                              char path[200];
 +                              char vbuf[1024];
 +                              int nlen = strlen(sra->sys_name);
 +                              int dn;
 +                              if (de->d_name[0] == '.')
 +                                      continue;
 +                              sprintf(path, "/sys/block/%s/md/metadata_version",
 +                                      de->d_name);
 +                              if (load_sys(path, vbuf) < 0)
 +                                      continue;
 +                              if (strncmp(vbuf, "external:", 9) != 0 ||
 +                                  !is_subarray(sra->sys_name+9) ||
 +                                  strncmp(vbuf+10, sra->sys_name, nlen) != 0 ||
 +                                  vbuf[10+nlen] != '/')
 +                                      continue;
 +                              dn = devname2devnum(de->d_name);
 +                              printf(" %s", map_dev(dev2major(dn),
 +                                                    dev2minor(dn), 1));
 +                      }
 +                      if (dir)
 +                              closedir(dir);
 +                      printf("\n\n");
 +              }
 +
 +              if (array.raid_disks)
 +                      printf("    Number   Major   Minor   RaidDevice State\n");
 +              else
 +                      printf("    Number   Major   Minor   RaidDevice\n");
        }
        disks = malloc(max_disks * sizeof(mdu_disk_info_t));
        for (d=0; d<max_disks; d++) {
                        else
                                printf("   %5d   %5d    %5d    %5d     ",
                                       disk.number, disk.major, disk.minor, disk.raid_disk);
 +              }
 +              if (!brief && array.raid_disks) {
 +
                        if (disk.state & (1<<MD_DISK_FAULTY)) {
                                printf(" faulty");
                                if (disk.raid_disk < array.raid_disks &&
                }
                if (!brief) printf("\n");
        }
 -      if (spares && brief) printf(" spares=%d", spares);
 +      if (spares && brief && array.raid_disks) printf(" spares=%d", spares);
        if (brief && st && st->sb)
                st->ss->brief_detail_super(st);
        st->ss->free_super(st);
@@@ -530,44 -417,3 +530,44 @@@ out
        close(fd);
        return rv;
  }
 +
 +int Detail_Platform(struct superswitch *ss, int scan, int verbose)
 +{
 +      /* display platform capabilities for the given metadata format
 +       * 'scan' in this context means iterate over all metadata types
 +       */
 +      int i;
 +      int err = 1;
 +
 +      if (ss && ss->detail_platform)
 +              err = ss->detail_platform(verbose, 0);
 +      else if (ss) {
 +              if (verbose)
 +                      fprintf(stderr, Name ": %s metadata is platform independent\n",
 +                              ss->name ? : "[no name]");
 +      } else if (!scan) {
 +              if (verbose)
 +                      fprintf(stderr, Name ": specify a metadata type or --scan\n");
 +      }
 +
 +      if (!scan)
 +              return err;
 +
 +      for (i = 0; superlist[i]; i++) {
 +              struct superswitch *meta = superlist[i];
 +
 +              if (meta == ss)
 +                      continue;
 +              if (verbose)
 +                      fprintf(stderr, Name ": checking metadata %s\n",
 +                              meta->name ? : "[no name]");
 +              if (!meta->detail_platform) {
 +                      if (verbose)
 +                              fprintf(stderr, Name ": %s metadata is platform independent\n",
 +                                      meta->name ? : "[no name]");
 +              } else
 +                      err |= meta->detail_platform(verbose, 0);
 +      }
 +
 +      return err;
 +}
diff --combined Makefile
index 7f27aa46de199e877416de8c368624688958cb1d,c0e2b5da6136767a8e6d339dd3415b152953f3da..30f45c79572814f9a055c9cf859f13cdd5b500c1
+++ 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,37 -69,27 +75,37 @@@ 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
 -ASSEMBLE_AUTO_SRCS := mdopen.c mdstat.c sysfs.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
  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 \
@@@ -122,9 -106,6 +122,6 @@@ mdadm.static : $(OBJS) $(STATICOBJS
  mdadm.tcc : $(SRCS) mdadm.h
        $(TCC) -o mdadm.tcc $(SRCS)
  
- dadm.uclibc : $(SRCS) mdadm.h
-       $(UCLIBC_GCC) -DUCLIBC -DHAVE_STDINT_H -o mdadm.uclibc $(SRCS) $(STATICSRC)
  mdadm.klibc : $(SRCS) mdadm.h
        rm -f $(OBJS) 
        gcc -nostdinc -iwithprefix include -I$(KLIBC)/klibc/include -I$(KLIBC)/linux/include -I$(KLIBC)/klibc/arch/i386/include -I$(KLIBC)/klibc/include/bits32 $(CFLAGS) $(SRCS)
@@@ -135,10 -116,6 +132,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
  
@@@ -176,15 -153,13 +173,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
@@@ -203,9 -178,6 +200,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
  
@@@ -213,8 -185,7 +210,8 @@@ 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 \
diff --combined ReadMe.c
index ea4d29134dcc44812d75ae799b86b65166bc75a7,3164322b3f4c57211ce317637e07dee3feaa91ab..ea977d22763c54ce0e5d4be8d0cdfe38d30ad720
+++ b/ReadMe.c
@@@ -24,7 -24,7 +24,7 @@@
  
  #include "mdadm.h"
  
 -char Version[] = Name " - v2.6.8 - 28th November 2008\n";
 +char Version[] = Name " - v3.0-devel2 - 5th November 2008\n";
  
  /*
   * File: ReadMe.c
@@@ -107,7 -107,6 +107,7 @@@ struct option long_options[] = 
      {"query",   0, 0, 'Q'},
      {"examine-bitmap", 0, 0, 'X'},
      {"auto-detect", 0, 0, AutoDetect},
 +    {"detail-platform", 0, 0, DetailPlatform},
  
      /* synonyms */
      {"monitor",   0, 0, 'F'},
      {"readwrite", 0, 0, 'w'},
      {"no-degraded",0,0,  NoDegraded },
      {"wait",    0, 0, 'W'},
 +    {"wait-clean", 0, 0, Waitclean },
  
      /* For Detail/Examine */
      {"brief",   0, 0, 'b'},
@@@ -467,7 -465,6 +467,7 @@@ char Help_misc[] 
  "  --query       -Q   : Display general information about how a\n"
  "                       device relates to the md driver\n"
  "  --detail      -D   : Display details of an array\n"
 +"  --detail-platform  : Display hardware/firmware details\n"
  "  --examine     -E   : Examine superblock on an array component\n"
  "  --examine-bitmap -X: Display contents of a bitmap file\n"
  "  --zero-superblock  : erase the MD superblock from a device.\n"
@@@ -520,7 -517,8 +520,8 @@@ char Help_grow[] 
  "  --layout=      -p   : For a FAULTY array, set/change the error mode.\n"
  "  --size=        -z   : Change the active size of devices in an array.\n"
  "                      : This is useful if all devices have been replaced\n"
- "                      : with larger devices.\n"
+ "                      : with larger devices.   Value is in Kilobytes, or\n"
+ "                      : the special word 'max' meaning 'as large as possible'.\n"
  "  --raid-devices= -n  : Change the number of active devices in an array.\n"
  "  --bitmap=      -b   : Add or remove a write-intent bitmap.\n"
  "  --backup-file= file : A file on a differt device to store data for a\n"
@@@ -615,7 -613,6 +616,7 @@@ mapping_t pers[] = 
        { "raid10", 10},
        { "10", 10},
        { "faulty", LEVEL_FAULTY},
 +      { "container", LEVEL_CONTAINER},
        { NULL, 0}
  };
  
diff --combined bitmap.c
index 18101664fa1728e997bdb27826141d5a1f40cca7,352be5d7261a7e130ad900bbbf3d2ff1b5128c34..b9bbaebdf09bfdaa8981314b280db33156ff2c42
+++ b/bitmap.c
@@@ -131,13 -131,11 +131,13 @@@ bitmap_info_t *bitmap_fd_read(int fd, i
         */
        unsigned long long total_bits = 0, read_bits = 0, dirty_bits = 0;
        bitmap_info_t *info;
 -      char *buf, *unaligned;
 +      void *buf;
        int n, skip;
  
 -      unaligned = malloc(8192*2);
 -      buf = (char*) ((unsigned long)unaligned | 8191)+1;
 +      if (posix_memalign(&buf, 512, 8192) != 0) {
 +              fprintf(stderr, Name ": failed to allocate 8192 bytes\n");
 +              return NULL;
 +      }
        n = read(fd, buf, 8192);
  
        info = malloc(sizeof(*info));
                fprintf(stderr, Name ": failed to read superblock of bitmap "
                        "file: %s\n", strerror(errno));
                free(info);
 -              free(unaligned);
                return NULL;
        }
        memcpy(&info->sb, buf, sizeof(info->sb));
  
        sb_le_to_cpu(&info->sb); /* convert superblock to CPU byte ordering */
  
-       if (brief || info->sb.sync_size == 0)
+       if (brief || info->sb.sync_size == 0 || info->sb.chunksize == 0)
                goto out;
  
        /* read the rest of the file counting total bits and dirty bits --
diff --combined mdadm.h
index 7c8c2f127534e3230a65c39666d89f245c502549,0d5c721125b5b5c3e04e4ee81b4f1351c63565ca..5be3affe073a9c2e425c1116543bd6c86d9d12fa
+++ b/mdadm.h
@@@ -76,7 -76,6 +76,7 @@@ extern __off64_t lseek64 __P ((int __fd
  #include      "md_u.h"
  #include      "md_p.h"
  #include      "bitmap.h"
 +#include      "msg.h"
  
  #include <endian.h>
  /* Redhat don't like to #include <asm/byteorder.h>, and
  #define       __le16_to_cpu(_x) (_x)
  #define __le32_to_cpu(_x) (_x)
  #define __le64_to_cpu(_x) (_x)
 +
 +#define       __cpu_to_be16(_x) bswap_16(_x)
 +#define __cpu_to_be32(_x) bswap_32(_x)
 +#define __cpu_to_be64(_x) bswap_64(_x)
 +#define       __be16_to_cpu(_x) bswap_16(_x)
 +#define __be32_to_cpu(_x) bswap_32(_x)
 +#define __be64_to_cpu(_x) bswap_64(_x)
  #elif BYTE_ORDER == BIG_ENDIAN
  #define       __cpu_to_le16(_x) bswap_16(_x)
  #define __cpu_to_le32(_x) bswap_32(_x)
  #define       __le16_to_cpu(_x) bswap_16(_x)
  #define __le32_to_cpu(_x) bswap_32(_x)
  #define __le64_to_cpu(_x) bswap_64(_x)
 +
 +#define       __cpu_to_be16(_x) (_x)
 +#define __cpu_to_be32(_x) (_x)
 +#define __cpu_to_be64(_x) (_x)
 +#define       __be16_to_cpu(_x) (_x)
 +#define __be32_to_cpu(_x) (_x)
 +#define __be64_to_cpu(_x) (_x)
  #else
  #  error "unknown endianness."
  #endif
@@@ -143,38 -128,18 +143,38 @@@ struct mdinfo 
        int                     uuid[4];
        char                    name[33];
        unsigned long long      data_offset;
 -      unsigned long long      component_size;
 +      unsigned long long      component_size; /* same as array.size, except in
 +                                               * sectors and up to 64bits.
 +                                               */
        int                     reshape_active;
        unsigned long long      reshape_progress;
 +      unsigned long long      resync_start;
 +      unsigned long           safe_mode_delay; /* ms delay to mark clean */
        int                     new_level, delta_disks, new_layout, new_chunk;
        int                     errors;
        int                     cache_size; /* size of raid456 stripe cache*/
        int                     mismatch_cnt;
        char                    text_version[50];
  
 +      int container_member; /* for assembling external-metatdata arrays
 +                             * This is to be used internally by metadata
 +                             * handler only */
 +
        char            sys_name[20];
        struct mdinfo *devs;
        struct mdinfo *next;
 +
 +      /* Device info for mdmon: */
 +      int state_fd;
 +      #define DS_FAULTY       1
 +      #define DS_INSYNC       2
 +      #define DS_WRITE_MOSTLY 4
 +      #define DS_SPARE        8
 +      #define DS_BLOCKED      16
 +      #define DS_REMOVE       1024
 +      #define DS_UNBLOCK      2048
 +      int prev_state, curr_state, next_state;
 +
  };
  
  struct createinfo {
@@@ -224,8 -189,6 +224,8 @@@ enum special_options 
        AutoHomeHost,
        Symlinks,
        AutoDetect,
 +      Waitclean,
 +      DetailPlatform,
  };
  
  /* structures read from config file */
@@@ -260,13 -223,6 +260,13 @@@ typedef struct mddev_ident_s 
        char    *bitmap_file;
        int     bitmap_fd;
  
 +      char    *container;     /* /dev/whatever name of container, or
 +                               * uuid of container.  You would expect
 +                               * this to be the 'devname' or UUID
 +                               * of some other entry.
 +                               */
 +      char    *member;        /* subarray within a container */
 +
        struct mddev_ident_s *next;
  } *mddev_ident_t;
  
@@@ -279,8 -235,6 +279,8 @@@ typedef struct mddev_dev_s 
        char writemostly;       /* 1 for 'set writemostly', 2 for 'clear writemostly' */
        char re_add;
        char used;              /* set when used */
 +      struct mdinfo *content; /* If devname is a container, this might list
 +                               * the remaining member arrays. */
        struct mddev_dev_s *next;
  } *mddev_dev_t;
  
@@@ -298,40 -252,30 +298,40 @@@ struct mdstat_ent 
        char            *pattern; /* U or up, _ for down */
        int             percent; /* -1 if no resync */
        int             resync; /* 1 if resync, 0 if recovery */
 +      int             devcnt;
 +      int             raid_disks;
 +      int             chunk_size;
 +      char *          metadata_version;
        struct mdstat_ent *next;
  };
  
  extern struct mdstat_ent *mdstat_read(int hold, int start);
  extern void free_mdstat(struct mdstat_ent *ms);
  extern void mdstat_wait(int seconds);
 +extern void mdstat_wait_fd(int fd, const sigset_t *sigmask);
  extern int mddev_busy(int devnum);
  
  struct map_ent {
        struct map_ent *next;
        int     devnum;
 -      int     major,minor;
 +      char    metadata[20];
        int     uuid[4];
 +      int     bad;
        char    *path;
  };
 -extern int map_update(struct map_ent **mpp, int devnum, int major, int minor,
 +extern int map_update(struct map_ent **mpp, int devnum, char *metadata,
                      int uuid[4], char *path);
  extern struct map_ent *map_by_uuid(struct map_ent **map, int uuid[4]);
 +extern struct map_ent *map_by_devnum(struct map_ent **map, int devnum);
 +extern struct map_ent *map_by_name(struct map_ent **map, char *name);
  extern void map_read(struct map_ent **melp);
  extern int map_write(struct map_ent *mel);
  extern void map_delete(struct map_ent **mapp, int devnum);
  extern void map_free(struct map_ent *map);
  extern void map_add(struct map_ent **melp,
 -                  int devnum, int major, int minor, int uuid[4], char *path);
 +                  int devnum, char *metadata, int uuid[4], char *path);
 +extern int map_lock(struct map_ent **melp);
 +extern void map_unlock(struct map_ent **melp);
  
  /* various details can be requested */
  #define       GET_LEVEL       1
  #define GET_CACHE     16
  #define       GET_MISMATCH    32
  #define       GET_VERSION     64
 +#define       GET_DISKS       128
 +#define       GET_DEGRADED    256
 +#define       GET_SAFEMODE    512
  
  #define       GET_DEVS        1024 /* gets role, major, minor */
  #define       GET_OFFSET      2048
  /* If fd >= 0, get the array it is open on,
   * else use devnum. >=0 -> major9. <0.....
   */
 +extern int sysfs_open(int devnum, char *devname, char *attr);
 +extern void sysfs_init(struct mdinfo *mdi, int fd, int devnum);
  extern void sysfs_free(struct mdinfo *sra);
  extern struct mdinfo *sysfs_read(int fd, int devnum, unsigned long options);
 +extern int sysfs_attr_match(const char *attr, const char *str);
 +extern int sysfs_match_word(const char *word, char **list);
  extern int sysfs_set_str(struct mdinfo *sra, struct mdinfo *dev,
                         char *name, char *val);
  extern int sysfs_set_num(struct mdinfo *sra, struct mdinfo *dev,
                         char *name, unsigned long long val);
 +extern int sysfs_uevent(struct mdinfo *sra, char *event);
  extern int sysfs_get_ll(struct mdinfo *sra, struct mdinfo *dev,
                        char *name, unsigned long long *val);
 +extern int sysfs_set_safemode(struct mdinfo *sra, unsigned long ms);
 +extern int sysfs_set_array(struct mdinfo *info, int vers);
 +extern int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd);
 +extern int sysfs_disk_to_scsi_id(int fd, __u32 *id);
 +extern int sysfs_unique_holder(int devnum, long rdev);
 +extern int load_sys(char *path, char *buf);
  
  
  extern int save_stripes(int *source, unsigned long long *offsets,
@@@ -396,128 -326,28 +396,128 @@@ extern mapping_t r5layout[], pers[], mo
  
  extern char *map_dev(int major, int minor, int create);
  
 +struct active_array;
 +struct metadata_update;
  
 +/* A superswitch provides entry point the a metadata handler.
 + *
 + * The super_switch primarily operates on some "metadata" that
 + * is accessed via the 'supertype'.
 + * This metadata has one of three possible sources.
 + * 1/ It is read from a single device.  In this case it may not completely
 + *    describe the array or arrays as some information might be on other
 + *    devices.
 + * 2/ It is read from all devices in a container.  In this case all
 + *    information is present.
 + * 3/ It is created by ->init_super / ->add_to_super.  In this case it will
 + *    be complete once enough ->add_to_super calls have completed.
 + *
 + * When creating an array inside a container, the metadata will be
 + * formed by a combination of 2 and 3.  The metadata or the array is read,
 + * then new information is added.
 + *
 + * The metadata must sometimes have a concept of a 'current' array
 + * and a 'current' device.
 + * The 'current' array is set by init_super to be the newly created array,
 + * or is set by super_by_fd when it finds it is looking at an array inside
 + * a container.
 + *
 + * The 'current' device is either the device that the metadata was read from
 + * in case 1, or the last device added by add_to_super in case 3.
 + * Case 2 does not identify a 'current' device.
 + */
  extern struct superswitch {
 +
 +      /* Used to report details of metadata read from a component
 +       * device. ->load_super has been called.
 +       */
        void (*examine_super)(struct supertype *st, char *homehost);
        void (*brief_examine_super)(struct supertype *st);
        void (*export_examine_super)(struct supertype *st);
 +
 +      /* Used to report details of an active array.
 +       * ->load_super was possibly given a 'component' string.
 +       */
        void (*detail_super)(struct supertype *st, char *homehost);
        void (*brief_detail_super)(struct supertype *st);
        void (*export_detail_super)(struct supertype *st);
 +
 +      /* Optional: platform hardware / firmware details */
 +      int (*detail_platform)(int verbose, int enumerate_only);
 +
 +      /* Used:
 +       *   to get uuid to storing in bitmap metadata
 +       *   and 'reshape' backup-data metadata
 +       *   To see if a device is being re-added to an array it was part of.
 +       */
        void (*uuid_from_super)(struct supertype *st, int uuid[4]);
 +
 +      /* Extract generic details from metadata.  This could be details about
 +       * the container, or about an individual array within the container.
 +       * The determination is made either by:
 +       *   load_super being given a 'component' string.
 +       *   validate_geometry determining what to create.
 +       * The info includes both array information and device information.
 +       * The particular device should be:
 +       *   The last device added by add_to_super
 +       *   The device the metadata was loaded from by load_super
 +       */
        void (*getinfo_super)(struct supertype *st, struct mdinfo *info);
 +
 +      /* Check if the given metadata is flagged as belonging to "this"
 +       * host.  0 for 'no', 1 for 'yes', -1 for "Don't record homehost"
 +       */
        int (*match_home)(struct supertype *st, char *homehost);
 +
 +      /* Make one of several generic modifications to metadata
 +       * prior to assembly (or other times).
 +       *   sparc2.2  - first bug in early 0.90 metadata
 +       *   super-minor - change name of 0.90 metadata
 +       *   summaries - 'correct' any redundant data
 +       *   resync - mark array as dirty to trigger a resync.
 +       *   uuid - set new uuid - only 0.90 or 1.x
 +       *   name - change the name of the array (where supported)
 +       *   homehost - change which host this array is tied to.
 +       *   devicesize - If metadata is at start of device, change recorded
 +       *               device size to match actual device size
 +       *   byteorder - swap bytes for 0.90 metadata
 +       *
 +       *   force-one  - mark that device as uptodate, not old or failed.
 +       *   force-array - mark array as clean if it would not otherwise
 +       *               assemble
 +       *   assemble   - not sure how this is different from force-one...
 +       *   linear-grow-new - add a new device to a linear array, but don't
 +       *                   change the size: so superblock still matches
 +       *   linear-grow-update - now change the size of the array.
 +       */
        int (*update_super)(struct supertype *st, struct mdinfo *info,
                            char *update,
                            char *devname, int verbose,
                            int uuid_set, char *homehost);
 +
 +      /* Create new metadata for new array as described.  This could
 +       * be a new container, or an array in a pre-existing container.
 +       * Also used to zero metadata prior to writing it to invalidate old
 +       * metadata.
 +       */
        int (*init_super)(struct supertype *st, mdu_array_info_t *info,
                          unsigned long long size, char *name,
                          char *homehost, int *uuid);
 -      void (*add_to_super)(struct supertype *st, mdu_disk_info_t *dinfo);
 +
 +      /* update the metadata to include new device, either at create or
 +       * when hot-adding a spare.
 +       */
 +      int (*add_to_super)(struct supertype *st, mdu_disk_info_t *dinfo,
 +                           int fd, char *devname);
 +
 +      /* Write metadata to one device when fixing problems or adding
 +       * a new device.
 +       */
        int (*store_super)(struct supertype *st, int fd);
 -      int (*write_init_super)(struct supertype *st, mdu_disk_info_t *dinfo,
 -                              char *devname);
 +
 +      /*  Write all metadata for this array.
 +       */
 +      int (*write_init_super)(struct supertype *st);
        int (*compare_super)(struct supertype *st, struct supertype *tst);
        int (*load_super)(struct supertype *st, int fd, char *devname);
        struct supertype * (*match_metadata_desc)(char *arg);
        void (*locate_bitmap)(struct supertype *st, int fd);
        int (*write_bitmap)(struct supertype *st, int fd);
        void (*free_super)(struct supertype *st);
 -      int major;
 +
 +      /* validate_geometry is called with an st returned by
 +       * match_metadata_desc.
 +       * It should check that the geometry described in compatible with
 +       * the metadata type.  It will be called repeatedly as devices
 +       * added to validate changing size and new devices.  If there are
 +       * inter-device dependencies, it should record sufficient details
 +       * so these can be validated.
 +       * Both 'size' and '*freesize' are in sectors.  chunk is bytes.
 +       */
 +      int (*validate_geometry)(struct supertype *st, int level, int layout,
 +                               int raiddisks,
 +                               int chunk, unsigned long long size,
 +                               char *subdev, unsigned long long *freesize,
 +                               int verbose);
 +
 +      struct mdinfo *(*container_content)(struct supertype *st);
 +      /* Allow a metadata handler to override mdadm's default layouts */
 +      int (*default_layout)(int level); /* optional */
 +
 +/* for mdmon */
 +      int (*open_new)(struct supertype *c, struct active_array *a,
 +                      char *inst);
 +
 +      /* Tell the metadata handler the current state of the array.
 +       * This covers whether it is known to be consistent (no pending writes)
 +       * and how far along a resync is known to have progressed
 +       * (in a->resync_start).
 +       * resync status is really irrelevant if the array is not consistent,
 +       * but some metadata (DDF!) have a place to record the distinction.
 +       * If 'consistent' is '2', then the array can mark it dirty if a 
 +       * resync/recovery/whatever is required, or leave it clean if not.
 +       * Return value is 0 dirty (not consistent) and 1 if clean.
 +       * it is only really important if consistent is passed in as '2'.
 +       */
 +      int (*set_array_state)(struct active_array *a, int consistent);
 +
 +      /* When the state of a device might have changed, we call set_disk to
 +       * tell the metadata what the current state is.
 +       * Typically this happens on spare->in_sync and (spare|in_sync)->faulty
 +       * transitions.
 +       * set_disk might be called when the state of the particular disk has
 +       * not in fact changed.
 +       */
 +      void (*set_disk)(struct active_array *a, int n, int state);
 +      void (*sync_metadata)(struct supertype *st);
 +      void (*process_update)(struct supertype *st,
 +                             struct metadata_update *update);
 +      void (*prepare_update)(struct supertype *st,
 +                             struct metadata_update *update);
 +
 +      /* activate_spare will check if the array is degraded and, if it
 +       * is, try to find some spare space in the container.
 +       * On success, it add appropriate updates (For process_update) to
 +       * to the 'updates' list and returns a list of 'mdinfo' identifying
 +       * the device, or devices as there might be multiple missing
 +       * devices and multiple spares available.
 +       */
 +      struct mdinfo *(*activate_spare)(struct active_array *a,
 +                                       struct metadata_update **updates);
 +
        int swapuuid; /* true if uuid is bigending rather than hostendian */
 -} super0, super1, *superlist[];
 +      int external;
 +      const char *name; /* canonical metadata name */
 +} super0, super1, super_ddf, *superlist[];
 +
 +extern struct superswitch super_imsm;
  
 +struct metadata_update {
 +      int     len;
 +      char    *buf;
 +      void    *space; /* allocated space that monitor will use */
 +      struct metadata_update *next;
 +};
 +
 +/* A supertype holds a particular collection of metadata.
 + * It identifies the metadata type by the superswitch, and the particular
 + * sub-version of that metadata type.
 + * metadata read in or created is stored in 'sb' and 'info'.
 + * There are also fields used by mdmon to track containers.
 + *
 + * A supertype may refer to:
 + *   Just an array, possibly in a container
 + *   A container, not identifying any particular array
 + *   Info read from just one device, not yet fully describing the array/container.
 + *
 + *
 + * A supertype is created by:
 + *   super_by_fd
 + *   guess_super
 + *   dup_super
 + */
  struct supertype {
        struct superswitch *ss;
        int minor_version;
        int max_devs;
 +      int container_dev;    /* devnum of container */
 +      char subarray[32];      /* name of array inside container */
        void *sb;
 +      void *info;
 +      int loaded_container;   /* Set if load_super found a container,
 +                               * not just one device */
 +
 +      struct metadata_update *updates;
 +      struct metadata_update **update_tail;
 +
 +      /* extra stuff used by mdmon */
 +      struct active_array *arrays;
 +      int sock; /* listen to external programs */
 +      int devnum;
 +      char *devname; /* e.g. md0.  This appears in metadata_verison:
 +                      *  external:/md0/12
 +                      */
 +      int devcnt;
 +
 +      struct mdinfo *devs;
 +
  };
  
  extern struct supertype *super_by_fd(int fd);
@@@ -653,7 -375,6 +653,7 @@@ extern struct supertype *dup_super(stru
  extern int get_dev_size(int fd, char *dname, unsigned long long *sizep);
  extern void get_one_disk(int mdfd, mdu_array_info_t *ainf,
                         mdu_disk_info_t *disk);
 +void wait_for(char *dev);
  
  #if __GNUC__ < 3
  struct stat64;
  #define HAVE_NFTW  we assume
  #define HAVE_FTW
  
- #ifdef UCLIBC
+ #ifdef __UCLIBC__
  # include <features.h>
+ # ifndef __UCLIBC_HAS_LFS__
+ #  define lseek64 lseek
+ # endif
  # ifndef  __UCLIBC_HAS_FTW__
  #  undef HAVE_FTW
  #  undef HAVE_NFTW
@@@ -709,28 -433,27 +712,28 @@@ extern int Grow_restart(struct supertyp
                        int *fdlist, int cnt, char *backup_file);
  
  
 -extern int Assemble(struct supertype *st, char *mddev, int mdfd,
 +extern int Assemble(struct supertype *st, char *mddev,
                    mddev_ident_t ident,
                    mddev_dev_t devlist, char *backup_file,
                    int readonly, int runstop,
                    char *update, char *homehost,
                    int verbose, int force);
  
 -extern int Build(char *mddev, int mdfd, int chunk, int level, int layout,
 -               int raiddisks,
 -               mddev_dev_t devlist, int assume_clean,
 -               char *bitmap_file, int bitmap_chunk, int write_behind, int delay, int verbose);
 +extern int Build(char *mddev, int chunk, int level, int layout,
 +               int raiddisks, mddev_dev_t devlist, int assume_clean,
 +               char *bitmap_file, int bitmap_chunk, int write_behind,
 +               int delay, int verbose, int autof);
  
  
 -extern int Create(struct supertype *st, char *mddev, int mdfd,
 +extern int Create(struct supertype *st, char *mddev,
                  int chunk, int level, int layout, unsigned long long size, int raiddisks, int sparedisks,
                  char *name, char *homehost, int *uuid,
                  int subdevs, mddev_dev_t devlist,
                  int runstop, int verbose, int force, int assume_clean,
 -                char *bitmap_file, int bitmap_chunk, int write_behind, int delay);
 +                char *bitmap_file, int bitmap_chunk, int write_behind, int delay, int autof);
  
  extern int Detail(char *dev, int brief, int export, int test, char *homehost);
 +extern int Detail_Platform(struct superswitch *ss, int scan, int verbose);
  extern int Query(char *dev);
  extern int Examine(mddev_dev_t devlist, int brief, int export, int scan,
                   int SparcAdjust, struct supertype *forcest, char *homehost);
@@@ -739,15 -462,11 +742,15 @@@ extern int Monitor(mddev_dev_t devlist
                   int period, int daemonise, int scan, int oneshot,
                   int dosyslog, int test, char *pidfile);
  
 -extern int Kill(char *dev, int force, int quiet);
 +extern int Kill(char *dev, int force, int quiet, int noexcl);
  extern int Wait(char *dev);
 +extern int WaitClean(char *dev, int verbose);
  
  extern int Incremental(char *devname, int verbose, int runstop,
                       struct supertype *st, char *homehost, int autof);
 +extern int Incremental_container(struct supertype *st, char *devname,
 +                               int verbose, int runstop, int autof,
 +                               int trustworthy);
  extern void RebuildMap(void);
  extern int IncrementalScan(int verbose);
  
@@@ -769,10 -488,7 +772,10 @@@ extern int check_raid(int fd, char *nam
  
  extern int get_mdp_major(void);
  extern int dev_open(char *dev, int flags);
 +extern int open_dev(int devnum);
 +extern int open_dev_excl(int devnum);
  extern int is_standard(char *dev, int *nump);
 +extern int same_dev(char *one, char *two);
  
  extern int parse_auto(char *str, char *msg, int config);
  extern mddev_ident_t conf_get_ident(char *dev);
@@@ -789,28 -505,15 +792,28 @@@ extern char *conf_word(FILE *file, int 
  extern void free_line(char *line);
  extern int match_oneof(char *devices, char *devname);
  extern void uuid_from_super(int uuid[4], mdp_super_t *super);
 +extern const int uuid_match_any[4];
  extern int same_uuid(int a[4], int b[4], int swapuuid);
  extern void copy_uuid(void *a, int b[4], int swapuuid);
 +extern char *fname_from_uuid(struct supertype *st,
 +                           struct mdinfo *info, char *buf, char sep);
  extern unsigned long calc_csum(void *super, int bytes);
  extern int enough(int level, int raid_disks, int layout, int clean,
                   char *avail, int avail_disks);
  extern int ask(char *mesg);
  extern unsigned long long get_component_size(int fd);
  extern void remove_partitions(int fd);
 -
 +extern unsigned long long calc_array_size(int level, int raid_disks, int layout,
 +                                 int chunksize, unsigned long long devsize);
 +extern int flush_metadata_updates(struct supertype *st);
 +extern void append_metadata_update(struct supertype *st, void *buf, int len);
 +extern int assemble_container_content(struct supertype *st, int mdfd,
 +                                    struct mdinfo *content, int runstop,
 +                                    char *chosen_name, int verbose);
 +
 +extern int add_disk(int mdfd, struct supertype *st,
 +                  struct mdinfo *sra, struct mdinfo *info);
 +extern int set_array_info(int mdfd, struct supertype *st, struct mdinfo *info);
  
  extern char *human_size(long long bytes);
  extern char *human_size_brief(long long bytes);
@@@ -824,71 -527,17 +827,71 @@@ extern char *get_md_name(int dev)
  
  extern char DefaultConfFile[];
  
 -extern int open_mddev(char *dev, int autof);
 -extern int open_mddev_devnum(char *devname, int devnum, char *name,
 -                           char *chosen_name, int parts);
 +extern int create_mddev(char *dev, char *name, int autof, int trustworthy,
 +                      char *chosen);
 +/* values for 'trustworthy' */
 +#define       LOCAL   1
 +#define       FOREIGN 2
 +#define       METADATA 3
 +extern int open_mddev(char *dev, int report_errors);
 +extern int open_container(int fd);
 +
 +extern int mdmon_running(int devnum);
 +extern int signal_mdmon(int devnum);
 +extern int check_env(char *name);
 +extern int start_mdmon(int devnum);
 +
 +extern char *devnum2devname(int num);
 +extern int devname2devnum(char *name);
 +extern int stat2devnum(struct stat *st);
 +extern int fd2devnum(int fd);
 +
 +static inline int dev2major(int d)
 +{
 +      if (d >= 0)
 +              return MD_MAJOR;
 +      else
 +              return get_mdp_major();
 +}
 +
 +static inline int dev2minor(int d)
 +{
 +      if (d >= 0)
 +              return d;
 +      return (-1-d) << MdpMinorShift;
 +}
 +
 +static inline int ROUND_UP(int a, int base)
 +{
 +      return ((a+base-1)/base)*base;
 +}
  
 +static inline int is_subarray(char *vers)
 +{
 +      /* The version string for a 'subarray' (an array in a container)
 +       * is 
 +       *    /containername/componentname    for normal read-write arrays
 +       *    -containername/componentname    for read-only arrays.
 +       * containername is e.g. md0, md_d1
 +       * componentname is dependant on the metadata. e.g. '1' 'S1' ...
 +       */
 +      return (*vers == '/' || *vers == '-');
 +}
 +
 +#ifdef DEBUG
 +#define dprintf(fmt, arg...) \
 +      fprintf(stderr, fmt, ##arg)
 +#else
 +#define dprintf(fmt, arg...) \
 +        ({ if (0) fprintf(stderr, fmt, ##arg); 0; })
 +#endif
  #include <assert.h>
  #include <stdarg.h>
  static inline int xasprintf(char **strp, const char *fmt, ...) {
        va_list ap;
        int ret;
        va_start(ap, fmt);
-       ret = asprintf(strp, fmt, ap);
+       ret = vasprintf(strp, fmt, ap);
        va_end(ap);
        assert(ret >= 0);
        return ret;
  #define       LEVEL_LINEAR            (-1)
  #define       LEVEL_FAULTY            (-5)
  
 +/* kernel module doesn't know about these */
 +#define LEVEL_CONTAINER               (-100)
 +#define       LEVEL_UNSUPPORTED       (-200)
 +
  
  /* faulty stuff */