mdadm: Remove busybox mdadm re-make
authorSebastian Pipping <sebastian@pipping.org>
Mon, 17 Jan 2011 15:24:54 +0000 (16:24 +0100)
committerSebastian Pipping <sebastian@pipping.org>
Mon, 17 Jan 2011 15:24:54 +0000 (16:24 +0100)
patches/busybox/1.18.1/1.18.1-mdadm.diff [deleted file]
patches/busybox/1.18.1/README
patches/busybox/1.7.4/1.7.4-mdadm.diff [deleted file]
patches/busybox/1.7.4/README

diff --git a/patches/busybox/1.18.1/1.18.1-mdadm.diff b/patches/busybox/1.18.1/1.18.1-mdadm.diff
deleted file mode 100644 (file)
index 0f3107e..0000000
+++ /dev/null
@@ -1,5874 +0,0 @@
-Based on:
-
-> Forward-port the mdadm tool from the Gentoo Busybox-1.1.3.
-> Should handle all types of metadata 0.90, 1.0, 1.1, 1.2.
-> If /etc/mdadm.conf does not exist in the initrd, it is created first, by
-> scanning devices, and then it is used.
-
---- a/Config.in        2010-12-21 06:31:04.000000000 +0200
-+++ mdadm/Config.in    2011-01-12 21:33:01.000000000 +0200
-@@ -749,6 +749,7 @@ source findutils/Config.in
- source init/Config.in
- source loginutils/Config.in
- source e2fsprogs/Config.in
-+source mdadm/Config.in
- source modutils/Config.in
- source util-linux/Config.in
- source miscutils/Config.in
---- a/include/applets.src.h    2010-12-21 06:31:04.000000000 +0200
-+++ mdadm/include/applets.src.h        2011-01-12 21:33:01.000000000 +0200
-@@ -206,6 +206,7 @@ IF_KILLALL5(APPLET_ODDNAME(killall5, kil
- IF_KLOGD(APPLET(klogd, _BB_DIR_SBIN, _BB_SUID_DROP))
- IF_LAST(APPLET(last, _BB_DIR_USR_BIN, _BB_SUID_DROP))
- IF_LENGTH(APPLET_NOFORK(length, length, _BB_DIR_USR_BIN, _BB_SUID_DROP, length))
-+IF_MDADM(APPLET(mdadm, _BB_DIR_SBIN, _BB_SUID_DROP))
- IF_LESS(APPLET(less, _BB_DIR_USR_BIN, _BB_SUID_DROP))
- IF_SETARCH(APPLET_ODDNAME(linux32, setarch, _BB_DIR_BIN, _BB_SUID_DROP, linux32))
- IF_SETARCH(APPLET_ODDNAME(linux64, setarch, _BB_DIR_BIN, _BB_SUID_DROP, linux64))
---- a/include/usage.src.h      2010-12-21 06:29:45.000000000 +0200
-+++ mdadm/include/usage.src.h  2011-01-12 21:33:01.000000000 +0200
-@@ -2404,6 +2404,11 @@ INSERT
-      "\n      -w      Warn about improperly formatted checksum lines" \
-       )
-+#define mdadm_trivial_usage \
-+      ""
-+#define mdadm_full_usage \
-+      "Assemble or Examine the mdadm arrays."
-+
- #define mdev_trivial_usage \
-        "[-s]"
- #define mdev_full_usage "\n\n" \
---- a/Makefile 2010-12-21 06:31:43.000000000 +0200
-+++ mdadm/Makefile     2011-01-12 21:33:01.000000000 +0200
-@@ -478,6 +478,7 @@ libs-y             := \
-               loginutils/ \
-               mailutils/ \
-               miscutils/ \
-+              mdadm/ \
-               modutils/ \
-               networking/ \
-               networking/libiproute/ \
---- a/mdadm/bitmap.h   1970-01-01 03:00:00.000000000 +0300
-+++ mdadm/mdadm/bitmap.h       2011-01-12 21:33:01.000000000 +0200
-@@ -0,0 +1,287 @@
-+/*
-+ * bitmap.h: Copyright (C) Peter T. Breuer (ptb@ot.uc3m.es) 2003
-+ *
-+ * additions: Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc.
-+ */
-+#ifndef BITMAP_H
-+#define BITMAP_H 1
-+
-+#define BITMAP_MAJOR_LO 3
-+/* version 4 insists the bitmap is in little-endian order
-+ * with version 3, it is host-endian which is non-portable
-+ */
-+#define BITMAP_MAJOR_HI 4
-+#define       BITMAP_MAJOR_HOSTENDIAN 3
-+
-+#define BITMAP_MINOR 39
-+
-+/*
-+ * in-memory bitmap:
-+ *
-+ * Use 16 bit block counters to track pending writes to each "chunk".
-+ * The 2 high order bits are special-purpose, the first is a flag indicating
-+ * whether a resync is needed.  The second is a flag indicating whether a
-+ * resync is active.
-+ * This means that the counter is actually 14 bits:
-+ *
-+ * +--------+--------+------------------------------------------------+
-+ * | resync | resync |               counter                          |
-+ * | needed | active |                                                |
-+ * |  (0-1) |  (0-1) |              (0-16383)                         |
-+ * +--------+--------+------------------------------------------------+
-+ *
-+ * The "resync needed" bit is set when:
-+ *    a '1' bit is read from storage at startup.
-+ *    a write request fails on some drives
-+ *    a resync is aborted on a chunk with 'resync active' set
-+ * It is cleared (and resync-active set) when a resync starts across all drives
-+ * of the chunk.
-+ *
-+ *
-+ * The "resync active" bit is set when:
-+ *    a resync is started on all drives, and resync_needed is set.
-+ *       resync_needed will be cleared (as long as resync_active wasn't already set).
-+ * It is cleared when a resync completes.
-+ *
-+ * The counter counts pending write requests, plus the on-disk bit.
-+ * When the counter is '1' and the resync bits are clear, the on-disk
-+ * bit can be cleared aswell, thus setting the counter to 0.
-+ * When we set a bit, or in the counter (to start a write), if the fields is
-+ * 0, we first set the disk bit and set the counter to 1.
-+ *
-+ * If the counter is 0, the on-disk bit is clear and the stipe is clean
-+ * Anything that dirties the stipe pushes the counter to 2 (at least)
-+ * and sets the on-disk bit (lazily).
-+ * If a periodic sweep find the counter at 2, it is decremented to 1.
-+ * If the sweep find the counter at 1, the on-disk bit is cleared and the
-+ * counter goes to zero.
-+ *
-+ * Also, we'll hijack the "map" pointer itself and use it as two 16 bit block
-+ * counters as a fallback when "page" memory cannot be allocated:
-+ *
-+ * Normal case (page memory allocated):
-+ *
-+ *     page pointer (32-bit)
-+ *
-+ *     [ ] ------+
-+ *               |
-+ *               +-------> [   ][   ]..[   ] (4096 byte page == 2048 counters)
-+ *                          c1   c2    c2048
-+ *
-+ * Hijacked case (page memory allocation failed):
-+ *
-+ *     hijacked page pointer (32-bit)
-+ *
-+ *     [                ][              ] (no page memory allocated)
-+ *      counter #1 (16-bit) counter #2 (16-bit)
-+ *
-+ */
-+
-+#ifdef __KERNEL__
-+
-+#define PAGE_BITS (PAGE_SIZE << 3)
-+#define PAGE_BIT_SHIFT (PAGE_SHIFT + 3)
-+
-+typedef __u16 bitmap_counter_t;
-+#define COUNTER_BITS 16
-+#define COUNTER_BIT_SHIFT 4
-+#define COUNTER_BYTE_RATIO (COUNTER_BITS / 8)
-+#define COUNTER_BYTE_SHIFT (COUNTER_BIT_SHIFT - 3)
-+
-+#define NEEDED_MASK ((bitmap_counter_t) (1 << (COUNTER_BITS - 1)))
-+#define RESYNC_MASK ((bitmap_counter_t) (1 << (COUNTER_BITS - 2)))
-+#define COUNTER_MAX ((bitmap_counter_t) RESYNC_MASK - 1)
-+#define NEEDED(x) (((bitmap_counter_t) x) & NEEDED_MASK)
-+#define RESYNC(x) (((bitmap_counter_t) x) & RESYNC_MASK)
-+#define COUNTER(x) (((bitmap_counter_t) x) & COUNTER_MAX)
-+
-+/* how many counters per page? */
-+#define PAGE_COUNTER_RATIO (PAGE_BITS / COUNTER_BITS)
-+/* same, except a shift value for more efficient bitops */
-+#define PAGE_COUNTER_SHIFT (PAGE_BIT_SHIFT - COUNTER_BIT_SHIFT)
-+/* same, except a mask value for more efficient bitops */
-+#define PAGE_COUNTER_MASK  (PAGE_COUNTER_RATIO - 1)
-+
-+#define BITMAP_BLOCK_SIZE 512
-+#define BITMAP_BLOCK_SHIFT 9
-+
-+/* how many blocks per chunk? (this is variable) */
-+#define CHUNK_BLOCK_RATIO(bitmap) ((bitmap)->chunksize >> BITMAP_BLOCK_SHIFT)
-+#define CHUNK_BLOCK_SHIFT(bitmap) ((bitmap)->chunkshift - BITMAP_BLOCK_SHIFT)
-+#define CHUNK_BLOCK_MASK(bitmap) (CHUNK_BLOCK_RATIO(bitmap) - 1)
-+
-+/* when hijacked, the counters and bits represent even larger "chunks" */
-+/* there will be 1024 chunks represented by each counter in the page pointers */
-+#define PAGEPTR_BLOCK_RATIO(bitmap) \
-+                      (CHUNK_BLOCK_RATIO(bitmap) << PAGE_COUNTER_SHIFT >> 1)
-+#define PAGEPTR_BLOCK_SHIFT(bitmap) \
-+                      (CHUNK_BLOCK_SHIFT(bitmap) + PAGE_COUNTER_SHIFT - 1)
-+#define PAGEPTR_BLOCK_MASK(bitmap) (PAGEPTR_BLOCK_RATIO(bitmap) - 1)
-+
-+/*
-+ * on-disk bitmap:
-+ *
-+ * Use one bit per "chunk" (block set). We do the disk I/O on the bitmap
-+ * file a page at a time. There's a superblock at the start of the file.
-+ */
-+
-+/* map chunks (bits) to file pages - offset by the size of the superblock */
-+#define CHUNK_BIT_OFFSET(chunk) ((chunk) + (sizeof(bitmap_super_t) << 3))
-+
-+#endif
-+
-+/*
-+ * bitmap structures:
-+ */
-+
-+#define BITMAP_MAGIC 0x6d746962
-+
-+/* use these for bitmap->flags and bitmap->sb->state bit-fields */
-+enum bitmap_state {
-+      BITMAP_ACTIVE = 0x001, /* the bitmap is in use */
-+      BITMAP_STALE  = 0x002  /* the bitmap file is out of date or had -EIO */
-+};
-+
-+/* the superblock at the front of the bitmap file -- little endian */
-+typedef struct bitmap_super_s {
-+      __u32 magic;        /*  0  BITMAP_MAGIC */
-+      __u32 version;      /*  4  the bitmap major for now, could change... */
-+      __u8  uuid[16];     /*  8  128 bit uuid - must match md device uuid */
-+      __u64 events;       /* 24  event counter for the bitmap (1)*/
-+      __u64 events_cleared;/*32  event counter when last bit cleared (2) */
-+      __u64 sync_size;    /* 40  the size of the md device's sync range(3) */
-+      __u32 state;        /* 48  bitmap state information */
-+      __u32 chunksize;    /* 52  the bitmap chunk size in bytes */
-+      __u32 daemon_sleep; /* 56  seconds between disk flushes */
-+      __u32 write_behind; /* 60  number of outstanding write-behind writes */
-+
-+      __u8  pad[256 - 64]; /* set to zero */
-+} bitmap_super_t;
-+
-+/* notes:
-+ * (1) This event counter is updated before the eventcounter in the md superblock
-+ *    When a bitmap is loaded, it is only accepted if this event counter is equal
-+ *    to, or one greater than, the event counter in the superblock.
-+ * (2) This event counter is updated when the other one is *if*and*only*if* the 
-+ *    array is not degraded.  As bits are not cleared when the array is degraded,
-+ *    this represents the last time that any bits were cleared.
-+ *    If a device is being added that has an event count with this value or
-+ *    higher, it is accepted as conforming to the bitmap.
-+ * (3)This is the number of sectors represented by the bitmap, and is the range that
-+ *    resync happens across.  For raid1 and raid5/6 it is the size of individual
-+ *    devices.  For raid10 it is the size of the array.
-+ */
-+
-+#ifdef __KERNEL__
-+
-+/* the in-memory bitmap is represented by bitmap_pages */
-+struct bitmap_page {
-+      /*
-+       * map points to the actual memory page
-+       */
-+      char *map;
-+      /*
-+       * in emergencies (when map cannot be alloced), hijack the map
-+       * pointer and use it as two counters itself
-+       */
-+      unsigned int hijacked;
-+      /*
-+       * count of dirty bits on the page
-+       */ 
-+      int count;
-+};
-+
-+/* keep track of bitmap file pages that have pending writes on them */
-+struct page_list {
-+      struct list_head list;
-+      struct page *page;
-+};
-+
-+/* the main bitmap structure - one per mddev */
-+struct bitmap {
-+      struct bitmap_page *bp;
-+      unsigned long pages; /* total number of pages in the bitmap */
-+      unsigned long missing_pages; /* number of pages not yet allocated */
-+
-+      mddev_t *mddev; /* the md device that the bitmap is for */
-+
-+      int counter_bits; /* how many bits per block counter */
-+
-+      /* bitmap chunksize -- how much data does each bit represent? */
-+      unsigned long chunksize;
-+      unsigned long chunkshift; /* chunksize = 2^chunkshift (for bitops) */
-+      unsigned long chunks; /* total number of data chunks for the array */
-+
-+      /* We hold a count on the chunk currently being synced, and drop
-+       * it when the last block is started.  If the resync is aborted
-+       * midway, we need to be able to drop that count, so we remember
-+       * the counted chunk..
-+       */
-+      unsigned long syncchunk;
-+
-+      __u64   events_cleared;
-+
-+      /* bitmap spinlock */
-+      spinlock_t lock;
-+
-+      struct file *file; /* backing disk file */
-+      struct page *sb_page; /* cached copy of the bitmap file superblock */
-+      struct page **filemap; /* list of cache pages for the file */
-+      unsigned long *filemap_attr; /* attributes associated w/ filemap pages */
-+      unsigned long file_pages; /* number of pages in the file */
-+
-+      unsigned long flags;
-+
-+      /*
-+       * the bitmap daemon - periodically wakes up and sweeps the bitmap
-+       * file, cleaning up bits and flushing out pages to disk as necessary
-+       */
-+      mdk_thread_t *daemon;
-+      unsigned long daemon_sleep; /* how many seconds between updates? */
-+
-+      /*
-+       * bitmap write daemon - this daemon performs writes to the bitmap file
-+       * this thread is only needed because of a limitation in ext3 (jbd)
-+       * that does not allow a task to have two journal transactions ongoing
-+       * simultaneously (even if the transactions are for two different
-+       * filesystems) -- in the case of bitmap, that would be the filesystem
-+       * that the bitmap file resides on and the filesystem that is mounted
-+       * on the md device -- see current->journal_info in jbd/transaction.c
-+       */
-+      mdk_thread_t *write_daemon;
-+      mdk_thread_t *writeback_daemon;
-+      spinlock_t write_lock;
-+      struct semaphore write_ready;
-+      struct semaphore write_done;
-+      unsigned long writes_pending;
-+      wait_queue_head_t write_wait;
-+      struct list_head write_pages;
-+      struct list_head complete_pages;
-+      mempool_t *write_pool;
-+};
-+
-+/* the bitmap API */
-+
-+/* these are used only by md/bitmap */
-+int  bitmap_create(mddev_t *mddev);
-+void bitmap_destroy(mddev_t *mddev);
-+int  bitmap_active(struct bitmap *bitmap);
-+
-+char *file_path(struct file *file, char *buf, int count);
-+void bitmap_print_sb(struct bitmap *bitmap);
-+int bitmap_update_sb(struct bitmap *bitmap);
-+
-+int  bitmap_setallbits(struct bitmap *bitmap);
-+
-+/* these are exported */
-+void bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors);
-+void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors,
-+                   int success);
-+int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks);
-+void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int aborted);
-+void bitmap_close_sync(struct bitmap *bitmap);
-+
-+int bitmap_unplug(struct bitmap *bitmap);
-+#endif
-+
-+#endif
-diff -pruN a/mdadm/config.c mdadm/mdadm/config.c
---- a/mdadm/config.c   1970-01-01 03:00:00.000000000 +0300
-+++ mdadm/mdadm/config.c       2011-01-12 21:33:01.000000000 +0200
-@@ -0,0 +1,824 @@
-+/*
-+ * mdadm - manage Linux "md" devices aka RAID arrays.
-+ *
-+ * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
-+ *
-+ *
-+ *    This program is free software; you can redistribute it and/or modify
-+ *    it under the terms of the GNU General Public License as published by
-+ *    the Free Software Foundation; either version 2 of the License, or
-+ *    (at your option) any later version.
-+ *
-+ *    This program is distributed in the hope that it will be useful,
-+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *    GNU General Public License for more details.
-+ *
-+ *    You should have received a copy of the GNU General Public License
-+ *    along with this program; if not, write to the Free Software
-+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ *
-+ *    Author: Neil Brown
-+ *    Email: <neilb@cse.unsw.edu.au>
-+ *    Paper: Neil Brown
-+ *           School of Computer Science and Engineering
-+ *           The University of New South Wales
-+ *           Sydney, 2052
-+ *           Australia
-+ */
-+
-+#include      "mdadm.h"
-+#include      "dlink.h"
-+#include      <sys/dir.h>
-+#include      <glob.h>
-+#include      <fnmatch.h>
-+#include      <ctype.h>
-+#include      <pwd.h>
-+#include      <grp.h>
-+
-+mapping_t r5layout[] = {
-+      { "left-asymmetric", 0},
-+      { "right-asymmetric", 1},
-+      { "left-symmetric", 2},
-+      { "right-symmetric", 3},
-+
-+      { "default", 2},
-+      { "la", 0},
-+      { "ra", 1},
-+      { "ls", 2},
-+      { "rs", 3},
-+      { NULL, 0}
-+};
-+
-+mapping_t pers[] = {
-+      { "linear", -1},
-+      { "raid0", 0},
-+      { "0", 0},
-+      { "stripe", 0},
-+      { "raid1", 1},
-+      { "1", 1},
-+      { "mirror", 1},
-+      { "raid4", 4},
-+      { "4", 4},
-+      { "raid5", 5},
-+      { "5", 5},
-+      { "multipath", -4},
-+      { "mp", -4},
-+      { "raid6", 6},
-+      { "6", 6},
-+      { "raid10", 10},
-+      { "10", 10},
-+      { "faulty", -5},
-+      { NULL, 0}
-+};
-+/*
-+ * Read the config file
-+ *
-+ * conf_get_uuids gets a list of devicename+uuid pairs
-+ * conf_get_devs gets device names after expanding wildcards
-+ *
-+ * Each keeps the returned list and frees it when asked to make
-+ * a new list.
-+ *
-+ * The format of the config file needs to be fairly extensible.
-+ * Now, arrays only have names and uuids and devices merely are.
-+ * But later arrays might want names, and devices might want superblock
-+ * versions, and who knows what else.
-+ * I like free format, abhore backslash line continuation, adore
-+ *   indentation for structure and am ok about # comments.
-+ *
-+ * So, each line that isn't blank or a #comment must either start
-+ *  with a key word, and not be indented, or must start with a
-+ *  non-key-word and must be indented.
-+ *
-+ * Keywords are DEVICE and ARRAY
-+ * DEV{ICE} introduces some devices that might contain raid components.
-+ * e.g.
-+ *   DEV style=0 /dev/sda* /dev/hd*
-+ *   DEV style=1 /dev/sd[b-f]*
-+ * ARR{AY} describes an array giving md device and attributes like uuid=whatever
-+ * e.g.
-+ *   ARRAY /dev/md0 uuid=whatever name=something
-+ * Spaces separate words on each line.  Quoting, with "" or '' protects them,
-+ * but may not wrap over lines
-+ *
-+ */
-+
-+#ifndef CONFFILE
-+#define CONFFILE "/etc/mdadm.conf"
-+#endif
-+#ifndef CONFFILE2
-+/* for Debian compatibility .... */
-+#define CONFFILE2 "/etc/mdadm/mdadm.conf"
-+#endif
-+char DefaultConfFile[] = CONFFILE;
-+char DefaultAltConfFile[] = CONFFILE2;
-+
-+enum linetype { Devices, Array, Mailaddr, Mailfrom, Program, CreateDev, Homehost, LTEnd };
-+char *keywords[] = {
-+      [Devices]  = "devices",
-+      [Array]    = "array",
-+      [Mailaddr] = "mailaddr",
-+      [Mailfrom] = "mailfrom",
-+      [Program]  = "program",
-+      [CreateDev]= "create",
-+      [Homehost] = "homehost",
-+      [LTEnd]    = NULL
-+};
-+
-+/*
-+ * match_keyword returns an index into the keywords array, or -1 for no match
-+ * case is ignored, and at least three characters must be given
-+ */
-+
-+int match_keyword(char *word)
-+{
-+      int len = strlen(word);
-+      int n;
-+    
-+      if (len < 3) return -1;
-+      for (n=0; keywords[n]; n++) {
-+              if (strncasecmp(word, keywords[n], len)==0)
-+                      return n;
-+      }
-+      return -1;
-+}
-+
-+/* conf_word gets one word from the conf file.
-+ * if "allow_key", then accept words at the start of a line,
-+ * otherwise stop when such a word is found.
-+ * We assume that the file pointer is at the end of a word, so the
-+ * next character is a space, or a newline.  If not, it is the start of a line.
-+ */
-+
-+char *conf_word(FILE *file, int allow_key)
-+{
-+      int wsize = 100;
-+      int len = 0;
-+      int c;
-+      int quote;
-+      int wordfound = 0;
-+      char *word = malloc(wsize);
-+
-+      if (!word) abort();
-+
-+      while (wordfound==0) {
-+              /* at the end of a word.. */
-+              c = getc(file);
-+              if (c == '#')
-+                      while (c != EOF && c != '\n')
-+                              c = getc(file);
-+              if (c == EOF) break;
-+              if (c == '\n') continue;
-+
-+              if (c != ' ' && c != '\t' && ! allow_key) {
-+                      ungetc(c, file);
-+                      break;
-+              }
-+              /* looks like it is safe to get a word here, if there is one */
-+              quote = 0;
-+              /* first, skip any spaces */
-+              while (c == ' ' || c == '\t')
-+                      c = getc(file);
-+              if (c != EOF && c != '\n' && c != '#') {
-+                      /* we really have a character of a word, so start saving it */
-+                      while (c != EOF && c != '\n' && (quote || (c!=' ' && c != '\t'))) {
-+                              wordfound = 1;
-+                              if (quote && c == quote) quote = 0;
-+                              else if (quote == 0 && (c == '\'' || c == '"'))
-+                                      quote = c;
-+                              else {
-+                                      if (len == wsize-1) {
-+                                              wsize += 100;
-+                                              word = realloc(word, wsize);
-+                                              if (!word) abort();
-+                                      }
-+                                      word[len++] = c;
-+                              }
-+                              c = getc(file);
-+                      }
-+              }
-+              if (c != EOF) ungetc(c, file);
-+      }
-+      word[len] = 0;
-+/*    printf("word is <%s>\n", word); */
-+      if (!wordfound) {
-+              free(word);
-+              word = NULL;
-+      }
-+      return word;
-+}
-+      
-+/*
-+ * conf_line reads one logical line from the conffile.
-+ * It skips comments and continues until it finds a line that starts
-+ * with a non blank/comment.  This character is pushed back for the next call
-+ * A doubly linked list of words is returned.
-+ * the first word will be a keyword.  Other words will have had quotes removed.
-+ */
-+
-+char *conf_line(FILE *file)
-+{
-+      char *w;
-+      char *list;
-+
-+      w = conf_word(file, 1);
-+      if (w == NULL) return NULL;
-+
-+      list = dl_strdup(w);
-+      free(w);
-+      dl_init(list);
-+
-+      while ((w = conf_word(file,0))){
-+              char *w2 = dl_strdup(w);
-+              free(w);
-+              dl_add(list, w2);
-+      }
-+/*    printf("got a line\n");*/
-+      return list;
-+}
-+
-+void free_line(char *line)
-+{
-+      char *w;
-+      for (w=dl_next(line); w != line; w=dl_next(line)) {
-+              dl_del(w);
-+              dl_free(w);
-+      }
-+      dl_free(line);
-+}
-+
-+
-+struct conf_dev {
-+    struct conf_dev *next;
-+    char *name;
-+} *cdevlist = NULL;
-+
-+mddev_dev_t load_partitions(void)
-+{
-+      FILE *f = fopen("/proc/partitions", "r");
-+      char buf[1024];
-+      mddev_dev_t rv = NULL;
-+      if (f == NULL) {
-+              fprintf(stderr, Name ": cannot open /proc/partitions\n");
-+              return NULL;
-+      }
-+      while (fgets(buf, 1024, f)) {
-+              int major, minor;
-+              char *name, *mp;
-+              mddev_dev_t d;
-+
-+              buf[1023] = '\0';
-+              if (buf[0] != ' ')
-+                      continue;
-+              major = strtoul(buf, &mp, 10);
-+              if (mp == buf || *mp != ' ') 
-+                      continue;
-+              minor = strtoul(mp, NULL, 10);
-+
-+              name = map_dev(major, minor, 1);
-+              if (!name)
-+                      continue;
-+              d = malloc(sizeof(*d));
-+              d->devname = strdup(name);
-+              d->next = rv;
-+              d->used = 0;
-+              rv = d;
-+      }
-+      fclose(f);
-+      return rv;
-+}
-+
-+struct createinfo createinfo = {
-+      .autof = 2, /* by default, create devices with standard names */
-+      .symlinks = 1,
-+#ifdef DEBIAN
-+      .gid = 6, /* disk */
-+      .mode = 0660,
-+#else
-+      .mode = 0600,
-+#endif
-+};
-+
-+int parse_auto(char *str, char *msg, int config)
-+{
-+      int autof;
-+      if (str == NULL || *str == 0)
-+              autof = 2;
-+      else if (strcasecmp(str,"no")==0)
-+              autof = 1;
-+      else if (strcasecmp(str,"yes")==0)
-+              autof = 2;
-+      else if (strcasecmp(str,"md")==0)
-+              autof = config?5:3;
-+      else {
-+              /* There might be digits, and maybe a hypen, at the end */
-+              char *e = str + strlen(str);
-+              int num = 4;
-+              int len;
-+              while (e > str && isdigit(e[-1]))
-+                      e--;
-+              if (*e) {
-+                      num = atoi(e);
-+                      if (num <= 0) num = 1;
-+              }
-+              if (e > str && e[-1] == '-')
-+                      e--;
-+              len = e - str;
-+              if ((len == 2 && strncasecmp(str,"md",2)==0)) {
-+                      autof = config ? 5 : 3;
-+              } else if ((len == 3 && strncasecmp(str,"yes",3)==0)) {
-+                      autof = 2;
-+              } else if ((len == 3 && strncasecmp(str,"mdp",3)==0)) {
-+                      autof = config ? 6 : 4;
-+              } else if ((len == 1 && strncasecmp(str,"p",1)==0) ||
-+                         (len >= 4 && strncasecmp(str,"part",4)==0)) {
-+                      autof = 6;
-+              } else {
-+                      fprintf(stderr, Name ": %s arg of \"%s\" unrecognised: use no,yes,md,mdp,part\n"
-+                              "        optionally followed by a number.\n",
-+                              msg, str);
-+                      exit(2);
-+              }
-+              autof |= num << 3;
-+      }
-+      return autof;
-+}
-+
-+static void createline(char *line)
-+{
-+      char *w;
-+      char *ep;
-+
-+      for (w=dl_next(line); w!=line; w=dl_next(w)) {
-+              if (strncasecmp(w, "auto=", 5) == 0)
-+                      createinfo.autof = parse_auto(w+5, "auto=", 1);
-+              else if (strncasecmp(w, "owner=", 6) == 0) {
-+                      if (w[6] == 0) {
-+                              fprintf(stderr, Name ": missing owner name\n");
-+                              continue;
-+                      }
-+                      createinfo.uid = strtoul(w+6, &ep, 10);
-+                      if (*ep != 0) {
-+                              struct passwd *pw;
-+                              /* must be a name */
-+                              pw = getpwnam(w+6);
-+                              if (pw)
-+                                      createinfo.uid = pw->pw_uid;
-+                              else
-+                                      fprintf(stderr, Name ": CREATE user %s not found\n", w+6);
-+                      }
-+              } else if (strncasecmp(w, "group=", 6) == 0) {
-+                      if (w[6] == 0) {
-+                              fprintf(stderr, Name ": missing group name\n");
-+                              continue;
-+                      }
-+                      createinfo.gid = strtoul(w+6, &ep, 10);
-+                      if (*ep != 0) {
-+                              struct group *gr;
-+                              /* must be a name */
-+                              gr = getgrnam(w+6);
-+                              if (gr)
-+                                      createinfo.gid = gr->gr_gid;
-+                              else
-+                                      fprintf(stderr, Name ": CREATE group %s not found\n", w+6);
-+                      }
-+              } else if (strncasecmp(w, "mode=", 5) == 0) {
-+                      if (w[5] == 0) {
-+                              fprintf(stderr, Name ": missing CREATE mode\n");
-+                              continue;
-+                      }
-+                      createinfo.mode = strtoul(w+5, &ep, 8);
-+                      if (*ep != 0) {
-+                              createinfo.mode = 0600;
-+                              fprintf(stderr, Name ": unrecognised CREATE mode %s\n",
-+                                      w+5);
-+                      }
-+              } else if (strncasecmp(w, "metadata=", 9) == 0) {
-+                      /* style of metadata to use by default */
-+                      int i;
-+                      for (i=0; superlist[i] && !createinfo.supertype; i++)
-+                              createinfo.supertype =
-+                                      superlist[i]->match_metadata_desc(w+9);
-+                      if (!createinfo.supertype)
-+                              fprintf(stderr, Name ": metadata format %s unknown, ignoring\n",
-+                                      w+9);
-+              } else if (strncasecmp(w, "symlinks=yes", 12) == 0)
-+                      createinfo.symlinks = 1;
-+              else if  (strncasecmp(w, "symlinks=no", 11) == 0)
-+                      createinfo.symlinks = 0;
-+              else {
-+                      fprintf(stderr, Name ": unrecognised word on CREATE line: %s\n",
-+                              w);
-+              }
-+      }
-+}
-+
-+void devline(char *line) 
-+{
-+      char *w;
-+      struct conf_dev *cd;
-+
-+      for (w=dl_next(line); w != line; w=dl_next(w)) {
-+              if (w[0] == '/' || strcasecmp(w, "partitions") == 0) {
-+                      cd = malloc(sizeof(*cd));
-+                      cd->name = strdup(w);
-+                      cd->next = cdevlist;
-+                      cdevlist = cd;
-+              } else {
-+                      fprintf(stderr, Name ": unreconised word on DEVICE line: %s\n",
-+                              w);
-+              }
-+      }
-+}
-+
-+mddev_ident_t mddevlist = NULL;
-+mddev_ident_t *mddevlp = &mddevlist;
-+
-+void arrayline(char *line)
-+{
-+      char *w;
-+
-+      struct mddev_ident_s mis;
-+      mddev_ident_t mi;
-+
-+      mis.uuid_set = 0;
-+      mis.super_minor = UnSet;
-+      mis.level = UnSet;
-+      mis.raid_disks = UnSet;
-+      mis.spare_disks = 0;
-+      mis.devices = NULL;
-+      mis.devname = NULL;
-+      mis.spare_group = NULL;
-+      mis.autof = 0;
-+      mis.next = NULL;
-+      mis.st = NULL;
-+      mis.bitmap_fd = -1;
-+      mis.bitmap_file = NULL;
-+      mis.name[0] = 0;
-+
-+      for (w=dl_next(line); w!=line; w=dl_next(w)) {
-+              if (w[0] == '/') {
-+                      if (mis.devname)
-+                              fprintf(stderr, Name ": only give one device per ARRAY line: %s and %s\n",
-+                                      mis.devname, w);
-+                      else mis.devname = w;
-+              } else if (strncasecmp(w, "uuid=", 5)==0 ) {
-+                      if (mis.uuid_set)
-+                              fprintf(stderr, Name ": only specify uuid once, %s ignored.\n",
-+                                      w);
-+                      else {
-+                              if (parse_uuid(w+5, mis.uuid))
-+                                      mis.uuid_set = 1;
-+                              else
-+                                      fprintf(stderr, Name ": bad uuid: %s\n", w);
-+                      }
-+              } else if (strncasecmp(w, "super-minor=", 12)==0 ) {
-+                      if (mis.super_minor != UnSet)
-+                              fprintf(stderr, Name ": only specify super-minor once, %s ignored.\n",
-+                                      w);
-+                      else {
-+                              char *endptr;
-+                              mis.super_minor= strtol(w+12, &endptr, 10);
-+                              if (w[12]==0 || endptr[0]!=0 || mis.super_minor < 0) {
-+                                      fprintf(stderr, Name ": invalid super-minor number: %s\n",
-+                                              w);
-+                                      mis.super_minor = UnSet;
-+                              }
-+                      }
-+              } else if (strncasecmp(w, "name=", 5)==0) {
-+                      if (mis.name[0])
-+                              fprintf(stderr, Name ": only specify name once, %s ignored.\n",
-+                                      w);
-+                      else if (strlen(w+5) > 32)
-+                              fprintf(stderr, Name ": name too long, ignoring %s\n", w);
-+                      else
-+                              strcpy(mis.name, w+5);
-+
-+              } else if (strncasecmp(w, "bitmap=", 7) == 0) {
-+                      if (mis.bitmap_file)
-+                              fprintf(stderr, Name ": only specify bitmap file once. %s ignored\n",
-+                                      w);
-+                      else
-+                              mis.bitmap_file = strdup(w+7);
-+
-+              } else if (strncasecmp(w, "devices=", 8 ) == 0 ) {
-+                      if (mis.devices)
-+                              fprintf(stderr, Name ": only specify devices once (use a comma separated list). %s ignored\n",
-+                                      w);
-+                      else
-+                              mis.devices = strdup(w+8);
-+              } else if (strncasecmp(w, "spare-group=", 12) == 0 ) {
-+                      if (mis.spare_group)
-+                              fprintf(stderr, Name ": only specify one spare group per array. %s ignored.\n",
-+                                      w);
-+                      else
-+                              mis.spare_group = strdup(w+12);
-+              } else if (strncasecmp(w, "level=", 6) == 0 ) {
-+                      /* this is mainly for compatability with --brief output */
-+                      mis.level = map_name(pers, w+6);
-+              } else if (strncasecmp(w, "disks=", 6) == 0 ) {
-+                      /* again, for compat */
-+                      mis.raid_disks = atoi(w+6);
-+              } else if (strncasecmp(w, "num-devices=", 12) == 0 ) {
-+                      /* again, for compat */
-+                      mis.raid_disks = atoi(w+12);
-+              } else if (strncasecmp(w, "spares=", 7) == 0 ) {
-+                      /* for warning if not all spares present */
-+                      mis.spare_disks = atoi(w+7);
-+              } else if (strncasecmp(w, "metadata=", 9) == 0) {
-+                      /* style of metadata on the devices. */
-+                      int i;
-+                      
-+                      for(i=0; superlist[i] && !mis.st; i++)
-+                              mis.st = superlist[i]->match_metadata_desc(w+9);
-+
-+                      if (!mis.st)
-+                              fprintf(stderr, Name ": metadata format %s unknown, ignored.\n", w+9);
-+              } else if (strncasecmp(w, "auto=", 5) == 0 ) {
-+                      /* whether to create device special files as needed */
-+                      mis.autof = parse_auto(w+5, "auto type", 0);
-+              } else {
-+                      fprintf(stderr, Name ": unrecognised word on ARRAY line: %s\n",
-+                              w);
-+              }
-+      }
-+      if (mis.devname == NULL)
-+              fprintf(stderr, Name ": ARRAY line with no device\n");
-+      else if (mis.uuid_set == 0 && mis.devices == NULL && mis.super_minor == UnSet && mis.name[0] == 0)
-+              fprintf(stderr, Name ": ARRAY line %s has no identity information.\n", mis.devname);
-+      else {
-+              mi = malloc(sizeof(*mi));
-+              *mi = mis;
-+              mi->devname = strdup(mis.devname);
-+              mi->next = NULL;
-+              *mddevlp = mi;
-+              mddevlp = &mi->next;
-+      }
-+}
-+
-+static char *alert_email = NULL;
-+void mailline(char *line)
-+{
-+      char *w;
-+
-+      for (w=dl_next(line); w != line ; w=dl_next(w)) {
-+              if (alert_email == NULL)
-+                      alert_email = strdup(w);
-+              else
-+                      fprintf(stderr, Name ": excess address on MAIL line: %s - ignored\n",
-+                              w);
-+      }
-+}
-+
-+static char *alert_mail_from = NULL;
-+void mailfromline(char *line)
-+{
-+      char *w;
-+
-+      for (w=dl_next(line); w != line ; w=dl_next(w)) {
-+              if (alert_mail_from == NULL)
-+                      alert_mail_from = strdup(w);
-+              else {
-+                      char *t= NULL;
-+                      asprintf(&t, "%s %s", alert_mail_from, w);
-+                      free(alert_mail_from);
-+                      alert_mail_from = t;
-+              }
-+      }
-+}
-+
-+
-+static char *alert_program = NULL;
-+void programline(char *line)
-+{
-+      char *w;
-+
-+      for (w=dl_next(line); w != line ; w=dl_next(w)) {
-+              if (alert_program == NULL)
-+                      alert_program = strdup(w);
-+              else
-+                      fprintf(stderr, Name ": excess program on PROGRAM line: %s - ignored\n",
-+                              w);
-+      }
-+}
-+
-+static char *home_host = NULL;
-+void homehostline(char *line)
-+{
-+      char *w;
-+
-+      for (w=dl_next(line); w != line ; w=dl_next(w)) {
-+              if (home_host == NULL)
-+                      home_host = strdup(w);
-+              else
-+                      fprintf(stderr, Name ": excess host name on HOMEHOST line: %s - ignored\n",
-+                              w);
-+      }
-+}
-+
-+
-+int loaded = 0;
-+
-+static char *conffile = NULL;
-+void set_conffile(char *file)
-+{
-+      conffile = file;
-+}
-+
-+void load_conffile(void)
-+{
-+      FILE *f;
-+      char *line;
-+
-+      if (loaded) return;
-+      if (conffile == NULL)
-+              conffile = DefaultConfFile;
-+
-+      if (strcmp(conffile, "none") == 0) {
-+              loaded = 1;
-+              return;
-+      }
-+      if (strcmp(conffile, "partitions")==0) {
-+              char *list = dl_strdup("DEV");
-+              dl_init(list);
-+              dl_add(list, dl_strdup("partitions"));
-+              devline(list);
-+              free_line(list);
-+              loaded = 1;
-+              return;
-+      }
-+      f = fopen(conffile, "r");
-+      /* Debian chose to relocate mdadm.conf into /etc/mdadm/.
-+       * To allow Debian users to compile from clean source and still
-+       * have a working mdadm, we read /etc/mdadm/mdadm.conf
-+       * if /etc/mdadm.conf doesn't exist
-+       */
-+      if (f == NULL &&
-+          conffile == DefaultConfFile) {
-+              f = fopen(DefaultAltConfFile, "r");
-+              if (f)
-+                      conffile = DefaultAltConfFile;
-+      }
-+      if (f == NULL)
-+              return;
-+
-+      loaded = 1;
-+      while ((line=conf_line(f))) {
-+              switch(match_keyword(line)) {
-+              case Devices:
-+                      devline(line);
-+                      break;
-+              case Array:
-+                      arrayline(line);
-+                      break;
-+              case Mailaddr:
-+                      mailline(line);
-+                      break;
-+              case Mailfrom:
-+                      mailfromline(line);
-+                      break;
-+              case Program:
-+                      programline(line);
-+                      break;
-+              case CreateDev:
-+                      createline(line);
-+                      break;
-+              case Homehost:
-+                      homehostline(line);
-+                      break;
-+              default:
-+                      fprintf(stderr, Name ": Unknown keyword %s\n", line);
-+              }
-+              free_line(line);
-+      }
-+    
-+      fclose(f);
-+
-+/*    printf("got file\n"); */
-+}
-+
-+char *conf_get_mailaddr(void)
-+{
-+      load_conffile();
-+      return alert_email;
-+}
-+
-+char *conf_get_mailfrom(void)
-+{
-+      load_conffile();
-+      return alert_mail_from;
-+}
-+
-+char *conf_get_program(void)
-+{
-+      load_conffile();
-+      return alert_program;
-+}
-+
-+char *conf_get_homehost(void)
-+{
-+      load_conffile();
-+      return home_host;
-+}
-+
-+struct createinfo *conf_get_create_info(void)
-+{
-+      load_conffile();
-+      return &createinfo;
-+}
-+
-+mddev_ident_t conf_get_ident(char *dev)
-+{
-+      mddev_ident_t rv;
-+      load_conffile();
-+      rv = mddevlist;
-+      while (dev && rv && strcmp(dev, rv->devname)!=0)
-+              rv = rv->next;
-+      return rv;
-+}
-+
-+mddev_dev_t conf_get_devs()
-+{
-+      glob_t globbuf;
-+      struct conf_dev *cd;
-+      int flags = 0;
-+      static mddev_dev_t dlist = NULL;
-+      unsigned int i;
-+
-+      while (dlist) {
-+              mddev_dev_t t = dlist;
-+              dlist = dlist->next;
-+              free(t->devname);
-+              free(t);
-+      }
-+    
-+      load_conffile();
-+
-+      if (cdevlist == NULL)
-+              /* default to 'partitions */
-+              dlist = load_partitions();
-+
-+      for (cd=cdevlist; cd; cd=cd->next) {
-+              if (strcasecmp(cd->name, "partitions")==0 && dlist == NULL)
-+                      dlist = load_partitions();
-+              else {
-+                      glob(cd->name, flags, NULL, &globbuf);
-+                      flags |= GLOB_APPEND;
-+              }
-+      }
-+      if (flags & GLOB_APPEND) {
-+              for (i=0; i<globbuf.gl_pathc; i++) {
-+                      mddev_dev_t t = malloc(sizeof(*t));
-+                      t->devname = strdup(globbuf.gl_pathv[i]);
-+                      t->next = dlist;
-+                      t->used = 0;
-+                      dlist = t;
-+/*    printf("one dev is %s\n", t->devname);*/
-+              }
-+              globfree(&globbuf);
-+      }
-+
-+      return dlist;
-+}
-+
-+int conf_test_dev(char *devname)
-+{
-+      struct conf_dev *cd;
-+      if (cdevlist == NULL)
-+              /* allow anything by default */
-+              return 1;
-+      for (cd = cdevlist ; cd ; cd = cd->next) {
-+              if (strcasecmp(cd->name, "partitions") == 0)
-+                      return 1;
-+              if (fnmatch(cd->name, devname, FNM_PATHNAME) == 0)
-+                      return 1;
-+      }
-+      return 0;
-+}
-+
-+
-+int match_oneof(char *devices, char *devname)
-+{
-+    /* check if one of the comma separated patterns in devices
-+     * matches devname
-+     */
-+
-+
-+    while (devices && *devices) {
-+      char patn[1024];
-+      char *p = devices;
-+      devices = strchr(devices, ',');
-+      if (!devices)
-+          devices = p + strlen(p);
-+      if (devices-p < 1024) {
-+              strncpy(patn, p, devices-p);
-+              patn[devices-p] = 0;
-+              if (fnmatch(patn, devname, FNM_PATHNAME)==0)
-+                      return 1;
-+      }
-+      if (*devices == ',')
-+              devices++;
-+    }
-+    return 0;
-+}
---- a/mdadm/Config.in  1970-01-01 03:00:00.000000000 +0300
-+++ mdadm/mdadm/Config.in      2011-01-12 21:33:01.000000000 +0200
-@@ -0,0 +1,15 @@
-+#
-+# For a description of the syntax of this configuration file,
-+# see scripts/kbuild/config-language.txt.
-+#
-+
-+menu "Linux mdadm Utilities"
-+
-+config MDADM
-+      bool "mdadm"
-+      default n
-+      help
-+        assemble or examine raid array
-+
-+endmenu
-+
---- a/mdadm/dlink.c    1970-01-01 03:00:00.000000000 +0300
-+++ mdadm/mdadm/dlink.c        2011-01-12 21:33:01.000000000 +0200
-@@ -0,0 +1,79 @@
-+
-+/* doubly linked lists */
-+/* This is free software. No strings attached. No copyright claimed */
-+
-+#include      <unistd.h>
-+#include      <stdlib.h>
-+#include      <string.h>
-+#ifdef __dietlibc__
-+char *strncpy(char *dest, const char *src, size_t n) __THROW;
-+#endif
-+#include      "dlink.h"
-+
-+
-+void *dl_head()
-+{
-+    void *h;
-+    h = dl_alloc(0);
-+    dl_next(h) = h;
-+    dl_prev(h) = h;
-+    return h;
-+}
-+
-+void dl_free(void *v)
-+{
-+    struct __dl_head *vv  = v;
-+    free(vv-1);
-+}
-+
-+void dl_init(void *v)
-+{
-+    dl_next(v) = v;
-+    dl_prev(v) = v;
-+}
-+
-+void dl_insert(void *head, void *val)
-+{
-+    dl_next(val) = dl_next(head);
-+    dl_prev(val) = head;
-+    dl_next(dl_prev(val)) = val;
-+    dl_prev(dl_next(val)) = val;
-+}
-+
-+void dl_add(void *head, void *val)
-+{
-+    dl_prev(val) = dl_prev(head);
-+    dl_next(val) = head;
-+    dl_next(dl_prev(val)) = val;
-+    dl_prev(dl_next(val)) = val;
-+}
-+
-+void dl_del(void *val)
-+{
-+    if (dl_prev(val) == 0 || dl_next(val) == 0)
-+      return;
-+    dl_prev(dl_next(val)) = dl_prev(val);
-+    dl_next(dl_prev(val)) = dl_next(val);
-+    dl_prev(val) = dl_next(val) = 0;
-+}
-+
-+char *dl_strndup(char *s, int l)
-+{
-+    char *n;
-+    if (s == NULL)
-+      return NULL;
-+    n = dl_newv(char, l+1);
-+    if (n == NULL)
-+      return NULL;
-+    else
-+    {
-+      strncpy(n, s, l);
-+      n[l] = 0;
-+      return n;
-+    }
-+}
-+
-+char *dl_strdup(char *s)
-+{
-+    return dl_strndup(s, (int)strlen(s));
-+}
---- a/mdadm/dlink.h    1970-01-01 03:00:00.000000000 +0300
-+++ mdadm/mdadm/dlink.h        2011-01-12 21:33:01.000000000 +0200
-@@ -0,0 +1,25 @@
-+
-+/* doubley linked lists */
-+/* This is free software. No strings attached. No copyright claimed */
-+
-+struct __dl_head
-+{
-+    void * dh_prev;
-+    void * dh_next;
-+};
-+
-+#define       dl_alloc(size)  ((void*)(((char*)calloc(1,(size)+sizeof(struct __dl_head)))+sizeof(struct __dl_head)))
-+#define       dl_new(t)       ((t*)dl_alloc(sizeof(t)))
-+#define       dl_newv(t,n)    ((t*)dl_alloc(sizeof(t)*n))
-+
-+#define dl_next(p) *(&(((struct __dl_head*)(p))[-1].dh_next))
-+#define dl_prev(p) *(&(((struct __dl_head*)(p))[-1].dh_prev))
-+
-+void *dl_head(void);
-+char *dl_strdup(char *);
-+char *dl_strndup(char *, int);
-+void dl_insert(void*, void*);
-+void dl_add(void*, void*);
-+void dl_del(void*);
-+void dl_free(void*);
-+void dl_init(void*);
---- a/mdadm/Kbuild     1970-01-01 03:00:00.000000000 +0300
-+++ mdadm/mdadm/Kbuild 2011-01-12 21:33:01.000000000 +0200
-@@ -0,0 +1,9 @@
-+# Makefile for busybox
-+#
-+# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
-+#
-+# Licensed under the GPL v2, see the file LICENSE in this tarball.
-+
-+lib-y:=
-+MDADM-y:= config.o util.o dlink.o sha1.o super0.o super1.o mdexamine.o mdassemble.o
-+lib-$(CONFIG_MDADM)   += mdadm.o $(MDADM-y)
---- a/mdadm/md5.h      1970-01-01 03:00:00.000000000 +0300
-+++ mdadm/mdadm/md5.h  2011-01-12 21:33:01.000000000 +0200
-@@ -0,0 +1,134 @@
-+/* Declaration of functions and data types used for MD5 sum computing
-+   library functions.
-+   Copyright (C) 1995-1997,1999-2005 Free Software Foundation, Inc.
-+
-+   NOTE: The canonical source of this file is maintained with the GNU C
-+   Library.  Bugs can be reported to bug-glibc@prep.ai.mit.edu.
-+
-+   This program is free software; you can redistribute it and/or modify it
-+   under the terms of the GNU General Public License as published by the
-+   Free Software Foundation; either version 2, or (at your option) any
-+   later version.
-+
-+   This program is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+   GNU General Public License for more details.
-+
-+   You should have received a copy of the GNU General Public License
-+   along with this program; if not, write to the Free Software Foundation,
-+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
-+
-+#ifndef _MD5_H
-+#define _MD5_H 1
-+
-+#include <stdio.h>
-+
-+# include <inttypes.h>
-+#if HAVE_STDINT_H || _LIBC
-+# include <stdint.h>
-+#endif
-+
-+#ifndef __GNUC_PREREQ
-+# if defined __GNUC__ && defined __GNUC_MINOR__
-+#  define __GNUC_PREREQ(maj, min) \
-+      ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
-+# else
-+#  define __GNUC_PREREQ(maj, min) 0
-+# endif
-+#endif
-+
-+#ifndef __THROW
-+# if defined __cplusplus && __GNUC_PREREQ (2,8)
-+#  define __THROW     throw ()
-+# else
-+#  define __THROW
-+# endif
-+#endif
-+
-+#ifndef __attribute__
-+# if ! __GNUC_PREREQ (2,8) || __STRICT_ANSI__
-+#  define __attribute__(x)
-+# endif
-+#endif
-+
-+#ifndef _LIBC
-+# define __md5_buffer md5_buffer
-+# define __md5_finish_ctx md5_finish_ctx
-+# define __md5_init_ctx md5_init_ctx
-+# define __md5_process_block md5_process_block
-+# define __md5_process_bytes md5_process_bytes
-+# define __md5_read_ctx md5_read_ctx
-+# define __md5_stream md5_stream
-+#endif
-+
-+typedef uint32_t md5_uint32;
-+
-+/* Structure to save state of computation between the single steps.  */
-+struct md5_ctx
-+{
-+  md5_uint32 A;
-+  md5_uint32 B;
-+  md5_uint32 C;
-+  md5_uint32 D;
-+
-+  md5_uint32 total[2];
-+  md5_uint32 buflen;
-+  char buffer[128] __attribute__ ((__aligned__ (__alignof__ (md5_uint32))));
-+};
-+
-+/*
-+ * The following three functions are build up the low level used in
-+ * the functions `md5_stream' and `md5_buffer'.
-+ */
-+
-+/* Initialize structure containing state of computation.
-+   (RFC 1321, 3.3: Step 3)  */
-+extern void __md5_init_ctx (struct md5_ctx *ctx) __THROW;
-+
-+/* Starting with the result of former calls of this function (or the
-+   initialization function update the context for the next LEN bytes
-+   starting at BUFFER.
-+   It is necessary that LEN is a multiple of 64!!! */
-+extern void __md5_process_block (const void *buffer, size_t len,
-+                               struct md5_ctx *ctx) __THROW;
-+
-+/* Starting with the result of former calls of this function (or the
-+   initialization function update the context for the next LEN bytes
-+   starting at BUFFER.
-+   It is NOT required that LEN is a multiple of 64.  */
-+extern void __md5_process_bytes (const void *buffer, size_t len,
-+                               struct md5_ctx *ctx) __THROW;
-+
-+/* Process the remaining bytes in the buffer and put result from CTX
-+   in first 16 bytes following RESBUF.  The result is always in little
-+   endian byte order, so that a byte-wise output yields to the wanted
-+   ASCII representation of the message digest.
-+
-+   IMPORTANT: On some systems it is required that RESBUF be correctly
-+   aligned for a 32 bits value.  */
-+extern void *__md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) __THROW;
-+
-+
-+/* Put result from CTX in first 16 bytes following RESBUF.  The result is
-+   always in little endian byte order, so that a byte-wise output yields
-+   to the wanted ASCII representation of the message digest.
-+
-+   IMPORTANT: On some systems it is required that RESBUF is correctly
-+   aligned for a 32 bits value.  */
-+extern void *__md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) __THROW;
-+
-+
-+/* Compute MD5 message digest for bytes read from STREAM.  The
-+   resulting message digest number will be written into the 16 bytes
-+   beginning at RESBLOCK.  */
-+extern int __md5_stream (FILE *stream, void *resblock) __THROW;
-+
-+/* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
-+   result is always in little endian byte order, so that a byte-wise
-+   output yields to the wanted ASCII representation of the message
-+   digest.  */
-+extern void *__md5_buffer (const char *buffer, size_t len,
-+                         void *resblock) __THROW;
-+
-+#endif /* md5.h */
---- a/mdadm/mdadm.c    1970-01-01 03:00:00.000000000 +0300
-+++ mdadm/mdadm/mdadm.c        2011-01-12 21:33:01.000000000 +0200
-@@ -0,0 +1,18 @@
-+/*
-+ * mdadm support for busybox.
-+ * added by Alan Hourihane <alanh@fairlite.demon.co.uk>
-+ */
-+#include <string.h>
-+
-+extern int mdassemble_main(int argc, char **argv);
-+extern int mdexamine_main(int argc, char **argv);
-+
-+int mdadm_main(int argc, char **argv) {
-+      if (argc >= 2) {
-+              if (!strncmp(argv[1],"--assemble",10))
-+                      return mdassemble_main(argc, argv);
-+              if (!strncmp(argv[1],"--examine",9))
-+                      return mdexamine_main(argc, argv);
-+      }
-+      return 0;
-+}
---- a/mdadm/mdadm.h    1970-01-01 03:00:00.000000000 +0300
-+++ mdadm/mdadm/mdadm.h        2011-01-12 21:33:01.000000000 +0200
-@@ -0,0 +1,540 @@
-+/*
-+ * mdadm - manage Linux "md" devices aka RAID arrays.
-+ *
-+ * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
-+ *
-+ *
-+ *    This program is free software; you can redistribute it and/or modify
-+ *    it under the terms of the GNU General Public License as published by
-+ *    the Free Software Foundation; either version 2 of the License, or
-+ *    (at your option) any later version.
-+ *
-+ *    This program is distributed in the hope that it will be useful,
-+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *    GNU General Public License for more details.
-+ *
-+ *    You should have received a copy of the GNU General Public License
-+ *    along with this program; if not, write to the Free Software
-+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ *
-+ *    Author: Neil Brown
-+ *    Email: <neilb@cse.unsw.edu.au>
-+ *    Paper: Neil Brown
-+ *           School of Computer Science and Engineering
-+ *           The University of New South Wales
-+ *           Sydney, 2052
-+ *           Australia
-+ */
-+
-+#include      <unistd.h>
-+#ifndef __dietlibc__
-+extern __off64_t lseek64 __P ((int __fd, __off64_t __offset, int __whence));
-+#else
-+# if defined(__NO_STAT64) || __WORDSIZE != 32
-+# define lseek64 lseek
-+# endif
-+#endif
-+
-+#include      <sys/types.h>
-+#include      <sys/stat.h>
-+#include      <stdlib.h>
-+#include      <time.h>
-+#include      <sys/time.h>
-+#include      <getopt.h>
-+#include      <fcntl.h>
-+#include      <stdio.h>
-+#include      <errno.h>
-+#include      <string.h>
-+#include      <syslog.h>
-+#ifdef __dietlibc__
-+#include      <strings.h>
-+/* dietlibc has deprecated random and srandom!! */
-+#define random rand
-+#define srandom srand
-+#endif
-+
-+
-+#include      <linux/kdev_t.h>
-+/*#include    <linux/fs.h> */
-+#include      <sys/mount.h>
-+#include      <asm/types.h>
-+#include      <sys/ioctl.h>
-+#define       MD_MAJOR 9
-+#define MdpMinorShift 6
-+
-+#ifndef BLKGETSIZE64
-+#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
-+#endif
-+
-+#define DEFAULT_BITMAP_CHUNK 4096
-+#define DEFAULT_BITMAP_DELAY 5
-+#define DEFAULT_MAX_WRITE_BEHIND 256
-+
-+#include      "md_u.h"
-+#include      "md_p.h"
-+#include      "bitmap.h"
-+
-+#include <endian.h>
-+/* Redhat don't like to #include <asm/byteorder.h>, and
-+ * some time include <linux/byteorder/xxx_endian.h> isn't enough,
-+ * and there is no standard conversion function so... */
-+/* And dietlibc doesn't think byteswap is ok, so.. */
-+/*  #include <byteswap.h> */
-+#define bswap_16(x) (((x) & 0x00ffU) << 8 | \
-+                   ((x) & 0xff00U) >> 8)
-+#define bswap_32(x) (((x) & 0x000000ffU) << 24 | \
-+                   ((x) & 0xff000000U) >> 24 | \
-+                   ((x) & 0x0000ff00U) << 8  | \
-+                   ((x) & 0x00ff0000U) >> 8)
-+#define bswap_64(x) (((x) & 0x00000000000000ffULL) << 56 | \
-+                   ((x) & 0xff00000000000000ULL) >> 56 | \
-+                   ((x) & 0x000000000000ff00ULL) << 40 | \
-+                   ((x) & 0x00ff000000000000ULL) >> 40 | \
-+                   ((x) & 0x0000000000ff0000ULL) << 24 | \
-+                   ((x) & 0x0000ff0000000000ULL) >> 24 | \
-+                   ((x) & 0x00000000ff000000ULL) << 8 | \
-+                   ((x) & 0x000000ff00000000ULL) >> 8)
-+
-+#if BYTE_ORDER == LITTLE_ENDIAN
-+#define       __cpu_to_le16(_x) (_x)
-+#define __cpu_to_le32(_x) (_x)
-+#define __cpu_to_le64(_x) (_x)
-+#define       __le16_to_cpu(_x) (_x)
-+#define __le32_to_cpu(_x) (_x)
-+#define __le64_to_cpu(_x) (_x)
-+#elif BYTE_ORDER == BIG_ENDIAN
-+#define       __cpu_to_le16(_x) bswap_16(_x)
-+#define __cpu_to_le32(_x) bswap_32(_x)
-+#define __cpu_to_le64(_x) bswap_64(_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)
-+#else
-+#  error "unknown endianness."
-+#endif
-+
-+
-+
-+/* general information that might be extracted from a superblock */
-+struct mdinfo {
-+      mdu_array_info_t        array;
-+      mdu_disk_info_t         disk;
-+      __u64                   events;
-+      int                     uuid[4];
-+      char                    name[33];
-+      unsigned long long      data_offset;
-+      unsigned long long      component_size;
-+      int                     reshape_active;
-+      unsigned long long      reshape_progress;
-+      int                     new_level, delta_disks, new_layout, new_chunk;
-+};
-+
-+struct createinfo {
-+      int     uid;
-+      int     gid;
-+      int     autof;
-+      int     mode;
-+      int     symlinks;
-+      struct supertype *supertype;
-+};
-+
-+#define Name "mdadm"
-+
-+enum mode {
-+      ASSEMBLE=1,
-+      BUILD,
-+      CREATE,
-+      MANAGE,
-+      MISC,
-+      MONITOR,
-+      GROW,
-+      INCREMENTAL,
-+      AUTODETECT,
-+};
-+
-+extern char short_options[];
-+extern char short_bitmap_auto_options[];
-+extern struct option long_options[];
-+extern char Version[], Usage[], Help[], OptionHelp[],
-+      Help_create[], Help_build[], Help_assemble[], Help_grow[],
-+      Help_incr[],
-+      Help_manage[], Help_misc[], Help_monitor[], Help_config[];
-+
-+/* for option that don't have short equivilents, we assign arbitrary
-+ * small numbers.  '1' means an undecorated option, so we start at '2'.
-+ */
-+enum special_options {
-+      AssumeClean = 2,
-+      BitmapChunk,
-+      WriteBehind,
-+      ReAdd,
-+      NoDegraded,
-+      Sparc22,
-+      BackupFile,
-+      HomeHost,
-+      AutoHomeHost,
-+      Symlinks,
-+      AutoDetect,
-+};
-+
-+/* structures read from config file */
-+/* List of mddevice names and identifiers
-+ * Identifiers can be:
-+ *    uuid=128-hex-uuid
-+ *    super-minor=decimal-minor-number-from-superblock
-+ *    devices=comma,separated,list,of,device,names,with,wildcards
-+ *
-+ * If multiple fields are present, the intersection of all matching
-+ * devices is considered
-+ */
-+#define UnSet (0xfffe)
-+typedef struct mddev_ident_s {
-+      char    *devname;
-+      
-+      int     uuid_set;
-+      int     uuid[4];
-+      char    name[33];
-+
-+      unsigned int super_minor;
-+
-+      char    *devices;       /* comma separated list of device
-+                               * names with wild cards
-+                               */
-+      int     level;
-+      unsigned int raid_disks;
-+      unsigned int spare_disks;
-+      struct supertype *st;
-+      int     autof;          /* 1 for normal, 2 for partitioned */
-+      char    *spare_group;
-+      char    *bitmap_file;
-+      int     bitmap_fd;
-+
-+      struct mddev_ident_s *next;
-+} *mddev_ident_t;
-+
-+/* List of device names - wildcards expanded */
-+typedef struct mddev_dev_s {
-+      char *devname;
-+      char disposition;       /* 'a' for add, 'r' for remove, 'f' for fail.
-+                               * Not set for names read from .config
-+                               */
-+      char writemostly;
-+      char re_add;
-+      char used;              /* set when used */
-+      struct mddev_dev_s *next;
-+} *mddev_dev_t;
-+
-+typedef struct mapping {
-+      char *name;
-+      int num;
-+} mapping_t;
-+
-+
-+struct mdstat_ent {
-+      char            *dev;
-+      int             devnum;
-+      int             active;
-+      char            *level;
-+      char            *pattern; /* U or up, _ for down */
-+      int             percent; /* -1 if no resync */
-+      int             resync; /* 1 if resync, 0 if recovery */
-+      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 int mddev_busy(int devnum);
-+
-+struct map_ent {
-+      struct map_ent *next;
-+      int     devnum;
-+      int     major,minor;
-+      int     uuid[4];
-+      char    *path;
-+};
-+extern int map_update(struct map_ent **mpp, int devnum, int major, int minor,
-+                    int uuid[4], char *path);
-+extern struct map_ent *map_by_uuid(struct map_ent **map, int uuid[4]);
-+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);
-+
-+/* Data structure for holding info read from sysfs */
-+struct sysdev {
-+      char    name[20];
-+      int     role;
-+      int     major, minor;
-+      unsigned long long offset, size;
-+      int     state;
-+      int     errors;
-+      struct sysdev *next;
-+};
-+struct sysarray {
-+      char    name[20];
-+      struct sysdev *devs;
-+      int     chunk;
-+      unsigned long long component_size;
-+      int     layout;
-+      int     level;
-+      int     spares;
-+      int     cache_size;
-+      int     mismatch_cnt;
-+      int     major_version, minor_version;
-+};
-+/* various details can be requested */
-+#define       GET_LEVEL       1
-+#define       GET_LAYOUT      2
-+#define       GET_COMPONENT   4
-+#define       GET_CHUNK       8
-+#define GET_CACHE     16
-+#define       GET_MISMATCH    32
-+#define       GET_VERSION     64
-+
-+#define       GET_DEVS        1024 /* gets role, major, minor */
-+#define       GET_OFFSET      2048
-+#define       GET_SIZE        4096
-+#define       GET_STATE       8192
-+#define       GET_ERROR       16384
-+
-+/* If fd >= 0, get the array it is open on,
-+ * else use devnum. >=0 -> major9. <0.....
-+ */
-+extern void sysfs_free(struct sysarray *sra);
-+extern struct sysarray *sysfs_read(int fd, int devnum, unsigned long options);
-+extern int sysfs_set_str(struct sysarray *sra, struct sysdev *dev,
-+                       char *name, char *val);
-+extern int sysfs_set_num(struct sysarray *sra, struct sysdev *dev,
-+                       char *name, unsigned long long val);
-+extern int sysfs_get_ll(struct sysarray *sra, struct sysdev *dev,
-+                      char *name, unsigned long long *val);
-+
-+
-+extern int save_stripes(int *source, unsigned long long *offsets,
-+                      int raid_disks, int chunk_size, int level, int layout,
-+                      int nwrites, int *dest,
-+                      unsigned long long start, unsigned long long length);
-+extern int restore_stripes(int *dest, unsigned long long *offsets,
-+                         int raid_disks, int chunk_size, int level, int layout,
-+                         int source, unsigned long long read_offset,
-+                         unsigned long long start, unsigned long long length);
-+
-+#ifndef Sendmail
-+#define Sendmail "/usr/lib/sendmail -t"
-+#endif
-+
-+#define SYSLOG_FACILITY LOG_DAEMON
-+
-+extern char *map_num(mapping_t *map, int num);
-+extern int map_name(mapping_t *map, char *name);
-+extern mapping_t r5layout[], pers[], modes[], faultylayout[];
-+
-+extern char *map_dev(int major, int minor, int create);
-+
-+
-+extern struct superswitch {
-+      void (*examine_super)(void *sbv, char *homehost);
-+      void (*brief_examine_super)(void *sbv);
-+      void (*detail_super)(void *sbv, char *homehost);
-+      void (*export_super)(void *sbv);
-+      void (*brief_detail_super)(void *sbv);
-+      void (*uuid_from_super)(int uuid[4], void *sbv);
-+      void (*getinfo_super)(struct mdinfo *info, void *sbv);
-+      int (*match_home)(void *sbv, char *homehost);
-+      int (*update_super)(struct mdinfo *info, void *sbv, char *update,
-+                          char *devname, int verbose,
-+                          int uuid_set, char *homehost);
-+      int (*init_super)(struct supertype *st, void **sbp, mdu_array_info_t *info, unsigned long long size, char *name, char *homehost, int *uuid);
-+      void (*add_to_super)(void *sbv, mdu_disk_info_t *dinfo);
-+      int (*store_super)(struct supertype *st, int fd, void *sbv);
-+      int (*write_init_super)(struct supertype *st, void *sbv, mdu_disk_info_t *dinfo, char *devname);
-+      int (*compare_super)(void **firstp, void *secondv);
-+      int (*load_super)(struct supertype *st, int fd, void **sbp, char *devname);
-+      struct supertype * (*match_metadata_desc)(char *arg);
-+      __u64 (*avail_size)(struct supertype *st, __u64 size);
-+      int (*add_internal_bitmap)(struct supertype *st, void *sbv, int *chunkp,
-+                                 int delay, int write_behind,
-+                                 unsigned long long size, int may_change, int major);
-+      void (*locate_bitmap)(struct supertype *st, int fd, void *sbv);
-+      int (*write_bitmap)(struct supertype *st, int fd, void *sbv);
-+      int major;
-+      int swapuuid; /* true if uuid is bigending rather than hostendian */
-+} super0, super1, *superlist[];
-+
-+struct supertype {
-+      struct superswitch *ss;
-+      int minor_version;
-+      int max_devs;
-+};
-+
-+extern struct supertype *super_by_version(int vers, int minor);
-+extern struct supertype *guess_super(int fd);
-+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);
-+
-+#if __GNUC__ < 3
-+struct stat64;
-+#endif
-+
-+#define HAVE_NFTW  we assume
-+#define HAVE_FTW
-+
-+#ifdef UCLIBC
-+# include <features.h>
-+# ifndef  __UCLIBC_HAS_FTW__
-+#  undef HAVE_FTW
-+#  undef HAVE_NFTW
-+# endif
-+#endif
-+
-+#ifdef __dietlibc__
-+# undef HAVE_NFTW
-+#endif
-+
-+#ifndef HAVE_NFTW
-+# define FTW_PHYS 1
-+# ifndef HAVE_FTW
-+  struct FTW {};
-+# endif
-+#endif
-+
-+#ifdef HAVE_FTW
-+# include <ftw.h>
-+#endif
-+
-+extern int add_dev(const char *name, const struct stat *stb, int flag, struct FTW *s);
-+
-+
-+extern int Manage_ro(char *devname, int fd, int readonly);
-+extern int Manage_runstop(char *devname, int fd, int runstop, int quiet);
-+extern int Manage_resize(char *devname, int fd, long long size, int raid_disks);
-+extern int Manage_reconfig(char *devname, int fd, int layout);
-+extern int Manage_subdevs(char *devname, int fd,
-+                        mddev_dev_t devlist, int verbose);
-+extern int autodetect(void);
-+extern int Grow_Add_device(char *devname, int fd, char *newdev);
-+extern int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int write_behind, int force);
-+extern int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
-+                      long long size,
-+                      int level, int layout, int chunksize, int raid_disks);
-+extern int Grow_restart(struct supertype *st, struct mdinfo *info,
-+                      int *fdlist, int cnt, char *backup_file);
-+
-+
-+extern int Assemble(struct supertype *st, char *mddev, int mdfd,
-+                  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 Create(struct supertype *st, char *mddev, int mdfd,
-+                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);
-+
-+extern int Detail(char *dev, int brief, int export, int test, char *homehost);
-+extern int Query(char *dev);
-+
-+extern int md_get_version(int fd);
-+extern int get_linux_version(void);
-+extern int parse_uuid(char *str, int uuid[4]);
-+extern int check_ext2(int fd, char *name);
-+extern int check_reiser(int fd, char *name);
-+extern int check_raid(int fd, char *name);
-+
-+extern int get_mdp_major(void);
-+extern int dev_open(char *dev, int flags);
-+extern int is_standard(char *dev, int *nump);
-+
-+extern int parse_auto(char *str, char *msg, int config);
-+extern mddev_ident_t conf_get_ident(char *dev);
-+extern mddev_dev_t conf_get_devs(void);
-+extern int conf_test_dev(char *devname);
-+extern struct createinfo *conf_get_create_info(void);
-+extern void set_conffile(char *file);
-+extern char *conf_get_mailaddr(void);
-+extern char *conf_get_mailfrom(void);
-+extern char *conf_get_program(void);
-+extern char *conf_get_homehost(void);
-+extern char *conf_line(FILE *file);
-+extern char *conf_word(FILE *file, int allow_key);
-+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 int same_uuid(int a[4], int b[4], int swapuuid);
-+extern void copy_uuid(void *a, int b[4], int swapuuid);
-+/* extern int compare_super(mdp_super_t *first, mdp_super_t *second);*/
-+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 char *human_size(long long bytes);
-+char *human_size_brief(long long bytes);
-+
-+extern void put_md_name(char *name);
-+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);
-+
-+
-+#define       LEVEL_MULTIPATH         (-4)
-+#define       LEVEL_LINEAR            (-1)
-+#define       LEVEL_FAULTY            (-5)
-+
-+
-+/* faulty stuff */
-+
-+#define       WriteTransient  0
-+#define       ReadTransient   1
-+#define       WritePersistent 2
-+#define       ReadPersistent  3
-+#define       WriteAll        4 /* doesn't go to device */
-+#define       ReadFixable     5
-+#define       Modes   6
-+
-+#define       ClearErrors     31
-+#define       ClearFaults     30
-+
-+#define AllPersist    100 /* internal use only */
-+#define       NoPersist       101
-+
-+#define       ModeMask        0x1f
-+#define       ModeShift       5
-+
-+
-+#ifdef __TINYC__
-+#undef minor
-+#undef major
-+#undef makedev
-+#define minor(x) ((x)&0xff)
-+#define major(x) (((x)>>8)&0xff)
-+#define makedev(M,m) (((M)<<8) | (m))
-+#endif
-+
-+/* for raid5 */
-+#define ALGORITHM_LEFT_ASYMMETRIC     0
-+#define ALGORITHM_RIGHT_ASYMMETRIC    1
-+#define ALGORITHM_LEFT_SYMMETRIC      2
-+#define ALGORITHM_RIGHT_SYMMETRIC     3
---- a/mdadm/mdassemble.c       1970-01-01 03:00:00.000000000 +0300
-+++ mdadm/mdadm/mdassemble.c   2011-01-12 21:33:01.000000000 +0200
-@@ -0,0 +1,908 @@
-+/*
-+ * mdadm - manage Linux "md" devices aka RAID arrays.
-+ *
-+ * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
-+ *
-+ *
-+ *    This program is free software; you can redistribute it and/or modify
-+ *    it under the terms of the GNU General Public License as published by
-+ *    the Free Software Foundation; either version 2 of the License, or
-+ *    (at your option) any later version.
-+ *
-+ *    This program is distributed in the hope that it will be useful,
-+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *    GNU General Public License for more details.
-+ *
-+ *    You should have received a copy of the GNU General Public License
-+ *    along with this program; if not, write to the Free Software
-+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ *
-+ *    Author: Neil Brown
-+ *    Email: <neilb@cse.unsw.edu.au>
-+ *    Paper: Neil Brown
-+ *           School of Computer Science and Engineering
-+ *           The University of New South Wales
-+ *           Sydney, 2052
-+ *           Australia
-+ */
-+
-+#include      "mdadm.h"
-+#include      <ctype.h>
-+
-+static int name_matches(char *found, char *required, char *homehost)
-+{
-+      /* See if the name found matches the required name, possibly
-+       * prefixed with 'homehost'
-+       */
-+      char fnd[33];
-+
-+      strncpy(fnd, found, 32);
-+      fnd[32] = 0;
-+      if (strcmp(found, required)==0)
-+              return 1;
-+      if (homehost) {
-+              int l = strlen(homehost);
-+              if (l < 32 && fnd[l] == ':' &&
-+                  strcmp(fnd+l+1, required)==0)
-+                      return 1;
-+      }
-+      return 0;
-+}
-+
-+int open_mddev(char *dev, int autof/*unused */)
-+{
-+      int mdfd = open(dev, O_RDWR, 0);
-+      if (mdfd < 0)
-+              fprintf(stderr, Name ": error opening %s: %s\n",
-+                      dev, strerror(errno));
-+      else if (md_get_version(mdfd) <= 0) {
-+              fprintf(stderr, Name ": %s does not appear to be an md device\n",
-+                      dev);
-+              close(mdfd);
-+              mdfd = -1;
-+      }
-+      return mdfd;
-+}
-+
-+int Assemble(struct supertype *st, char *mddev, int mdfd,
-+           mddev_ident_t ident,
-+           mddev_dev_t devlist, char *backup_file,
-+           int readonly, int runstop,
-+           char *update, char *homehost,
-+           int verbose, int force)
-+{
-+      /*
-+       * The task of Assemble is to find a collection of
-+       * devices that should (according to their superblocks)
-+       * form an array, and to give this collection to the MD driver.
-+       * In Linux-2.4 and later, this involves submitting a
-+       * SET_ARRAY_INFO ioctl with no arg - to prepare
-+       * the array - and then submit a number of
-+       * ADD_NEW_DISK ioctls to add disks into
-+       * the array.  Finally RUN_ARRAY might
-+       * be submitted to start the array.
-+       *
-+       * Much of the work of Assemble is in finding and/or
-+       * checking the disks to make sure they look right.
-+       *
-+       * If mddev is not set, then scan must be set and we
-+       *  read through the config file for dev+uuid mapping
-+       *  We recurse, setting mddev, for each device that
-+       *    - isn't running
-+       *    - has a valid uuid (or any uuid if !uuidset)
-+       *
-+       * If mddev is set, we try to determine state of md.
-+       *   check version - must be at least 0.90.0
-+       *   check kernel version.  must be at least 2.4.
-+       *    If not, we can possibly fall back on START_ARRAY
-+       *   Try to GET_ARRAY_INFO.
-+       *     If possible, give up
-+       *     If not, try to STOP_ARRAY just to make sure
-+       *
-+       * If !uuidset and scan, look in conf-file for uuid
-+       *       If not found, give up
-+       * If !devlist and scan and uuidset, get list of devs from conf-file
-+       *
-+       * For each device:
-+       *   Check superblock - discard if bad
-+       *   Check uuid (set if we don't have one) - discard if no match
-+       *   Check superblock similarity if we have a superblock - discard if different
-+       *   Record events, devicenum
-+       * This should give us a list of devices for the array
-+       * We should collect the most recent event number
-+       *
-+       * Count disks with recent enough event count
-+       * While force && !enough disks
-+       *    Choose newest rejected disks, update event count
-+       *     mark clean and rewrite superblock
-+       * If recent kernel:
-+       *    SET_ARRAY_INFO
-+       *    foreach device with recent events : ADD_NEW_DISK
-+       *    if runstop == 1 || "enough" disks and runstop==0 -> RUN_ARRAY
-+       * If old kernel:
-+       *    Check the device numbers in superblock are right
-+       *    update superblock if any changes
-+       *    START_ARRAY
-+       *
-+       */
-+      int clean = 0;
-+      int old_linux = 0;
-+      int vers = 0; /* Keep gcc quite - it really is initialised */
-+      void *first_super = NULL, *super = NULL;
-+      struct {
-+              char *devname;
-+              unsigned int major, minor;
-+              unsigned int oldmajor, oldminor;
-+              long long events;
-+              int uptodate;
-+              int state;
-+              int raid_disk;
-+              int disk_nr;
-+      } *devices;
-+      int *best = NULL; /* indexed by raid_disk */
-+      unsigned int bestcnt = 0;
-+      int devcnt = 0;
-+      unsigned int okcnt, sparecnt;
-+      unsigned int req_cnt;
-+      unsigned int i;
-+      int most_recent = 0;
-+      int chosen_drive;
-+      int change = 0;
-+      int inargv = 0;
-+      int bitmap_done;
-+      int start_partial_ok = (runstop >= 0) && (force || devlist==NULL || mdfd < 0);
-+      unsigned int num_devs;
-+      mddev_dev_t tmpdev;
-+      struct mdinfo info;
-+      char *avail;
-+      int nextspare = 0;
-+
-+      if (mdfd < 0)
-+              return 2;
-+
-+      if (get_linux_version() < 2004000)
-+              old_linux = 1;
-+
-+      if (mdfd >= 0) {
-+              vers = md_get_version(mdfd);
-+              if (vers <= 0) {
-+                      fprintf(stderr, Name ": %s appears not to be an md device.\n", mddev);
-+                      return 1;
-+              }
-+              if (vers < 9000) {
-+                      fprintf(stderr, Name ": Assemble requires driver version 0.90.0 or later.\n"
-+                              "    Upgrade your kernel or try --build\n");
-+                      return 1;
-+              }
-+
-+              if (ioctl(mdfd, GET_ARRAY_INFO, &info.array)>=0) {
-+                      fprintf(stderr, Name ": device %s already active - cannot assemble it\n",
-+                              mddev);
-+                      return 1;
-+              }
-+              ioctl(mdfd, STOP_ARRAY, NULL); /* just incase it was started but has no content */
-+      }
-+      /*
-+       * If any subdevs are listed, then any that don't
-+       * match ident are discarded.  Remainder must all match and
-+       * become the array.
-+       * If no subdevs, then we scan all devices in the config file, but
-+       * there must be something in the identity
-+       */
-+
-+      if (!devlist &&
-+          ident->uuid_set == 0 &&
-+          ident->super_minor < 0 &&
-+          ident->devices == NULL) {
-+              fprintf(stderr, Name ": No identity information available for %s - cannot assemble.\n",
-+                      mddev ? mddev : "further assembly");
-+              return 1;
-+      }
-+      if (devlist == NULL)
-+              devlist = conf_get_devs();
-+      else if (mdfd >= 0)
-+              inargv = 1;
-+
-+      tmpdev = devlist; num_devs = 0;
-+      while (tmpdev) {
-+              if (tmpdev->used)
-+                      tmpdev->used = 2;
-+              else
-+                      num_devs++;
-+              tmpdev = tmpdev->next;
-+      }
-+      devices = malloc(num_devs * sizeof(*devices));
-+
-+      if (!st && ident->st) st = ident->st;
-+
-+      if (verbose>0)
-+          fprintf(stderr, Name ": looking for devices for %s\n",
-+                  mddev ? mddev : "further assembly");
-+
-+      /* first walk the list of devices to find a consistent set
-+       * that match the criterea, if that is possible.
-+       * We flag the one we like with 'used'.
-+       */
-+      for (tmpdev = devlist;
-+           tmpdev;
-+           tmpdev = tmpdev->next) {
-+              char *devname = tmpdev->devname;
-+              int dfd;
-+              struct stat stb;
-+              struct supertype *tst = st;
-+
-+              if (tmpdev->used > 1) continue;
-+
-+              if (ident->devices &&
-+                  !match_oneof(ident->devices, devname)) {
-+                      if ((inargv && verbose>=0) || verbose > 0)
-+                              fprintf(stderr, Name ": %s is not one of %s\n", devname, ident->devices);
-+                      continue;
-+              }
-+
-+              if (super) {
-+                      free(super);
-+                      super = NULL;
-+              }
-+              
-+              dfd = dev_open(devname, O_RDONLY|O_EXCL);
-+              if (dfd < 0) {
-+                      if ((inargv && verbose >= 0) || verbose > 0)
-+                              fprintf(stderr, Name ": cannot open device %s: %s\n",
-+                                      devname, strerror(errno));
-+                      tmpdev->used = 2;
-+              } else if (fstat(dfd, &stb)< 0) {
-+                      /* Impossible! */
-+                      fprintf(stderr, Name ": fstat failed for %s: %s\n",
-+                              devname, strerror(errno));
-+                      tmpdev->used = 2;
-+              } else if ((stb.st_mode & S_IFMT) != S_IFBLK) {
-+                      fprintf(stderr, Name ": %s is not a block device.\n",
-+                              devname);
-+                      tmpdev->used = 2;
-+              } else if (!tst && (tst = guess_super(dfd)) == NULL) {
-+                      if ((inargv && verbose >= 0) || verbose > 0)
-+                              fprintf(stderr, Name ": no recogniseable superblock on %s\n",
-+                                      devname);
-+                      tmpdev->used = 2;
-+              } else if (tst->ss->load_super(tst,dfd, &super, NULL)) {
-+                      if ((inargv && verbose >= 0) || verbose > 0)
-+                              fprintf( stderr, Name ": no RAID superblock on %s\n",
-+                                       devname);
-+              } else {
-+                      tst->ss->getinfo_super(&info, super);
-+              }
-+              if (dfd >= 0) close(dfd);
-+
-+              if (ident->uuid_set && (!update || strcmp(update, "uuid")!= 0) &&
-+                  (!super || same_uuid(info.uuid, ident->uuid, tst->ss->swapuuid)==0)) {
-+                      if ((inargv && verbose >= 0) || verbose > 0)
-+                              fprintf(stderr, Name ": %s has wrong uuid.\n",
-+                                      devname);
-+                      continue;
-+              }
-+              if (ident->name[0] && (!update || strcmp(update, "name")!= 0) &&
-+                  (!super || name_matches(info.name, ident->name, homehost)==0)) {
-+                      if ((inargv && verbose >= 0) || verbose > 0)
-+                              fprintf(stderr, Name ": %s has wrong name.\n",
-+                                      devname);
-+                      continue;
-+              }
-+              if (ident->super_minor != UnSet &&
-+                  (!super || ident->super_minor != info.array.md_minor)) {
-+                      if ((inargv && verbose >= 0) || verbose > 0)
-+                              fprintf(stderr, Name ": %s has wrong super-minor.\n",
-+                                      devname);
-+                      continue;
-+              }
-+              if (ident->level != UnSet &&
-+                  (!super|| ident->level != info.array.level)) {
-+                      if ((inargv && verbose >= 0) || verbose > 0)
-+                              fprintf(stderr, Name ": %s has wrong raid level.\n",
-+                                      devname);
-+                      continue;
-+              }
-+              if (ident->raid_disks != UnSet &&
-+                  (!super || ident->raid_disks!= info.array.raid_disks)) {
-+                      if ((inargv && verbose >= 0) || verbose > 0)
-+                              fprintf(stderr, Name ": %s requires wrong number of drives.\n",
-+                                      devname);
-+                      continue;
-+              }
-+              if (mdfd < 0) {
-+                      if (tst == NULL || super == NULL)
-+                              continue;
-+                      if (update == NULL &&
-+                          tst->ss->match_home(super, homehost)==0) {
-+                              if ((inargv && verbose >= 0) || verbose > 0)
-+                                      fprintf(stderr, Name ": %s is not built for host %s.\n",
-+                                              devname, homehost);
-+                              /* Auto-assemble, and this is not a usable host */
-+                              /* if update != NULL, we are updating the host
-+                               * name... */
-+                              continue;
-+                      }
-+              }
-+              /* If we are this far, then we are nearly commited to this device.
-+               * If the super_block doesn't exist, or doesn't match others,
-+               * then we probably cannot continue
-+               * However if one of the arrays is for the homehost, and
-+               * the other isn't that can disambiguate.
-+               */
-+
-+              if (!super) {
-+                      fprintf(stderr, Name ": %s has no superblock - assembly aborted\n",
-+                              devname);
-+                      free(first_super);
-+                      return 1;
-+              }
-+
-+              if (st == NULL)
-+                      st = tst;
-+              if (st->ss != tst->ss ||
-+                  st->minor_version != tst->minor_version ||
-+                  st->ss->compare_super(&first_super, super) != 0) {
-+                      /* Some mismatch. If exactly one array matches this host,
-+                       * we can resolve on that one.
-+                       * Or, if we are auto assembling, we just ignore the second
-+                       * for now.
-+                       */
-+                      if (mdfd < 0)
-+                              continue;
-+                      if (homehost) {
-+                              int first = st->ss->match_home(first_super, homehost);
-+                              int last = tst->ss->match_home(super, homehost);
-+                              if (first+last == 1) {
-+                                      /* We can do something */
-+                                      if (first) {/* just ignore this one */
-+                                              if ((inargv && verbose >= 0) || verbose > 0)
-+                                                      fprintf(stderr, Name ": %s misses out due to wrong homehost\n",
-+                                                              devname);
-+                                              continue;
-+                                      } else { /* reject all those sofar */
-+                                              mddev_dev_t td;
-+                                              if ((inargv && verbose >= 0) || verbose > 0)
-+                                                      fprintf(stderr, Name ": %s overrides previous devices due to good homehost\n",
-+                                                              devname);
-+                                              for (td=devlist; td != tmpdev; td=td->next)
-+                                                      if (td->used == 1)
-+                                                              td->used = 0;
-+                                              tmpdev->used = 1;
-+                                              continue;
-+                                      }
-+                              }
-+                      }
-+                      fprintf(stderr, Name ": superblock on %s doesn't match others - assembly aborted\n",
-+                              devname);
-+                      free(super);
-+                      free(first_super);
-+                      return 1;
-+              }
-+
-+              tmpdev->used = 1;
-+      }
-+
-+      /* Ok, no bad inconsistancy, we can try updating etc */
-+      bitmap_done = 0;
-+      for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) if (tmpdev->used == 1) {
-+              char *devname = tmpdev->devname;
-+              struct stat stb;
-+              /* looks like a good enough match to update the super block if needed */
-+              {
-+                      int dfd;
-+                      dfd = dev_open(devname, O_RDWR|O_EXCL);
-+
-+                      remove_partitions(dfd);
-+
-+                      if (super) {
-+                              free(super);
-+                              super = NULL;
-+                      }
-+
-+                      st->ss->load_super(st, dfd, &super, NULL);
-+                      st->ss->getinfo_super(&info, super);
-+                      close(dfd);
-+              }
-+
-+              stat(devname, &stb);
-+
-+              if (verbose > 0)
-+                      fprintf(stderr, Name ": %s is identified as a member of %s, slot %d.\n",
-+                              devname, mddev, info.disk.raid_disk);
-+              devices[devcnt].devname = devname;
-+              devices[devcnt].major = major(stb.st_rdev);
-+              devices[devcnt].minor = minor(stb.st_rdev);
-+              devices[devcnt].oldmajor = info.disk.major;
-+              devices[devcnt].oldminor = info.disk.minor;
-+              devices[devcnt].events = info.events;
-+              devices[devcnt].raid_disk = info.disk.raid_disk;
-+              devices[devcnt].disk_nr = info.disk.number;
-+              devices[devcnt].uptodate = 0;
-+              devices[devcnt].state = info.disk.state;
-+              if (most_recent < devcnt) {
-+                      if (devices[devcnt].events
-+                          > devices[most_recent].events)
-+                              most_recent = devcnt;
-+              }
-+              if (info.array.level == -4)
-+                      /* with multipath, the raid_disk from the superblock is meaningless */
-+                      i = devcnt;
-+              else
-+                      i = devices[devcnt].raid_disk;
-+              if (i+1 == 0) {
-+                      if (nextspare < info.array.raid_disks)
-+                              nextspare = info.array.raid_disks;
-+                      i = nextspare++;
-+              } else {
-+                      if (i >= info.array.raid_disks &&
-+                          i >= nextspare)
-+                              nextspare = i+1;
-+              }
-+              if (i < 10000) {
-+                      if (i >= bestcnt) {
-+                              unsigned int newbestcnt = i+10;
-+                              int *newbest = malloc(sizeof(int)*newbestcnt);
-+                              unsigned int c;
-+                              for (c=0; c < newbestcnt; c++)
-+                                      if (c < bestcnt)
-+                                              newbest[c] = best[c];
-+                                      else
-+                                              newbest[c] = -1;
-+                              if (best)free(best);
-+                              best = newbest;
-+                              bestcnt = newbestcnt;
-+                      }
-+                      if (best[i] >=0 &&
-+                          devices[best[i]].events == devices[devcnt].events &&
-+                          devices[best[i]].minor != devices[devcnt].minor &&
-+                          st->ss->major == 0 &&
-+                          info.array.level != -4) {
-+                              /* two different devices with identical superblock.
-+                               * Could be a mis-detection caused by overlapping
-+                               * partitions.  fail-safe.
-+                               */
-+                              fprintf(stderr, Name ": WARNING %s and %s appear"
-+                                      " to have very similar superblocks.\n"
-+                                      "      If they are really different, "
-+                                      "please --zero the superblock on one\n"
-+                                      "      If they are the same or overlap,"
-+                                      " please remove one from %s.\n",
-+                                      devices[best[i]].devname, devname,
-+                                      inargv ? "the list" :
-+                                         "the\n      DEVICE list in mdadm.conf"
-+                                      );
-+                              return 1;
-+                      }
-+                      if (best[i] == -1
-+                          || devices[best[i]].events < devices[devcnt].events)
-+                              best[i] = devcnt;
-+              }
-+              devcnt++;
-+      }
-+
-+      if (super)
-+              free(super);
-+      super = NULL;
-+
-+      if (update && strcmp(update, "byteorder")==0)
-+              st->minor_version = 90;
-+
-+      if (devcnt == 0) {
-+              fprintf(stderr, Name ": no devices found for %s\n",
-+                      mddev);
-+              free(first_super);
-+              return 1;
-+      }
-+
-+      st->ss->getinfo_super(&info, first_super);
-+      clean = info.array.state & 1;
-+
-+      /* now we have some devices that might be suitable.
-+       * I wonder how many
-+       */
-+      avail = malloc(info.array.raid_disks);
-+      memset(avail, 0, info.array.raid_disks);
-+      okcnt = 0;
-+      sparecnt=0;
-+      for (i=0; i< bestcnt ;i++) {
-+              int j = best[i];
-+              int event_margin = 1; /* always allow a difference of '1'
-+                                     * like the kernel does
-+                                     */
-+              if (j < 0) continue;
-+              /* note: we ignore error flags in multipath arrays
-+               * as they don't make sense
-+               */
-+              if (info.array.level != -4)
-+                      if (!(devices[j].state & (1<<MD_DISK_SYNC))) {
-+                              if (!(devices[j].state & (1<<MD_DISK_FAULTY)))
-+                                      sparecnt++;
-+                              continue;
-+                      }
-+              if (devices[j].events+event_margin >=
-+                  devices[most_recent].events) {
-+                      devices[j].uptodate = 1;
-+                      if (i < info.array.raid_disks) {
-+                              okcnt++;
-+                              avail[i]=1;
-+                      } else
-+                              sparecnt++;
-+              }
-+      }
-+      while (force && !enough(info.array.level, info.array.raid_disks,
-+                              info.array.layout, 1,
-+                              avail, okcnt)) {
-+              /* Choose the newest best drive which is
-+               * not up-to-date, update the superblock
-+               * and add it.
-+               */
-+              int fd;
-+              long long current_events;
-+              chosen_drive = -1;
-+              for (i=0; i<info.array.raid_disks && i < bestcnt; i++) {
-+                      int j = best[i];
-+                      if (j>=0 &&
-+                          !devices[j].uptodate &&
-+                          devices[j].events > 0 &&
-+                          (chosen_drive < 0 ||
-+                           devices[j].events > devices[chosen_drive].events))
-+                              chosen_drive = j;
-+              }
-+              if (chosen_drive < 0)
-+                      break;
-+              current_events = devices[chosen_drive].events;
-+      add_another:
-+              if (verbose >= 0)
-+                      fprintf(stderr, Name ": forcing event count in %s(%d) from %d upto %d\n",
-+                              devices[chosen_drive].devname, devices[chosen_drive].raid_disk,
-+                              (int)(devices[chosen_drive].events),
-+                              (int)(devices[most_recent].events));
-+              fd = dev_open(devices[chosen_drive].devname, O_RDWR|O_EXCL);
-+              if (fd < 0) {
-+                      fprintf(stderr, Name ": Couldn't open %s for write - not updating\n",
-+                              devices[chosen_drive].devname);
-+                      devices[chosen_drive].events = 0;
-+                      continue;
-+              }
-+              if (st->ss->load_super(st,fd, &super, NULL)) {
-+                      close(fd);
-+                      fprintf(stderr, Name ": RAID superblock disappeared from %s - not updating.\n",
-+                              devices[chosen_drive].devname);
-+                      devices[chosen_drive].events = 0;
-+                      continue;
-+              }
-+              info.events = devices[most_recent].events;
-+              st->ss->update_super(&info, super, "force-one",
-+                                   devices[chosen_drive].devname, verbose,
-+                                   0, NULL);
-+
-+              if (st->ss->store_super(st, fd, super)) {
-+                      close(fd);
-+                      fprintf(stderr, Name ": Could not re-write superblock on %s\n",
-+                              devices[chosen_drive].devname);
-+                      devices[chosen_drive].events = 0;
-+                      free(super);
-+                      continue;
-+              }
-+              close(fd);
-+              devices[chosen_drive].events = devices[most_recent].events;
-+              devices[chosen_drive].uptodate = 1;
-+              avail[chosen_drive] = 1;
-+              okcnt++;
-+              free(super);
-+
-+              /* If there are any other drives of the same vintage,
-+               * add them in as well.  We can't lose and we might gain
-+               */
-+              for (i=0; i<info.array.raid_disks && i < bestcnt ; i++) {
-+                      int j = best[i];
-+                      if (j >= 0 &&
-+                          !devices[j].uptodate &&
-+                          devices[j].events > 0 &&
-+                          devices[j].events == current_events) {
-+                              chosen_drive = j;
-+                              goto add_another;
-+                      }
-+              }
-+      }
-+
-+      /* Now we want to look at the superblock which the kernel will base things on
-+       * and compare the devices that we think are working with the devices that the
-+       * superblock thinks are working.
-+       * If there are differences and --force is given, then update this chosen
-+       * superblock.
-+       */
-+      chosen_drive = -1;
-+      super = NULL;
-+      for (i=0; chosen_drive < 0 && i<bestcnt; i++) {
-+              int j = best[i];
-+              int fd;
-+
-+              if (j<0)
-+                      continue;
-+              if (!devices[j].uptodate)
-+                      continue;
-+              chosen_drive = j;
-+              if ((fd=dev_open(devices[j].devname, O_RDONLY|O_EXCL))< 0) {
-+                      fprintf(stderr, Name ": Cannot open %s: %s\n",
-+                              devices[j].devname, strerror(errno));
-+                      return 1;
-+              }
-+              if (st->ss->load_super(st,fd, &super, NULL)) {
-+                      close(fd);
-+                      fprintf(stderr, Name ": RAID superblock has disappeared from %s\n",
-+                              devices[j].devname);
-+                      return 1;
-+              }
-+              close(fd);
-+      }
-+      if (super == NULL) {
-+              fprintf(stderr, Name ": No suitable drives found for %s\n", mddev);
-+              return 1;
-+      }
-+      st->ss->getinfo_super(&info, super);
-+      for (i=0; i<bestcnt; i++) {
-+              int j = best[i];
-+              unsigned int desired_state;
-+
-+              if (i < info.array.raid_disks)
-+                      desired_state = (1<<MD_DISK_ACTIVE) | (1<<MD_DISK_SYNC);
-+              else
-+                      desired_state = 0;
-+
-+              if (j<0)
-+                      continue;
-+              if (!devices[j].uptodate)
-+                      continue;
-+              info.disk.number = devices[j].disk_nr;
-+              info.disk.raid_disk = i;
-+              info.disk.state = desired_state;
-+
-+              if (devices[j].uptodate &&
-+                  st->ss->update_super(&info, super, "assemble", NULL, verbose, 0, NULL)) {
-+                      if (force) {
-+                              if (verbose >= 0)
-+                                      fprintf(stderr, Name ": "
-+                                              "clearing FAULTY flag for device %d in %s for %s\n",
-+                                              j, mddev, devices[j].devname);
-+                              change = 1;
-+                      } else {
-+                              if (verbose >= -1)
-+                                      fprintf(stderr, Name ": "
-+                                              "device %d in %s has wrong state in superblock, but %s seems ok\n",
-+                                              i, mddev, devices[j].devname);
-+                      }
-+              }
-+#if 0
-+              if (!devices[j].uptodate &&
-+                  !(super.disks[i].state & (1 << MD_DISK_FAULTY))) {
-+                      fprintf(stderr, Name ": devices %d of %s is not marked FAULTY in superblock, but cannot be found\n",
-+                              i, mddev);
-+              }
-+#endif
-+      }
-+      if (force && !clean &&
-+          !enough(info.array.level, info.array.raid_disks,
-+                  info.array.layout, clean,
-+                  avail, okcnt)) {
-+              change += st->ss->update_super(&info, super, "force-array",
-+                                      devices[chosen_drive].devname, verbose,
-+                                             0, NULL);
-+              clean = 1;
-+      }
-+
-+      if (change) {
-+              int fd;
-+              fd = dev_open(devices[chosen_drive].devname, O_RDWR|O_EXCL);
-+              if (fd < 0) {
-+                      fprintf(stderr, Name ": Could not open %s for write - cannot Assemble array.\n",
-+                              devices[chosen_drive].devname);
-+                      return 1;
-+              }
-+              if (st->ss->store_super(st, fd, super)) {
-+                      close(fd);
-+                      fprintf(stderr, Name ": Could not re-write superblock on %s\n",
-+                              devices[chosen_drive].devname);
-+                      return 1;
-+              }
-+              close(fd);
-+      }
-+
-+      /* count number of in-sync devices according to the superblock.
-+       * We must have this number to start the array without -s or -R
-+       */
-+      req_cnt = info.array.working_disks;
-+
-+      /* Almost ready to actually *do* something */
-+      if (!old_linux) {
-+              int rv;
-+              if ((vers % 100) >= 1) { /* can use different versions */
-+                      mdu_array_info_t inf;
-+                      memset(&inf, 0, sizeof(inf));
-+                      inf.major_version = st->ss->major;
-+                      inf.minor_version = st->minor_version;
-+                      rv = ioctl(mdfd, SET_ARRAY_INFO, &inf);
-+              } else
-+                      rv = ioctl(mdfd, SET_ARRAY_INFO, NULL);
-+
-+              if (rv) {
-+                      fprintf(stderr, Name ": SET_ARRAY_INFO failed for %s: %s\n",
-+                              mddev, strerror(errno));
-+                      return 1;
-+              }
-+              if (ident->bitmap_fd >= 0) {
-+                      if (ioctl(mdfd, SET_BITMAP_FILE, ident->bitmap_fd) != 0) {
-+                              fprintf(stderr, Name ": SET_BITMAP_FILE failed.\n");
-+                              return 1;
-+                      }
-+              } else if (ident->bitmap_file) {
-+                      /* From config file */
-+                      int bmfd = open(ident->bitmap_file, O_RDWR);
-+                      if (bmfd < 0) {
-+                              fprintf(stderr, Name ": Could not open bitmap file %s\n",
-+                                      ident->bitmap_file);
-+                              return 1;
-+                      }
-+                      if (ioctl(mdfd, SET_BITMAP_FILE, bmfd) != 0) {
-+                              fprintf(stderr, Name ": Failed to set bitmapfile for %s\n", mddev);
-+                              close(bmfd);
-+                              return 1;
-+                      }
-+                      close(bmfd);
-+              }
-+
-+              /* First, add the raid disks, but add the chosen one last */
-+              for (i=0; i<= bestcnt; i++) {
-+                      int j;
-+                      if (i < bestcnt) {
-+                              j = best[i];
-+                              if (j == chosen_drive)
-+                                      continue;
-+                      } else
-+                              j = chosen_drive;
-+
-+                      if (j >= 0 /* && devices[j].uptodate */) {
-+                              mdu_disk_info_t disk;
-+                              memset(&disk, 0, sizeof(disk));
-+                              disk.major = devices[j].major;
-+                              disk.minor = devices[j].minor;
-+                              if (ioctl(mdfd, ADD_NEW_DISK, &disk)!=0) {
-+                                      fprintf(stderr, Name ": failed to add %s to %s: %s\n",
-+                                              devices[j].devname,
-+                                              mddev,
-+                                              strerror(errno));
-+                                      if (i < info.array.raid_disks || i == bestcnt)
-+                                              okcnt--;
-+                                      else
-+                                              sparecnt--;
-+                              } else if (verbose > 0)
-+                                      fprintf(stderr, Name ": added %s to %s as %d\n",
-+                                              devices[j].devname, mddev, devices[j].raid_disk);
-+                      } else if (verbose > 0 && i < info.array.raid_disks)
-+                              fprintf(stderr, Name ": no uptodate device for slot %d of %s\n",
-+                                      i, mddev);
-+              }
-+              
-+              if (runstop == 1 ||
-+                  (runstop <= 0 &&
-+                   ( enough(info.array.level, info.array.raid_disks,
-+                            info.array.layout, clean, avail, okcnt) &&
-+                     (okcnt >= req_cnt || start_partial_ok)
-+                           ))) {
-+                      if (ioctl(mdfd, RUN_ARRAY, NULL)==0) {
-+                              if (verbose >= 0) {
-+                                      fprintf(stderr, Name ": %s has been started with %d drive%s",
-+                                              mddev, okcnt, okcnt==1?"":"s");
-+                                      if (okcnt < info.array.raid_disks)
-+                                              fprintf(stderr, " (out of %d)", info.array.raid_disks);
-+                                      if (sparecnt)
-+                                              fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s");
-+                                      fprintf(stderr, ".\n");
-+                              }
-+                              return 0;
-+                      }
-+                      fprintf(stderr, Name ": failed to RUN_ARRAY %s: %s\n",
-+                              mddev, strerror(errno));
-+
-+                      if (!enough(info.array.level, info.array.raid_disks,
-+                                  info.array.layout, 1, avail, okcnt))
-+                              fprintf(stderr, Name ": Not enough devices to "
-+                                      "start the array.\n");
-+                      else if (!enough(info.array.level,
-+                                       info.array.raid_disks,
-+                                       info.array.layout, clean,
-+                                       avail, okcnt))
-+                              fprintf(stderr, Name ": Not enough devices to "
-+                                      "start the array while not clean "
-+                                      "- consider --force.\n");
-+
-+                      return 1;
-+              }
-+              if (runstop == -1) {
-+                      fprintf(stderr, Name ": %s assembled from %d drive%s",
-+                              mddev, okcnt, okcnt==1?"":"s");
-+                      if (okcnt != info.array.raid_disks)
-+                              fprintf(stderr, " (out of %d)", info.array.raid_disks);
-+                      fprintf(stderr, ", but not started.\n");
-+                      return 0;
-+              }
-+              if (verbose >= -1) {
-+                      fprintf(stderr, Name ": %s assembled from %d drive%s", mddev, okcnt, okcnt==1?"":"s");
-+                      if (sparecnt)
-+                              fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s");
-+                      if (!enough(info.array.level, info.array.raid_disks,
-+                                  info.array.layout, 1, avail, okcnt))
-+                              fprintf(stderr, " - not enough to start the array.\n");
-+                      else if (!enough(info.array.level,
-+                                       info.array.raid_disks,
-+                                       info.array.layout, clean,
-+                                       avail, okcnt))
-+                              fprintf(stderr, " - not enough to start the "
-+                                      "array while not clean - consider "
-+                                      "--force.\n");
-+                      else {
-+                              if (req_cnt == info.array.raid_disks)
-+                                      fprintf(stderr, " - need all %d to start it", req_cnt);
-+                              else
-+                                      fprintf(stderr, " - need %d of %d to start", req_cnt, info.array.raid_disks);
-+                              fprintf(stderr, " (use --run to insist).\n");
-+                      }
-+              }
-+              return 1;
-+      } else {
-+              /* The "chosen_drive" is a good choice, and if necessary, the superblock has
-+               * been updated to point to the current locations of devices.
-+               * so we can just start the array
-+               */
-+              unsigned long dev;
-+              dev = makedev(devices[chosen_drive].major,
-+                          devices[chosen_drive].minor);
-+              if (ioctl(mdfd, START_ARRAY, dev)) {
-+                  fprintf(stderr, Name ": Cannot start array: %s\n",
-+                          strerror(errno));
-+              }
-+              
-+      }
-+      return 0;
-+}
-+
-+int mdfd = -1;
-+int runstop = 0;
-+int readonly = 0;
-+int verbose = 0;
-+int force = 0;
-+
-+int mdassemble_main(int argc, char **argv) {
-+      mddev_ident_t array_list =  conf_get_ident(NULL);
-+      int minor;
-+      if (!array_list) {
-+              fprintf(stderr, Name ": No arrays found in config file\n");
-+              return 1;
-+      } else {
-+              for (; array_list; array_list = array_list->next) {
-+                      mdu_array_info_t array;
-+                      if (!strncmp("/dev/md", array_list->devname, 7)) {
-+                              errno = 0;
-+                              minor = strtoul(array_list->devname + 7, NULL, 0);
-+                              if (!errno) {
-+                                      mknod(array_list->devname, S_IFBLK|0600, makedev(MD_MAJOR, minor));
-+                              }
-+                      }
-+                      mdfd = open_mddev(array_list->devname, array_list->autof);
-+                      if (mdfd < 0) {
-+
-+                              fprintf(stderr, Name ": failed to open array\n");
-+                              continue;
-+                      }
-+                      if (ioctl(mdfd, GET_ARRAY_INFO, &array) < 0) {
-+                              Assemble(array_list->st, array_list->devname, mdfd,
-+                                         array_list, NULL, NULL,
-+                                         readonly, runstop, NULL, NULL, verbose, force);
-+                      }
-+                      close(mdfd);
-+              }
-+      }
-+      return 0;
-+}
-+
---- a/mdadm/mdexamine.c        1970-01-01 03:00:00.000000000 +0300
-+++ mdadm/mdadm/mdexamine.c    2011-01-12 21:33:01.000000000 +0200
-@@ -0,0 +1,157 @@
-+/*
-+ * mdadm - manage Linux "md" devices aka RAID arrays.
-+ *
-+ * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
-+ *
-+ *
-+ *    This program is free software; you can redistribute it and/or modify
-+ *    it under the terms of the GNU General Public License as published by
-+ *    the Free Software Foundation; either version 2 of the License, or
-+ *    (at your option) any later version.
-+ *
-+ *    This program is distributed in the hope that it will be useful,
-+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *    GNU General Public License for more details.
-+ *
-+ *    You should have received a copy of the GNU General Public License
-+ *    along with this program; if not, write to the Free Software
-+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ *
-+ *    Author: Neil Brown
-+ *    Email: <neilb@cse.unsw.edu.au>
-+ *    Paper: Neil Brown
-+ *           School of Computer Science and Engineering
-+ *           The University of New South Wales
-+ *           Sydney, 2052
-+ *           Australia
-+ */
-+
-+#include      "mdadm.h"
-+#include      "dlink.h"
-+
-+#if ! defined(__BIG_ENDIAN) && ! defined(__LITTLE_ENDIAN)
-+#error no endian defined
-+#endif
-+#include      "md_u.h"
-+#include      "md_p.h"
-+
-+static int Examine(mddev_dev_t devlist, int brief, int scan,
-+          int SparcAdjust, struct supertype *forcest,
-+          char *homehost)
-+{
-+
-+      /* Read the raid superblock from a device and
-+       * display important content.
-+       *
-+       * If cannot be found, print reason: too small, bad magic
-+       *
-+       * Print:
-+       *   version, ctime, level, size, raid+spare+
-+       *   prefered minor
-+       *   uuid
-+       *
-+       *   utime, state etc
-+       *
-+       * If (brief) gather devices for same array and just print a mdadm.conf line including devices=
-+       * if devlist==NULL, use conf_get_devs()
-+       */
-+      int fd; 
-+      void *super = NULL;
-+      int rv = 0;
-+      int err = 0;
-+
-+      struct array {
-+              void *super;
-+              struct supertype *st;
-+              struct mdinfo info;
-+              void *devs;
-+              struct array *next;
-+              int spares;
-+      } *arrays = NULL;
-+
-+      for (; devlist ; devlist=devlist->next) {
-+              struct supertype *st = forcest;
-+
-+              fd = dev_open(devlist->devname, O_RDONLY);
-+              if (fd < 0) {
-+                      if (!scan) {
-+                              fprintf(stderr,Name ": cannot open %s: %s\n",
-+                                      devlist->devname, strerror(errno));
-+                              rv = 1;
-+                      }
-+                      err = 1;
-+              }
-+              else {
-+                      if (!st)
-+                              st = guess_super(fd);
-+                      if (st)
-+                              err = st->ss->load_super(st, fd, &super, (brief||scan)?NULL:devlist->devname);
-+                      else {
-+                              if (!brief) {
-+                                      fprintf(stderr, Name ": No md superblock detected on %s.\n", devlist->devname);
-+                                      rv = 1;
-+                              }
-+                              err = 1;
-+                      }
-+                      close(fd);
-+              }
-+              if (err)
-+                      continue;
-+
-+              if (SparcAdjust)
-+                      st->ss->update_super(NULL, super, "sparc2.2", devlist->devname, 0, 0, NULL);
-+              /* Ok, its good enough to try, though the checksum could be wrong */
-+              if (brief) {
-+                      struct array *ap;
-+                      char *d;
-+                      for (ap=arrays; ap; ap=ap->next) {
-+                              if (st->ss == ap->st->ss && st->ss->compare_super(&ap->super, super)==0)
-+                                      break;
-+                      }
-+                      if (!ap) {
-+                              ap = malloc(sizeof(*ap));
-+                              ap->super = super;
-+                              ap->devs = dl_head();
-+                              ap->next = arrays;
-+                              ap->spares = 0;
-+                              ap->st = st;
-+                              arrays = ap;
-+                              st->ss->getinfo_super(&ap->info, super);
-+                      } else {
-+                              st->ss->getinfo_super(&ap->info, super);
-+                              free(super);
-+                      }
-+                      if (!(ap->info.disk.state & MD_DISK_SYNC))
-+                              ap->spares++;
-+                      d = dl_strdup(devlist->devname);
-+                      dl_add(ap->devs, d);
-+              }
-+      }
-+      if (brief) {
-+              struct array *ap;
-+              for (ap=arrays; ap; ap=ap->next) {
-+                      char sep='=';
-+                      char *d;
-+                      ap->st->ss->brief_examine_super(ap->super);
-+                      if (ap->spares) printf("   spares=%d", ap->spares);
-+                      if (brief > 1) {
-+                              printf("   devices");
-+                              for (d=dl_next(ap->devs); d!= ap->devs; d=dl_next(d)) {
-+                                      printf("%c%s", sep, d);
-+                                      sep=',';
-+                              }
-+                      }
-+                      free(ap->super);
-+                      /* FIXME free ap */
-+                      if (ap->spares || brief > 1)
-+                              printf("\n");
-+              }
-+      }
-+      return rv;
-+}
-+
-+int mdexamine_main(int argc, char **argv) {
-+      return Examine(conf_get_devs(), 1, 0, 0, NULL, NULL);
-+}
-+
---- a/mdadm/md_p.h     1970-01-01 03:00:00.000000000 +0300
-+++ mdadm/mdadm/md_p.h 2011-01-12 21:33:01.000000000 +0200
-@@ -0,0 +1,194 @@
-+/*
-+   md_p.h : physical layout of Linux RAID devices
-+          Copyright (C) 1996-98 Ingo Molnar, Gadi Oxman
-+        
-+   This program is free software; you can redistribute it and/or modify
-+   it under the terms of the GNU General Public License as published by
-+   the Free Software Foundation; either version 2, or (at your option)
-+   any later version.
-+   
-+   You should have received a copy of the GNU General Public License
-+   (for example /usr/src/linux/COPYING); if not, write to the Free
-+   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
-+*/
-+
-+#ifndef _MD_P_H
-+#define _MD_P_H
-+
-+/*
-+ * RAID superblock.
-+ *
-+ * The RAID superblock maintains some statistics on each RAID configuration.
-+ * Each real device in the RAID set contains it near the end of the device.
-+ * Some of the ideas are copied from the ext2fs implementation.
-+ *
-+ * We currently use 4096 bytes as follows:
-+ *
-+ *    word offset     function
-+ *
-+ *       0  -    31   Constant generic RAID device information.
-+ *        32  -    63   Generic state information.
-+ *      64  -   127   Personality specific information.
-+ *     128  -   511   12 32-words descriptors of the disks in the raid set.
-+ *     512  -   911   Reserved.
-+ *     912  -  1023   Disk specific descriptor.
-+ */
-+
-+/*
-+ * If x is the real device size in bytes, we return an apparent size of:
-+ *
-+ *    y = (x & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES
-+ *
-+ * and place the 4kB superblock at offset y.
-+ */
-+#define MD_RESERVED_BYTES             (64 * 1024)
-+#define MD_RESERVED_SECTORS           (MD_RESERVED_BYTES / 512)
-+#define MD_RESERVED_BLOCKS            (MD_RESERVED_BYTES / BLOCK_SIZE)
-+
-+#define MD_NEW_SIZE_SECTORS(x)                ((x & ~(MD_RESERVED_SECTORS - 1)) - MD_RESERVED_SECTORS)
-+#define MD_NEW_SIZE_BLOCKS(x)         ((x & ~(MD_RESERVED_BLOCKS - 1)) - MD_RESERVED_BLOCKS)
-+
-+#define MD_SB_BYTES                   4096
-+#define MD_SB_WORDS                   (MD_SB_BYTES / 4)
-+#define MD_SB_BLOCKS                  (MD_SB_BYTES / BLOCK_SIZE)
-+#define MD_SB_SECTORS                 (MD_SB_BYTES / 512)
-+
-+/*
-+ * The following are counted in 32-bit words
-+ */
-+#define       MD_SB_GENERIC_OFFSET            0
-+#define MD_SB_PERSONALITY_OFFSET      64
-+#define MD_SB_DISKS_OFFSET            128
-+#define MD_SB_DESCRIPTOR_OFFSET               992
-+
-+#define MD_SB_GENERIC_CONSTANT_WORDS  32
-+#define MD_SB_GENERIC_STATE_WORDS     32
-+#define MD_SB_GENERIC_WORDS           (MD_SB_GENERIC_CONSTANT_WORDS + MD_SB_GENERIC_STATE_WORDS)
-+#define MD_SB_PERSONALITY_WORDS               64
-+#define MD_SB_DESCRIPTOR_WORDS                32
-+#define MD_SB_DISKS                   27
-+#define MD_SB_DISKS_WORDS             (MD_SB_DISKS*MD_SB_DESCRIPTOR_WORDS)
-+#define MD_SB_RESERVED_WORDS          (1024 - MD_SB_GENERIC_WORDS - MD_SB_PERSONALITY_WORDS - MD_SB_DISKS_WORDS - MD_SB_DESCRIPTOR_WORDS)
-+#define MD_SB_EQUAL_WORDS             (MD_SB_GENERIC_WORDS + MD_SB_PERSONALITY_WORDS + MD_SB_DISKS_WORDS)
-+
-+/*
-+ * Device "operational" state bits
-+ */
-+#define MD_DISK_FAULTY                0 /* disk is faulty / operational */
-+#define MD_DISK_ACTIVE                1 /* disk is running or spare disk */
-+#define MD_DISK_SYNC          2 /* disk is in sync with the raid set */
-+#define MD_DISK_REMOVED               3 /* disk is in sync with the raid set */
-+
-+#define       MD_DISK_WRITEMOSTLY     9 /* disk is "write-mostly" is RAID1 config.
-+                                 * read requests will only be sent here in 
-+                                 * dire need
-+                                 */
-+
-+typedef struct mdp_device_descriptor_s {
-+      __u32 number;           /* 0 Device number in the entire set          */
-+      __u32 major;            /* 1 Device major number                      */
-+      __u32 minor;            /* 2 Device minor number                      */
-+      __u32 raid_disk;        /* 3 The role of the device in the raid set   */
-+      __u32 state;            /* 4 Operational state                        */
-+      __u32 reserved[MD_SB_DESCRIPTOR_WORDS - 5];
-+} mdp_disk_t;
-+
-+#define MD_SB_MAGIC           0xa92b4efc
-+
-+/*
-+ * Superblock state bits
-+ */
-+#define MD_SB_CLEAN           0
-+#define MD_SB_ERRORS          1
-+
-+#define       MD_SB_BITMAP_PRESENT    8 /* bitmap may be present nearby */
-+
-+typedef struct mdp_superblock_s {
-+      /*
-+       * Constant generic information
-+       */
-+      __u32 md_magic;         /*  0 MD identifier                           */
-+      __u32 major_version;    /*  1 major version to which the set conforms */
-+      __u32 minor_version;    /*  2 minor version ...                       */
-+      __u32 patch_version;    /*  3 patchlevel version ...                  */
-+      __u32 gvalid_words;     /*  4 Number of used words in this section    */
-+      __u32 set_uuid0;        /*  5 Raid set identifier                     */
-+      __u32 ctime;            /*  6 Creation time                           */
-+      __u32 level;            /*  7 Raid personality                        */
-+      __u32 size;             /*  8 Apparent size of each individual disk   */
-+      __u32 nr_disks;         /*  9 total disks in the raid set             */
-+      __u32 raid_disks;       /* 10 disks in a fully functional raid set    */
-+      __u32 md_minor;         /* 11 preferred MD minor device number        */
-+      __u32 not_persistent;   /* 12 does it have a persistent superblock    */
-+      __u32 set_uuid1;        /* 13 Raid set identifier #2                  */
-+      __u32 set_uuid2;        /* 14 Raid set identifier #3                  */
-+      __u32 set_uuid3;        /* 15 Raid set identifier #4                  */
-+      __u32 gstate_creserved[MD_SB_GENERIC_CONSTANT_WORDS - 16];
-+
-+      /*
-+       * Generic state information
-+       */
-+      __u32 utime;            /*  0 Superblock update time                  */
-+      __u32 state;            /*  1 State bits (clean, ...)                 */
-+      __u32 active_disks;     /*  2 Number of currently active disks        */
-+      __u32 working_disks;    /*  3 Number of working disks                 */
-+      __u32 failed_disks;     /*  4 Number of failed disks                  */
-+      __u32 spare_disks;      /*  5 Number of spare disks                   */
-+      __u32 sb_csum;          /*  6 checksum of the whole superblock        */
-+#if  __BYTE_ORDER ==  __BIG_ENDIAN
-+      __u32 events_hi;        /*  7 high-order of superblock update count   */
-+      __u32 events_lo;        /*  8 low-order of superblock update count    */
-+      __u32 cp_events_hi;     /*  9 high-order of checkpoint update count   */
-+      __u32 cp_events_lo;     /* 10 low-order of checkpoint update count    */
-+#else
-+      __u32 events_lo;        /*  7 low-order of superblock update count    */
-+      __u32 events_hi;        /*  8 high-order of superblock update count   */
-+      __u32 cp_events_lo;     /*  9 low-order of checkpoint update count    */
-+      __u32 cp_events_hi;     /* 10 high-order of checkpoint update count   */
-+#endif
-+      __u32 recovery_cp;      /* 11 recovery checkpoint sector count        */
-+      /* There are only valid for minor_version > 90 */
-+      __u64 reshape_position; /* 12,13 next address in array-space for reshape */
-+      __u32 new_level;        /* 14 new level we are reshaping to           */
-+      __u32 delta_disks;      /* 15 change in number of raid_disks          */
-+      __u32 new_layout;       /* 16 new layout                              */
-+      __u32 new_chunk;        /* 17 new chunk size (bytes)                  */
-+      __u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 18];
-+
-+      /*
-+       * Personality information
-+       */
-+      __u32 layout;           /*  0 the array's physical layout             */
-+      __u32 chunk_size;       /*  1 chunk size in bytes                     */
-+      __u32 root_pv;          /*  2 LV root PV */
-+      __u32 root_block;       /*  3 LV root block */
-+      __u32 pstate_reserved[MD_SB_PERSONALITY_WORDS - 4];
-+
-+      /*
-+       * Disks information
-+       */
-+      mdp_disk_t disks[MD_SB_DISKS];
-+
-+      /*
-+       * Reserved
-+       */
-+      __u32 reserved[MD_SB_RESERVED_WORDS];
-+
-+      /*
-+       * Active descriptor
-+       */
-+      mdp_disk_t this_disk;
-+
-+} mdp_super_t;
-+
-+#ifdef __TINYC__
-+typedef unsigned long long __u64;
-+#endif
-+
-+static inline __u64 md_event(mdp_super_t *sb) {
-+      __u64 ev = sb->events_hi;
-+      return (ev<<32)| sb->events_lo;
-+}
-+
-+#endif 
-+
---- a/mdadm/md_u.h     1970-01-01 03:00:00.000000000 +0300
-+++ mdadm/mdadm/md_u.h 2011-01-12 21:33:01.000000000 +0200
-@@ -0,0 +1,123 @@
-+/*
-+   md_u.h : user <=> kernel API between Linux raidtools and RAID drivers
-+          Copyright (C) 1998 Ingo Molnar
-+        
-+   This program is free software; you can redistribute it and/or modify
-+   it under the terms of the GNU General Public License as published by
-+   the Free Software Foundation; either version 2, or (at your option)
-+   any later version.
-+   
-+   You should have received a copy of the GNU General Public License
-+   (for example /usr/src/linux/COPYING); if not, write to the Free
-+   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
-+*/
-+
-+#ifndef _MD_U_H
-+#define _MD_U_H
-+
-+/* ioctls */
-+
-+/* status */
-+#define RAID_VERSION          _IOR (MD_MAJOR, 0x10, mdu_version_t)
-+#define GET_ARRAY_INFO                _IOR (MD_MAJOR, 0x11, mdu_array_info_t)
-+#define GET_DISK_INFO         _IOR (MD_MAJOR, 0x12, mdu_disk_info_t)
-+#define PRINT_RAID_DEBUG      _IO (MD_MAJOR, 0x13)
-+#define RAID_AUTORUN          _IO (MD_MAJOR, 0x14)
-+#define GET_BITMAP_FILE               _IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t)
-+
-+/* configuration */
-+#define CLEAR_ARRAY           _IO (MD_MAJOR, 0x20)
-+#define ADD_NEW_DISK          _IOW (MD_MAJOR, 0x21, mdu_disk_info_t)
-+#define HOT_REMOVE_DISK               _IO (MD_MAJOR, 0x22)
-+#define SET_ARRAY_INFO                _IOW (MD_MAJOR, 0x23, mdu_array_info_t)
-+#define SET_DISK_INFO         _IO (MD_MAJOR, 0x24)
-+#define WRITE_RAID_INFO               _IO (MD_MAJOR, 0x25)
-+#define UNPROTECT_ARRAY               _IO (MD_MAJOR, 0x26)
-+#define PROTECT_ARRAY         _IO (MD_MAJOR, 0x27)
-+#define HOT_ADD_DISK          _IO (MD_MAJOR, 0x28)
-+#define SET_DISK_FAULTY               _IO (MD_MAJOR, 0x29)
-+#define SET_BITMAP_FILE               _IOW (MD_MAJOR, 0x2b, int)
-+
-+/* usage */
-+#define RUN_ARRAY             _IOW (MD_MAJOR, 0x30, mdu_param_t)
-+#define START_ARRAY           _IO (MD_MAJOR, 0x31)
-+#define STOP_ARRAY            _IO (MD_MAJOR, 0x32)
-+#define STOP_ARRAY_RO         _IO (MD_MAJOR, 0x33)
-+#define RESTART_ARRAY_RW      _IO (MD_MAJOR, 0x34)
-+
-+typedef struct mdu_version_s {
-+      int major;
-+      int minor;
-+      int patchlevel;
-+} mdu_version_t;
-+
-+typedef struct mdu_array_info_s {
-+      /*
-+       * Generic constant information
-+       */
-+      int major_version;
-+      int minor_version;
-+      int patch_version;
-+      int ctime;
-+      int level;
-+      int size;
-+      int nr_disks;
-+      int raid_disks;
-+      int md_minor;
-+      int not_persistent;
-+
-+      /*
-+       * Generic state information
-+       */
-+      int utime;              /*  0 Superblock update time                  */
-+      int state;              /*  1 State bits (clean, ...)                 */
-+      int active_disks;       /*  2 Number of currently active disks        */
-+      int working_disks;      /*  3 Number of working disks                 */
-+      int failed_disks;       /*  4 Number of failed disks                  */
-+      int spare_disks;        /*  5 Number of spare disks                   */
-+
-+      /*
-+       * Personality information
-+       */
-+      int layout;             /*  0 the array's physical layout             */
-+      int chunk_size; /*  1 chunk size in bytes                     */
-+
-+} mdu_array_info_t;
-+
-+typedef struct mdu_disk_info_s {
-+      /*
-+       * configuration/status of one particular disk
-+       */
-+      int number;
-+      int major;
-+      int minor;
-+      int raid_disk;
-+      int state;
-+
-+} mdu_disk_info_t;
-+
-+typedef struct mdu_start_info_s {
-+      /*
-+       * configuration/status of one particular disk
-+       */
-+      int major;
-+      int minor;
-+      int raid_disk;
-+      int state;
-+
-+} mdu_start_info_t;
-+
-+typedef struct mdu_bitmap_file_s
-+{
-+      char pathname[4096];
-+} mdu_bitmap_file_t;
-+
-+typedef struct mdu_param_s
-+{
-+      int                     personality;    /* 1,2,3,4 */
-+      int                     chunk_size;     /* in bytes */
-+      int                     max_fault;      /* unused for now */
-+} mdu_param_t;
-+
-+#endif 
-+
---- a/mdadm/sha1.c     1970-01-01 03:00:00.000000000 +0300
-+++ mdadm/mdadm/sha1.c 2011-01-12 21:33:01.000000000 +0200
-@@ -0,0 +1,423 @@
-+/* sha1.c - Functions to compute SHA1 message digest of files or
-+   memory blocks according to the NIST specification FIPS-180-1.
-+
-+   Copyright (C) 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
-+
-+   This program is free software; you can redistribute it and/or modify it
-+   under the terms of the GNU General Public License as published by the
-+   Free Software Foundation; either version 2, or (at your option) any
-+   later version.
-+
-+   This program is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+   GNU General Public License for more details.
-+
-+   You should have received a copy of the GNU General Public License
-+   along with this program; if not, write to the Free Software Foundation,
-+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
-+
-+/* Written by Scott G. Miller
-+   Credits:
-+      Robert Klep <robert@ilse.nl>  -- Expansion function fix
-+*/
-+
-+#ifdef HAVE_CONFIG_H
-+# include <config.h>
-+#endif
-+
-+#include "sha1.h"
-+
-+#include <stddef.h>
-+#include <string.h>
-+
-+#if USE_UNLOCKED_IO
-+# include "unlocked-io.h"
-+#endif
-+
-+/* SWAP does an endian swap on architectures that are little-endian,
-+   as SHA1 needs some data in a big-endian form.  */
-+
-+#ifdef WORDS_BIGENDIAN
-+# define SWAP(n) (n)
-+#else
-+# define SWAP(n) \
-+    (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
-+#endif
-+
-+#define BLOCKSIZE 4096
-+#if BLOCKSIZE % 64 != 0
-+# error "invalid BLOCKSIZE"
-+#endif
-+
-+/* This array contains the bytes used to pad the buffer to the next
-+   64-byte boundary.  (RFC 1321, 3.1: Step 1)  */
-+static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ...  */ };
-+
-+
-+/*
-+  Takes a pointer to a 160 bit block of data (five 32 bit ints) and
-+  intializes it to the start constants of the SHA1 algorithm.  This
-+  must be called before using hash in the call to sha1_hash.
-+*/
-+void
-+sha1_init_ctx (struct sha1_ctx *ctx)
-+{
-+  ctx->A = 0x67452301;
-+  ctx->B = 0xefcdab89;
-+  ctx->C = 0x98badcfe;
-+  ctx->D = 0x10325476;
-+  ctx->E = 0xc3d2e1f0;
-+
-+  ctx->total[0] = ctx->total[1] = 0;
-+  ctx->buflen = 0;
-+}
-+
-+/* Put result from CTX in first 20 bytes following RESBUF.  The result
-+   must be in little endian byte order.
-+
-+   IMPORTANT: On some systems it is required that RESBUF is correctly
-+   aligned for a 32 bits value.  */
-+void *
-+sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf)
-+{
-+  ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
-+  ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
-+  ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
-+  ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
-+  ((md5_uint32 *) resbuf)[4] = SWAP (ctx->E);
-+
-+  return resbuf;
-+}
-+
-+/* Process the remaining bytes in the internal buffer and the usual
-+   prolog according to the standard and write the result to RESBUF.
-+
-+   IMPORTANT: On some systems it is required that RESBUF is correctly
-+   aligned for a 32 bits value.  */
-+void *
-+sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf)
-+{
-+  /* Take yet unprocessed bytes into account.  */
-+  md5_uint32 bytes = ctx->buflen;
-+  size_t pad;
-+
-+  /* Now count remaining bytes.  */
-+  ctx->total[0] += bytes;
-+  if (ctx->total[0] < bytes)
-+    ++ctx->total[1];
-+
-+  pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
-+  memcpy (&ctx->buffer[bytes], fillbuf, pad);
-+
-+  /* Put the 64-bit file length in *bits* at the end of the buffer.  */
-+  *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP (ctx->total[0] << 3);
-+  *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP ((ctx->total[1] << 3) |
-+                                                  (ctx->total[0] >> 29));
-+
-+  /* Process last bytes.  */
-+  sha1_process_block (ctx->buffer, bytes + pad + 8, ctx);
-+
-+  return sha1_read_ctx (ctx, resbuf);
-+}
-+
-+/* Compute SHA1 message digest for bytes read from STREAM.  The
-+   resulting message digest number will be written into the 16 bytes
-+   beginning at RESBLOCK.  */
-+int
-+sha1_stream (FILE *stream, void *resblock)
-+{
-+  struct sha1_ctx ctx;
-+  char buffer[BLOCKSIZE + 72];
-+  size_t sum;
-+
-+  /* Initialize the computation context.  */
-+  sha1_init_ctx (&ctx);
-+
-+  /* Iterate over full file contents.  */
-+  while (1)
-+    {
-+      /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
-+       computation function processes the whole buffer so that with the
-+       next round of the loop another block can be read.  */
-+      size_t n;
-+      sum = 0;
-+
-+      /* Read block.  Take care for partial reads.  */
-+      while (1)
-+      {
-+        n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
-+
-+        sum += n;
-+
-+        if (sum == BLOCKSIZE)
-+          break;
-+
-+        if (n == 0)
-+          {
-+            /* Check for the error flag IFF N == 0, so that we don't
-+               exit the loop after a partial read due to e.g., EAGAIN
-+               or EWOULDBLOCK.  */
-+            if (ferror (stream))
-+              return 1;
-+            goto process_partial_block;
-+          }
-+
-+        /* We've read at least one byte, so ignore errors.  But always
-+           check for EOF, since feof may be true even though N > 0.
-+           Otherwise, we could end up calling fread after EOF.  */
-+        if (feof (stream))
-+          goto process_partial_block;
-+      }
-+
-+      /* Process buffer with BLOCKSIZE bytes.  Note that
-+                      BLOCKSIZE % 64 == 0
-+       */
-+      sha1_process_block (buffer, BLOCKSIZE, &ctx);
-+    }
-+
-+ process_partial_block:;
-+
-+  /* Process any remaining bytes.  */
-+  if (sum > 0)
-+    sha1_process_bytes (buffer, sum, &ctx);
-+
-+  /* Construct result in desired memory.  */
-+  sha1_finish_ctx (&ctx, resblock);
-+  return 0;
-+}
-+
-+/* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
-+   result is always in little endian byte order, so that a byte-wise
-+   output yields to the wanted ASCII representation of the message
-+   digest.  */
-+void *
-+sha1_buffer (const char *buffer, size_t len, void *resblock)
-+{
-+  struct sha1_ctx ctx;
-+
-+  /* Initialize the computation context.  */
-+  sha1_init_ctx (&ctx);
-+
-+  /* Process whole buffer but last len % 64 bytes.  */
-+  sha1_process_bytes (buffer, len, &ctx);
-+
-+  /* Put result in desired memory area.  */
-+  return sha1_finish_ctx (&ctx, resblock);
-+}
-+
-+void
-+sha1_process_bytes (const void *buffer, size_t len, struct sha1_ctx *ctx)
-+{
-+  /* When we already have some bits in our internal buffer concatenate
-+     both inputs first.  */
-+  if (ctx->buflen != 0)
-+    {
-+      size_t left_over = ctx->buflen;
-+      size_t add = 128 - left_over > len ? len : 128 - left_over;
-+
-+      memcpy (&ctx->buffer[left_over], buffer, add);
-+      ctx->buflen += add;
-+
-+      if (ctx->buflen > 64)
-+      {
-+        sha1_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
-+
-+        ctx->buflen &= 63;
-+        /* The regions in the following copy operation cannot overlap.  */
-+        memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
-+                ctx->buflen);
-+      }
-+
-+      buffer = (const char *) buffer + add;
-+      len -= add;
-+    }
-+
-+  /* Process available complete blocks.  */
-+  if (len >= 64)
-+    {
-+#if !_STRING_ARCH_unaligned
-+# define alignof(type) offsetof (struct { char c; type x; }, x)
-+# define UNALIGNED_P(p) (((size_t) p) % alignof (md5_uint32) != 0)
-+      if (UNALIGNED_P (buffer))
-+      while (len > 64)
-+        {
-+          sha1_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx);
-+          buffer = (const char *) buffer + 64;
-+          len -= 64;
-+        }
-+      else
-+#endif
-+      {
-+        sha1_process_block (buffer, len & ~63, ctx);
-+        buffer = (const char *) buffer + (len & ~63);
-+        len &= 63;
-+      }
-+    }
-+
-+  /* Move remaining bytes in internal buffer.  */
-+  if (len > 0)
-+    {
-+      size_t left_over = ctx->buflen;
-+
-+      memcpy (&ctx->buffer[left_over], buffer, len);
-+      left_over += len;
-+      if (left_over >= 64)
-+      {
-+        sha1_process_block (ctx->buffer, 64, ctx);
-+        left_over -= 64;
-+        memcpy (ctx->buffer, &ctx->buffer[64], left_over);
-+      }
-+      ctx->buflen = left_over;
-+    }
-+}
-+
-+/* --- Code below is the primary difference between md5.c and sha1.c --- */
-+
-+/* SHA1 round constants */
-+#define K1 0x5a827999L
-+#define K2 0x6ed9eba1L
-+#define K3 0x8f1bbcdcL
-+#define K4 0xca62c1d6L
-+
-+/* Round functions.  Note that F2 is the same as F4.  */
-+#define F1(B,C,D) ( D ^ ( B & ( C ^ D ) ) )
-+#define F2(B,C,D) (B ^ C ^ D)
-+#define F3(B,C,D) ( ( B & C ) | ( D & ( B | C ) ) )
-+#define F4(B,C,D) (B ^ C ^ D)
-+
-+/* Process LEN bytes of BUFFER, accumulating context into CTX.
-+   It is assumed that LEN % 64 == 0.
-+   Most of this code comes from GnuPG's cipher/sha1.c.  */
-+
-+void
-+sha1_process_block (const void *buffer, size_t len, struct sha1_ctx *ctx)
-+{
-+  const md5_uint32 *words = buffer;
-+  size_t nwords = len / sizeof (md5_uint32);
-+  const md5_uint32 *endp = words + nwords;
-+  md5_uint32 x[16];
-+  md5_uint32 a = ctx->A;
-+  md5_uint32 b = ctx->B;
-+  md5_uint32 c = ctx->C;
-+  md5_uint32 d = ctx->D;
-+  md5_uint32 e = ctx->E;
-+
-+  /* First increment the byte count.  RFC 1321 specifies the possible
-+     length of the file up to 2^64 bits.  Here we only compute the
-+     number of bytes.  Do a double word increment.  */
-+  ctx->total[0] += len;
-+  if (ctx->total[0] < len)
-+    ++ctx->total[1];
-+
-+#define rol(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
-+
-+#define M(I) ( tm =   x[I&0x0f] ^ x[(I-14)&0x0f] \
-+                  ^ x[(I-8)&0x0f] ^ x[(I-3)&0x0f] \
-+             , (x[I&0x0f] = rol(tm, 1)) )
-+
-+#define R(A,B,C,D,E,F,K,M)  do { E += rol( A, 5 )     \
-+                                    + F( B, C, D )  \
-+                                    + K             \
-+                                    + M;            \
-+                               B = rol( B, 30 );    \
-+                             } while(0)
-+
-+  while (words < endp)
-+    {
-+      md5_uint32 tm;
-+      int t;
-+      for (t = 0; t < 16; t++)
-+      {
-+        x[t] = SWAP (*words);
-+        words++;
-+      }
-+
-+      R( a, b, c, d, e, F1, K1, x[ 0] );
-+      R( e, a, b, c, d, F1, K1, x[ 1] );
-+      R( d, e, a, b, c, F1, K1, x[ 2] );
-+      R( c, d, e, a, b, F1, K1, x[ 3] );
-+      R( b, c, d, e, a, F1, K1, x[ 4] );
-+      R( a, b, c, d, e, F1, K1, x[ 5] );
-+      R( e, a, b, c, d, F1, K1, x[ 6] );
-+      R( d, e, a, b, c, F1, K1, x[ 7] );
-+      R( c, d, e, a, b, F1, K1, x[ 8] );
-+      R( b, c, d, e, a, F1, K1, x[ 9] );
-+      R( a, b, c, d, e, F1, K1, x[10] );
-+      R( e, a, b, c, d, F1, K1, x[11] );
-+      R( d, e, a, b, c, F1, K1, x[12] );
-+      R( c, d, e, a, b, F1, K1, x[13] );
-+      R( b, c, d, e, a, F1, K1, x[14] );
-+      R( a, b, c, d, e, F1, K1, x[15] );
-+      R( e, a, b, c, d, F1, K1, M(16) );
-+      R( d, e, a, b, c, F1, K1, M(17) );
-+      R( c, d, e, a, b, F1, K1, M(18) );
-+      R( b, c, d, e, a, F1, K1, M(19) );
-+      R( a, b, c, d, e, F2, K2, M(20) );
-+      R( e, a, b, c, d, F2, K2, M(21) );
-+      R( d, e, a, b, c, F2, K2, M(22) );
-+      R( c, d, e, a, b, F2, K2, M(23) );
-+      R( b, c, d, e, a, F2, K2, M(24) );
-+      R( a, b, c, d, e, F2, K2, M(25) );
-+      R( e, a, b, c, d, F2, K2, M(26) );
-+      R( d, e, a, b, c, F2, K2, M(27) );
-+      R( c, d, e, a, b, F2, K2, M(28) );
-+      R( b, c, d, e, a, F2, K2, M(29) );
-+      R( a, b, c, d, e, F2, K2, M(30) );
-+      R( e, a, b, c, d, F2, K2, M(31) );
-+      R( d, e, a, b, c, F2, K2, M(32) );
-+      R( c, d, e, a, b, F2, K2, M(33) );
-+      R( b, c, d, e, a, F2, K2, M(34) );
-+      R( a, b, c, d, e, F2, K2, M(35) );
-+      R( e, a, b, c, d, F2, K2, M(36) );
-+      R( d, e, a, b, c, F2, K2, M(37) );
-+      R( c, d, e, a, b, F2, K2, M(38) );
-+      R( b, c, d, e, a, F2, K2, M(39) );
-+      R( a, b, c, d, e, F3, K3, M(40) );
-+      R( e, a, b, c, d, F3, K3, M(41) );
-+      R( d, e, a, b, c, F3, K3, M(42) );
-+      R( c, d, e, a, b, F3, K3, M(43) );
-+      R( b, c, d, e, a, F3, K3, M(44) );
-+      R( a, b, c, d, e, F3, K3, M(45) );
-+      R( e, a, b, c, d, F3, K3, M(46) );
-+      R( d, e, a, b, c, F3, K3, M(47) );
-+      R( c, d, e, a, b, F3, K3, M(48) );
-+      R( b, c, d, e, a, F3, K3, M(49) );
-+      R( a, b, c, d, e, F3, K3, M(50) );
-+      R( e, a, b, c, d, F3, K3, M(51) );
-+      R( d, e, a, b, c, F3, K3, M(52) );
-+      R( c, d, e, a, b, F3, K3, M(53) );
-+      R( b, c, d, e, a, F3, K3, M(54) );
-+      R( a, b, c, d, e, F3, K3, M(55) );
-+      R( e, a, b, c, d, F3, K3, M(56) );
-+      R( d, e, a, b, c, F3, K3, M(57) );
-+      R( c, d, e, a, b, F3, K3, M(58) );
-+      R( b, c, d, e, a, F3, K3, M(59) );
-+      R( a, b, c, d, e, F4, K4, M(60) );
-+      R( e, a, b, c, d, F4, K4, M(61) );
-+      R( d, e, a, b, c, F4, K4, M(62) );
-+      R( c, d, e, a, b, F4, K4, M(63) );
-+      R( b, c, d, e, a, F4, K4, M(64) );
-+      R( a, b, c, d, e, F4, K4, M(65) );
-+      R( e, a, b, c, d, F4, K4, M(66) );
-+      R( d, e, a, b, c, F4, K4, M(67) );
-+      R( c, d, e, a, b, F4, K4, M(68) );
-+      R( b, c, d, e, a, F4, K4, M(69) );
-+      R( a, b, c, d, e, F4, K4, M(70) );
-+      R( e, a, b, c, d, F4, K4, M(71) );
-+      R( d, e, a, b, c, F4, K4, M(72) );
-+      R( c, d, e, a, b, F4, K4, M(73) );
-+      R( b, c, d, e, a, F4, K4, M(74) );
-+      R( a, b, c, d, e, F4, K4, M(75) );
-+      R( e, a, b, c, d, F4, K4, M(76) );
-+      R( d, e, a, b, c, F4, K4, M(77) );
-+      R( c, d, e, a, b, F4, K4, M(78) );
-+      R( b, c, d, e, a, F4, K4, M(79) );
-+
-+      a = ctx->A += a;
-+      b = ctx->B += b;
-+      c = ctx->C += c;
-+      d = ctx->D += d;
-+      e = ctx->E += e;
-+    }
-+}
---- a/mdadm/sha1.h     1970-01-01 03:00:00.000000000 +0300
-+++ mdadm/mdadm/sha1.h 2011-01-12 21:33:01.000000000 +0200
-@@ -0,0 +1,87 @@
-+/* Declarations of functions and data types used for SHA1 sum
-+   library functions.
-+   Copyright (C) 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
-+
-+   This program is free software; you can redistribute it and/or modify it
-+   under the terms of the GNU General Public License as published by the
-+   Free Software Foundation; either version 2, or (at your option) any
-+   later version.
-+
-+   This program is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+   GNU General Public License for more details.
-+
-+   You should have received a copy of the GNU General Public License
-+   along with this program; if not, write to the Free Software Foundation,
-+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
-+
-+#ifndef SHA1_H
-+# define SHA1_H 1
-+
-+# include <stdio.h>
-+# include "md5.h"
-+
-+/* Structure to save state of computation between the single steps.  */
-+struct sha1_ctx
-+{
-+  md5_uint32 A;
-+  md5_uint32 B;
-+  md5_uint32 C;
-+  md5_uint32 D;
-+  md5_uint32 E;
-+
-+  md5_uint32 total[2];
-+  md5_uint32 buflen;
-+  char buffer[128] __attribute__ ((__aligned__ (__alignof__ (md5_uint32))));
-+};
-+
-+
-+/* Initialize structure containing state of computation. */
-+extern void sha1_init_ctx (struct sha1_ctx *ctx);
-+
-+/* Starting with the result of former calls of this function (or the
-+   initialization function update the context for the next LEN bytes
-+   starting at BUFFER.
-+   It is necessary that LEN is a multiple of 64!!! */
-+extern void sha1_process_block (const void *buffer, size_t len,
-+                              struct sha1_ctx *ctx);
-+
-+/* Starting with the result of former calls of this function (or the
-+   initialization function update the context for the next LEN bytes
-+   starting at BUFFER.
-+   It is NOT required that LEN is a multiple of 64.  */
-+extern void sha1_process_bytes (const void *buffer, size_t len,
-+                              struct sha1_ctx *ctx);
-+
-+/* Process the remaining bytes in the buffer and put result from CTX
-+   in first 20 bytes following RESBUF.  The result is always in little
-+   endian byte order, so that a byte-wise output yields to the wanted
-+   ASCII representation of the message digest.
-+
-+   IMPORTANT: On some systems it is required that RESBUF be correctly
-+   aligned for a 32 bits value.  */
-+extern void *sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf);
-+
-+
-+/* Put result from CTX in first 20 bytes following RESBUF.  The result is
-+   always in little endian byte order, so that a byte-wise output yields
-+   to the wanted ASCII representation of the message digest.
-+
-+   IMPORTANT: On some systems it is required that RESBUF is correctly
-+   aligned for a 32 bits value.  */
-+extern void *sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf);
-+
-+
-+/* Compute SHA1 message digest for bytes read from STREAM.  The
-+   resulting message digest number will be written into the 20 bytes
-+   beginning at RESBLOCK.  */
-+extern int sha1_stream (FILE *stream, void *resblock);
-+
-+/* Compute SHA1 message digest for LEN bytes beginning at BUFFER.  The
-+   result is always in little endian byte order, so that a byte-wise
-+   output yields to the wanted ASCII representation of the message
-+   digest.  */
-+extern void *sha1_buffer (const char *buffer, size_t len, void *resblock);
-+
-+#endif
---- a/mdadm/super0.c   1970-01-01 03:00:00.000000000 +0300
-+++ mdadm/mdadm/super0.c       2011-01-12 21:33:01.000000000 +0200
-@@ -0,0 +1,562 @@
-+/*
-+ * mdadm - manage Linux "md" devices aka RAID arrays.
-+ *
-+ * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
-+ *
-+ *
-+ *    This program is free software; you can redistribute it and/or modify
-+ *    it under the terms of the GNU General Public License as published by
-+ *    the Free Software Foundation; either version 2 of the License, or
-+ *    (at your option) any later version.
-+ *
-+ *    This program is distributed in the hope that it will be useful,
-+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *    GNU General Public License for more details.
-+ *
-+ *    You should have received a copy of the GNU General Public License
-+ *    along with this program; if not, write to the Free Software
-+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ *
-+ *    Author: Neil Brown
-+ *    Email: <neilb@cse.unsw.edu.au>
-+ *    Paper: Neil Brown
-+ *           School of Computer Science and Engineering
-+ *           The University of New South Wales
-+ *           Sydney, 2052
-+ *           Australia
-+ */
-+
-+#define HAVE_STDINT_H 1
-+#include "mdadm.h"
-+/*
-+ * All handling for the 0.90.0 version superblock is in
-+ * this file.
-+ * This includes:
-+ *   - finding, loading, and writing the superblock.
-+ *   - initialising a new superblock
-+ *   - printing the superblock for --examine
-+ *   - printing part of the superblock for --detail
-+ * .. other stuff 
-+ */
-+
-+
-+static unsigned long calc_sb0_csum(mdp_super_t *super)
-+{
-+      unsigned long csum = super->sb_csum;
-+      unsigned long newcsum;
-+      super->sb_csum= 0 ;
-+      newcsum = calc_csum(super, MD_SB_BYTES);
-+      super->sb_csum = csum;
-+      return newcsum;
-+}
-+
-+
-+void super0_swap_endian(struct mdp_superblock_s *sb)
-+{
-+      /* as super0 superblocks are host-endian, it is sometimes
-+       * useful to be able to swap the endianness 
-+       * as (almost) everything is u32's we byte-swap every 4byte
-+       * number.
-+       * We then also have to swap the events_hi and events_lo
-+       */
-+      char *sbc = (char *)sb;
-+      __u32 t32;
-+      int i;
-+
-+      for (i=0; i < MD_SB_BYTES ; i+=4) {
-+              char t = sbc[i];
-+              sbc[i] = sbc[i+3];
-+              sbc[i+3] = t;
-+              t=sbc[i+1];
-+              sbc[i+1]=sbc[i+2];
-+              sbc[i+2]=t;
-+      }
-+      t32 = sb->events_hi;
-+      sb->events_hi = sb->events_lo;
-+      sb->events_lo = t32;
-+
-+      t32 = sb->cp_events_hi;
-+      sb->cp_events_hi = sb->cp_events_lo;
-+      sb->cp_events_lo = t32;
-+
-+}
-+
-+static void brief_examine_super0(void *sbv)
-+{
-+      mdp_super_t *sb = sbv;
-+      char *c=map_num(pers, sb->level);
-+      char devname[20];
-+
-+      sprintf(devname, "/dev/md%d", sb->md_minor);
-+
-+      printf("ARRAY %s level=%s num-devices=%d UUID=",
-+             devname,
-+             c?c:"-unknown-", sb->raid_disks);
-+      if (sb->minor_version >= 90)
-+              printf("%08x:%08x:%08x:%08x", sb->set_uuid0, sb->set_uuid1,
-+                     sb->set_uuid2, sb->set_uuid3);
-+      else
-+              printf("%08x", sb->set_uuid0);
-+      printf("\n");
-+}
-+
-+static int match_home0(void *sbv, char *homehost)
-+{
-+      mdp_super_t *sb = sbv;
-+      char buf[20];
-+      char *hash = sha1_buffer(homehost,
-+                               strlen(homehost),
-+                               buf);
-+
-+      return (memcmp(&sb->set_uuid2, hash, 8)==0);
-+}
-+
-+static void uuid_from_super0(int uuid[4], void * sbv)
-+{
-+      mdp_super_t *super = sbv;
-+      uuid[0] = super->set_uuid0;
-+      if (super->minor_version >= 90) {
-+              uuid[1] = super->set_uuid1;
-+              uuid[2] = super->set_uuid2;
-+              uuid[3] = super->set_uuid3;
-+      } else {
-+              uuid[1] = 0;
-+              uuid[2] = 0;
-+              uuid[3] = 0;
-+      }
-+}
-+
-+static void getinfo_super0(struct mdinfo *info, void *sbv)
-+{
-+      mdp_super_t *sb = sbv;
-+      int working = 0;
-+      int i;
-+
-+      info->array.major_version = sb->major_version;
-+      info->array.minor_version = sb->minor_version;
-+      info->array.patch_version = sb->patch_version;
-+      info->array.raid_disks = sb->raid_disks;
-+      info->array.level = sb->level;
-+      info->array.layout = sb->layout;
-+      info->array.md_minor = sb->md_minor;
-+      info->array.ctime = sb->ctime;
-+      info->array.utime = sb->utime;
-+      info->array.chunk_size = sb->chunk_size;
-+      info->array.state = sb->state;
-+      info->component_size = sb->size*2;
-+
-+      info->disk.state = sb->this_disk.state;
-+      info->disk.major = sb->this_disk.major;
-+      info->disk.minor = sb->this_disk.minor;
-+      info->disk.raid_disk = sb->this_disk.raid_disk;
-+      info->disk.number = sb->this_disk.number;
-+
-+      info->events = md_event(sb);
-+      info->data_offset = 0;
-+
-+      uuid_from_super0(info->uuid, sbv);
-+
-+      if (sb->minor_version > 90 && (sb->reshape_position+1) != 0) {
-+              info->reshape_active = 1;
-+              info->reshape_progress = sb->reshape_position;
-+              info->new_level = sb->new_level;
-+              info->delta_disks = sb->delta_disks;
-+              info->new_layout = sb->new_layout;
-+              info->new_chunk = sb->new_chunk;
-+      } else
-+              info->reshape_active = 0;
-+
-+      sprintf(info->name, "%d", sb->md_minor);
-+      /* work_disks is calculated rather than read directly */
-+      for (i=0; i < MD_SB_DISKS; i++)
-+              if ((sb->disks[i].state & (1<<MD_DISK_SYNC)) &&
-+                  (sb->disks[i].raid_disk < info->array.raid_disks) &&
-+                  (sb->disks[i].state & (1<<MD_DISK_ACTIVE)) &&
-+                  !(sb->disks[i].state & (1<<MD_DISK_FAULTY)))
-+                      working ++;
-+      info->array.working_disks = working;
-+}
-+
-+
-+static int update_super0(struct mdinfo *info, void *sbv, char *update,
-+                       char *devname, int verbose,
-+                       int uuid_set, char *homehost)
-+{
-+      /* NOTE: for 'assemble' and 'force' we need to return non-zero if any change was made.
-+       * For others, the return value is ignored.
-+       */
-+      int rv = 0;
-+      mdp_super_t *sb = sbv;
-+      if (strcmp(update, "sparc2.2")==0 ) {
-+              /* 2.2 sparc put the events in the wrong place
-+               * So we copy the tail of the superblock
-+               * up 4 bytes before continuing
-+               */
-+              __u32 *sb32 = (__u32*)sb;
-+              memcpy(sb32+MD_SB_GENERIC_CONSTANT_WORDS+7,
-+                     sb32+MD_SB_GENERIC_CONSTANT_WORDS+7+1,
-+                     (MD_SB_WORDS - (MD_SB_GENERIC_CONSTANT_WORDS+7+1))*4);
-+              if (verbose >= 0)
-+                      fprintf (stderr, Name ": adjusting superblock of %s for 2.2/sparc compatability.\n",
-+                               devname);
-+      }
-+      if (strcmp(update, "super-minor") ==0) {
-+              sb->md_minor = info->array.md_minor;
-+              if (verbose > 0)
-+                      fprintf(stderr, Name ": updating superblock of %s with minor number %d\n",
-+                              devname, info->array.md_minor);
-+      }
-+      if (strcmp(update, "summaries") == 0) {
-+              int i;
-+              /* set nr_disks, active_disks, working_disks,
-+               * failed_disks, spare_disks based on disks[] 
-+               * array in superblock.
-+               * Also make sure extra slots aren't 'failed'
-+               */
-+              sb->nr_disks = sb->active_disks =
-+                      sb->working_disks = sb->failed_disks =
-+                      sb->spare_disks = 0;
-+              for (i=0; i < MD_SB_DISKS ; i++) 
-+                      if (sb->disks[i].major ||
-+                          sb->disks[i].minor) {
-+                              int state = sb->disks[i].state;
-+                              if (state & (1<<MD_DISK_REMOVED))
-+                                      continue;
-+                              sb->nr_disks++;
-+                              if (state & (1<<MD_DISK_ACTIVE))
-+                                      sb->active_disks++;
-+                              if (state & (1<<MD_DISK_FAULTY))
-+                                      sb->failed_disks++;
-+                              else
-+                                      sb->working_disks++;
-+                              if (state == 0)
-+                                      sb->spare_disks++;
-+                      } else if (i >= sb->raid_disks && sb->disks[i].number == 0)
-+                              sb->disks[i].state = 0;
-+      }
-+      if (strcmp(update, "force-one")==0) {
-+              /* Not enough devices for a working array, so
-+               * bring this one up-to-date.
-+               */
-+              __u32 ehi = sb->events_hi, elo = sb->events_lo;
-+              sb->events_hi = (info->events>>32) & 0xFFFFFFFF;
-+              sb->events_lo = (info->events) & 0xFFFFFFFF;
-+              if (sb->events_hi != ehi ||
-+                  sb->events_lo != elo)
-+                      rv = 1;
-+      }
-+      if (strcmp(update, "force-array")==0) {
-+              /* degraded array and 'force' requested, so
-+               * maybe need to mark it 'clean'
-+               */
-+              if ((sb->level == 5 || sb->level == 4 || sb->level == 6) &&
-+                  (sb->state & (1 << MD_SB_CLEAN)) == 0) {
-+                      /* need to force clean */
-+                      sb->state |= (1 << MD_SB_CLEAN);
-+                      rv = 1;
-+              }
-+      }
-+      if (strcmp(update, "assemble")==0) {
-+              int d = info->disk.number;
-+              int wonly = sb->disks[d].state & (1<<MD_DISK_WRITEMOSTLY);
-+              if ((sb->disks[d].state & ~(1<<MD_DISK_WRITEMOSTLY))
-+                  != info->disk.state) {
-+                      sb->disks[d].state = info->disk.state | wonly;
-+                      rv = 1;
-+              }
-+      }
-+      if (strcmp(update, "linear-grow-new") == 0) {
-+              memset(&sb->disks[info->disk.number], 0, sizeof(sb->disks[0]));
-+              sb->disks[info->disk.number].number = info->disk.number;
-+              sb->disks[info->disk.number].major = info->disk.major;
-+              sb->disks[info->disk.number].minor = info->disk.minor;
-+              sb->disks[info->disk.number].raid_disk = info->disk.raid_disk;
-+              sb->disks[info->disk.number].state = info->disk.state;
-+              sb->this_disk = sb->disks[info->disk.number];
-+      }
-+      if (strcmp(update, "linear-grow-update") == 0) {
-+              sb->raid_disks = info->array.raid_disks;
-+              sb->nr_disks = info->array.nr_disks;
-+              sb->active_disks = info->array.active_disks;
-+              sb->working_disks = info->array.working_disks;
-+              memset(&sb->disks[info->disk.number], 0, sizeof(sb->disks[0]));
-+              sb->disks[info->disk.number].number = info->disk.number;
-+              sb->disks[info->disk.number].major = info->disk.major;
-+              sb->disks[info->disk.number].minor = info->disk.minor;
-+              sb->disks[info->disk.number].raid_disk = info->disk.raid_disk;
-+              sb->disks[info->disk.number].state = info->disk.state;
-+      }
-+      if (strcmp(update, "resync") == 0) {
-+              /* make sure resync happens */
-+              sb->state &= ~(1<<MD_SB_CLEAN);
-+              sb->recovery_cp = 0;
-+      }
-+      if (strcmp(update, "homehost") == 0 &&
-+          homehost) {
-+              uuid_set = 0;
-+              update = "uuid";
-+              info->uuid[0] = sb->set_uuid0;
-+              info->uuid[1] = sb->set_uuid1;
-+      }
-+      if (strcmp(update, "uuid") == 0) {
-+              if (!uuid_set && homehost) {
-+                      char buf[20];
-+                      char *hash = sha1_buffer(homehost,
-+                                               strlen(homehost),
-+                                               buf);
-+                      memcpy(info->uuid+2, hash, 8);
-+              }
-+              sb->set_uuid0 = info->uuid[0];
-+              sb->set_uuid1 = info->uuid[1];
-+              sb->set_uuid2 = info->uuid[2];
-+              sb->set_uuid3 = info->uuid[3];
-+              if (sb->state & (1<<MD_SB_BITMAP_PRESENT)) {
-+                      struct bitmap_super_s *bm;
-+                      bm = (struct bitmap_super_s*)(sb+1);
-+                      uuid_from_super0((int*)bm->uuid, sbv);
-+              }
-+      }
-+      if (strcmp(update, "_reshape_progress")==0)
-+              sb->reshape_position = info->reshape_progress;
-+
-+      sb->sb_csum = calc_sb0_csum(sb);
-+      return rv;
-+}
-+
-+static int store_super0(struct supertype *st, int fd, void *sbv)
-+{
-+      unsigned long long dsize;
-+      unsigned long long offset;
-+      mdp_super_t *super = sbv;
-+
-+      if (!get_dev_size(fd, NULL, &dsize))
-+              return 1;
-+
-+      if (dsize < MD_RESERVED_SECTORS*2*512)
-+              return 2;
-+
-+      offset = MD_NEW_SIZE_SECTORS(dsize>>9);
-+
-+      offset *= 512;
-+
-+      if (lseek64(fd, offset, 0)< 0LL)
-+              return 3;
-+
-+      if (write(fd, super, sizeof(*super)) != sizeof(*super))
-+              return 4;
-+
-+      if (super->state & (1<<MD_SB_BITMAP_PRESENT)) {
-+              struct bitmap_super_s * bm = (struct bitmap_super_s*)(super+1);
-+              if (__le32_to_cpu(bm->magic) == BITMAP_MAGIC)
-+                      if (write(fd, bm, sizeof(*bm)) != sizeof(*bm))
-+                          return 5;
-+      }
-+
-+      fsync(fd);
-+      return 0;
-+}
-+
-+static int compare_super0(void **firstp, void *secondv)
-+{
-+      /*
-+       * return:
-+       *  0 same, or first was empty, and second was copied
-+       *  1 second had wrong number
-+       *  2 wrong uuid
-+       *  3 wrong other info
-+       */
-+      mdp_super_t *first = *firstp;
-+      mdp_super_t *second = secondv;
-+
-+      int uuid1[4], uuid2[4];
-+      if (second->md_magic != MD_SB_MAGIC)
-+              return 1;
-+      if (!first) {
-+              first = malloc(MD_SB_BYTES + sizeof(struct bitmap_super_s));
-+              memcpy(first, second, MD_SB_BYTES + sizeof(struct bitmap_super_s));
-+              *firstp = first;
-+              return 0;
-+      }
-+
-+      uuid_from_super0(uuid1, first);
-+      uuid_from_super0(uuid2, second);
-+      if (!same_uuid(uuid1, uuid2, 0))
-+              return 2;
-+      if (first->major_version != second->major_version ||
-+          first->minor_version != second->minor_version ||
-+          first->patch_version != second->patch_version ||
-+          first->gvalid_words  != second->gvalid_words  ||
-+          first->ctime         != second->ctime         ||
-+          first->level         != second->level         ||
-+          first->size          != second->size          ||
-+          first->raid_disks    != second->raid_disks    )
-+              return 3;
-+
-+      return 0;
-+}
-+
-+
-+static int load_super0(struct supertype *st, int fd, void **sbp, char *devname)
-+{
-+      /* try to read in the superblock
-+       * Return:
-+       *  0 on success
-+       *  1 on cannot get superblock
-+       *  2 on superblock meaningless
-+       */
-+      unsigned long long dsize;
-+      unsigned long long offset;
-+      mdp_super_t *super;
-+      int uuid[4];
-+      struct bitmap_super_s *bsb;
-+    
-+      if (!get_dev_size(fd, devname, &dsize))
-+              return 1;
-+
-+      if (dsize < MD_RESERVED_SECTORS*512 * 2) {
-+              if (devname)
-+                      fprintf(stderr, Name
-+                          ": %s is too small for md: size is %llu sectors.\n",
-+                              devname, dsize);
-+              return 1;
-+      }
-+
-+      offset = MD_NEW_SIZE_SECTORS(dsize>>9);
-+
-+      offset *= 512;
-+
-+      ioctl(fd, BLKFLSBUF, 0); /* make sure we read current data */
-+
-+      if (lseek64(fd, offset, 0)< 0LL) {
-+              if (devname)
-+                      fprintf(stderr, Name ": Cannot seek to superblock on %s: %s\n",
-+                              devname, strerror(errno));
-+              return 1;
-+      }
-+
-+      super = malloc(MD_SB_BYTES + sizeof(bitmap_super_t));
-+
-+      if (read(fd, super, sizeof(*super)) != MD_SB_BYTES) {
-+              if (devname)
-+                      fprintf(stderr, Name ": Cannot read superblock on %s\n",
-+                              devname);
-+              free(super);
-+              return 1;
-+      }
-+
-+      if (st->ss && st->minor_version == 9)
-+              super0_swap_endian(super);
-+
-+      if (super->md_magic != MD_SB_MAGIC) {
-+              if (devname)
-+                      fprintf(stderr, Name ": No super block found on %s (Expected magic %08x, got %08x)\n",
-+                              devname, MD_SB_MAGIC, super->md_magic);
-+              free(super);
-+              return 2;
-+      }
-+
-+      if (super->major_version != 0) {
-+              if (devname)
-+                      fprintf(stderr, Name ": Cannot interpret superblock on %s - version is %d\n",
-+                              devname, super->major_version);
-+              free(super);
-+              return 2;
-+      }
-+      *sbp = super;
-+      if (st->ss == NULL) {
-+              st->ss = &super0;
-+              st->minor_version = 90;
-+              st->max_devs = MD_SB_DISKS;
-+      }
-+
-+      /* Now check on the bitmap superblock */
-+      if ((super->state & (1<<MD_SB_BITMAP_PRESENT)) == 0)
-+              return 0;
-+      /* Read the bitmap superblock and make sure it looks
-+       * valid.  If it doesn't clear the bit.  An --assemble --force
-+       * should get that written out.
-+       */
-+      if (read(fd, super+1, sizeof(struct bitmap_super_s))
-+          != sizeof(struct bitmap_super_s))
-+              goto no_bitmap;
-+
-+      uuid_from_super0(uuid, super);
-+      bsb = (struct bitmap_super_s *)(super+1);
-+      if (__le32_to_cpu(bsb->magic) != BITMAP_MAGIC ||
-+          memcmp(bsb->uuid, uuid, 16) != 0)
-+              goto no_bitmap;
-+      return 0;
-+
-+ no_bitmap:
-+      super->state &= ~(1<<MD_SB_BITMAP_PRESENT);
-+
-+      return 0;
-+}
-+
-+static struct supertype *match_metadata_desc0(char *arg)
-+{
-+      struct supertype *st = malloc(sizeof(*st));
-+      if (!st) return st;
-+
-+      st->ss = &super0;
-+      st->minor_version = 90;
-+      st->max_devs = MD_SB_DISKS;
-+      if (strcmp(arg, "0") == 0 ||
-+          strcmp(arg, "0.90") == 0 ||
-+          strcmp(arg, "default") == 0
-+              )
-+              return st;
-+
-+      st->minor_version = 9; /* flag for 'byte-swapped' */
-+      if (strcmp(arg, "0.swap")==0)
-+              return st;
-+
-+      free(st);
-+      return NULL;
-+}
-+
-+void locate_bitmap0(struct supertype *st, int fd, void *sbv)
-+{
-+      unsigned long long dsize;
-+      unsigned long long offset;
-+
-+      if (!get_dev_size(fd, NULL, &dsize))
-+              return;
-+
-+      if (dsize < MD_RESERVED_SECTORS*512 * 2)
-+              return;
-+
-+      offset = MD_NEW_SIZE_SECTORS(dsize>>9);
-+
-+      offset *= 512;
-+
-+      offset += MD_SB_BYTES;
-+
-+      lseek64(fd, offset, 0);
-+}
-+
-+struct superswitch super0 = {
-+      .examine_super = NULL,
-+      .brief_examine_super = brief_examine_super0,
-+      .detail_super = NULL,
-+      .brief_detail_super = NULL,
-+      .export_super = NULL,
-+      .match_home = match_home0,
-+      .uuid_from_super = uuid_from_super0,
-+      .getinfo_super = getinfo_super0,
-+      .update_super = update_super0,
-+      .init_super = NULL,
-+      .add_to_super = NULL,
-+      .store_super = store_super0,
-+      .write_init_super = NULL,
-+      .compare_super = compare_super0,
-+      .load_super = load_super0,
-+      .match_metadata_desc = match_metadata_desc0,
-+      .avail_size = NULL,
-+      .add_internal_bitmap = NULL, 
-+      .locate_bitmap = locate_bitmap0,
-+      .write_bitmap = NULL,
-+      .major = 0,
-+      .swapuuid = 0,
-+};
---- a/mdadm/super1.c   1970-01-01 03:00:00.000000000 +0300
-+++ mdadm/mdadm/super1.c       2011-01-12 21:33:01.000000000 +0200
-@@ -0,0 +1,731 @@
-+/*
-+ * mdadm - manage Linux "md" devices aka RAID arrays.
-+ *
-+ * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
-+ *
-+ *
-+ *    This program is free software; you can redistribute it and/or modify
-+ *    it under the terms of the GNU General Public License as published by
-+ *    the Free Software Foundation; either version 2 of the License, or
-+ *    (at your option) any later version.
-+ *
-+ *    This program is distributed in the hope that it will be useful,
-+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *    GNU General Public License for more details.
-+ *
-+ *    You should have received a copy of the GNU General Public License
-+ *    along with this program; if not, write to the Free Software
-+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ *
-+ *    Author: Neil Brown
-+ *    Email: <neilb@cse.unsw.edu.au>
-+ *    Paper: Neil Brown
-+ *           School of Computer Science and Engineering
-+ *           The University of New South Wales
-+ *           Sydney, 2052
-+ *           Australia
-+ */
-+
-+#include "mdadm.h"
-+/*
-+ * The version-1 superblock :
-+ * All numeric fields are little-endian.
-+ *
-+ * total size: 256 bytes plus 2 per device.
-+ *  1K allows 384 devices.
-+ */
-+struct mdp_superblock_1 {
-+      /* constant array information - 128 bytes */
-+      __u32   magic;          /* MD_SB_MAGIC: 0xa92b4efc - little endian */
-+      __u32   major_version;  /* 1 */
-+      __u32   feature_map;    /* 0 for now */
-+      __u32   pad0;           /* always set to 0 when writing */
-+
-+      __u8    set_uuid[16];   /* user-space generated. */
-+      char    set_name[32];   /* set and interpreted by user-space */
-+
-+      __u64   ctime;          /* lo 40 bits are seconds, top 24 are microseconds or 0*/
-+      __u32   level;          /* -4 (multipath), -1 (linear), 0,1,4,5 */
-+      __u32   layout;         /* only for raid5 currently */
-+      __u64   size;           /* used size of component devices, in 512byte sectors */
-+
-+      __u32   chunksize;      /* in 512byte sectors */
-+      __u32   raid_disks;
-+      __u32   bitmap_offset;  /* sectors after start of superblock that bitmap starts
-+                               * NOTE: signed, so bitmap can be before superblock
-+                               * only meaningful of feature_map[0] is set.
-+                               */
-+
-+      /* These are only valid with feature bit '4' */
-+      __u32   new_level;      /* new level we are reshaping to                */
-+      __u64   reshape_position;       /* next address in array-space for reshape */
-+      __u32   delta_disks;    /* change in number of raid_disks               */
-+      __u32   new_layout;     /* new layout                                   */
-+      __u32   new_chunk;      /* new chunk size (bytes)                       */
-+      __u8    pad1[128-124];  /* set to 0 when written */
-+
-+      /* constant this-device information - 64 bytes */
-+      __u64   data_offset;    /* sector start of data, often 0 */
-+      __u64   data_size;      /* sectors in this device that can be used for data */
-+      __u64   super_offset;   /* sector start of this superblock */
-+      __u64   recovery_offset;/* sectors before this offset (from data_offset) have been recovered */
-+      __u32   dev_number;     /* permanent identifier of this  device - not role in raid */
-+      __u32   cnt_corrected_read; /* number of read errors that were corrected by re-writing */
-+      __u8    device_uuid[16]; /* user-space setable, ignored by kernel */
-+        __u8    devflags;        /* per-device flags.  Only one defined...*/
-+#define WriteMostly1    1        /* mask for writemostly flag in above */
-+      __u8    pad2[64-57];    /* set to 0 when writing */
-+
-+      /* array state information - 64 bytes */
-+      __u64   utime;          /* 40 bits second, 24 btes microseconds */
-+      __u64   events;         /* incremented when superblock updated */
-+      __u64   resync_offset;  /* data before this offset (from data_offset) known to be in sync */
-+      __u32   sb_csum;        /* checksum upto devs[max_dev] */
-+      __u32   max_dev;        /* size of devs[] array to consider */
-+      __u8    pad3[64-32];    /* set to 0 when writing */
-+
-+      /* device state information. Indexed by dev_number.
-+       * 2 bytes per device
-+       * Note there are no per-device state flags. State information is rolled
-+       * into the 'roles' value.  If a device is spare or faulty, then it doesn't
-+       * have a meaningful role.
-+       */
-+      __u16   dev_roles[0];   /* role in array, or 0xffff for a spare, or 0xfffe for faulty */
-+};
-+
-+struct misc_dev_info {
-+      __u64 device_size;
-+};
-+
-+/* feature_map bits */
-+#define MD_FEATURE_BITMAP_OFFSET      1
-+#define       MD_FEATURE_RECOVERY_OFFSET      2 /* recovery_offset is present and
-+                                         * must be honoured
-+                                         */
-+#define       MD_FEATURE_RESHAPE_ACTIVE       4
-+
-+#define       MD_FEATURE_ALL                  (1|2|4)
-+
-+#ifndef offsetof
-+#define offsetof(t,f) ((size_t)&(((t*)0)->f))
-+#endif
-+static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb)
-+{
-+      unsigned int disk_csum, csum;
-+      unsigned long long newcsum;
-+      int size = sizeof(*sb) + __le32_to_cpu(sb->max_dev)*2;
-+      unsigned int *isuper = (unsigned int*)sb;
-+      int i;
-+
-+/* make sure I can count... */
-+      if (offsetof(struct mdp_superblock_1,data_offset) != 128 ||
-+          offsetof(struct mdp_superblock_1, utime) != 192 ||
-+          sizeof(struct mdp_superblock_1) != 256) {
-+              fprintf(stderr, "WARNING - superblock isn't sized correctly\n");
-+      }
-+
-+      disk_csum = sb->sb_csum;
-+      sb->sb_csum = 0;
-+      newcsum = 0;
-+      for (i=0; size>=4; size -= 4 ) {
-+              newcsum += __le32_to_cpu(*isuper);
-+              isuper++;
-+      }
-+
-+      if (size == 2)
-+              newcsum += __le16_to_cpu(*(unsigned short*) isuper);
-+
-+      csum = (newcsum & 0xffffffff) + (newcsum >> 32);
-+      sb->sb_csum = disk_csum;
-+      return __cpu_to_le32(csum);
-+}
-+
-+static void brief_examine_super1(void *sbv)
-+{
-+      struct mdp_superblock_1 *sb = sbv;
-+      int i;
-+      unsigned long long sb_offset;
-+      char *nm;
-+      char *c=map_num(pers, __le32_to_cpu(sb->level));
-+
-+      nm = strchr(sb->set_name, ':');
-+      if (nm)
-+              nm++;
-+      else if (sb->set_name[0])
-+              nm = sb->set_name;
-+      else
-+              nm = "??";
-+
-+      printf("ARRAY /dev/md%s level=%s ", nm, c?c:"-unknown-");
-+      sb_offset = __le64_to_cpu(sb->super_offset);
-+      if (sb_offset <= 4)
-+              printf("metadata=1.1 ");
-+      else if (sb_offset <= 8)
-+              printf("metadata=1.2 ");
-+      else
-+              printf("metadata=1.0 ");
-+      printf("num-devices=%d UUID=", __le32_to_cpu(sb->raid_disks));
-+      for (i=0; i<16; i++) {
-+              if ((i&3)==0 && i != 0) printf(":");
-+              printf("%02x", sb->set_uuid[i]);
-+      }
-+      if (sb->set_name[0])
-+              printf(" name=%.32s", sb->set_name);
-+      printf("\n");
-+}
-+
-+static int match_home1(void *sbv, char *homehost)
-+{
-+      struct mdp_superblock_1 *sb = sbv;
-+      int l = homehost ? strlen(homehost) : 0;
-+
-+      return (l > 0 && l < 32 &&
-+              sb->set_name[l] == ':' &&
-+              strncmp(sb->set_name, homehost, l) == 0);
-+}
-+
-+static void uuid_from_super1(int uuid[4], void * sbv)
-+{
-+      struct mdp_superblock_1 *super = sbv;
-+      char *cuuid = (char*)uuid;
-+      int i;
-+      for (i=0; i<16; i++)
-+              cuuid[i] = super->set_uuid[i];
-+}
-+
-+static void getinfo_super1(struct mdinfo *info, void *sbv)
-+{
-+      struct mdp_superblock_1 *sb = sbv;
-+      int working = 0;
-+      int i;
-+      int role;
-+
-+      info->array.major_version = 1;
-+      info->array.minor_version = __le32_to_cpu(sb->feature_map);
-+      info->array.patch_version = 0;
-+      info->array.raid_disks = __le32_to_cpu(sb->raid_disks);
-+      info->array.level = __le32_to_cpu(sb->level);
-+      info->array.layout = __le32_to_cpu(sb->layout);
-+      info->array.md_minor = -1;
-+      info->array.ctime = __le64_to_cpu(sb->ctime);
-+      info->array.utime = __le64_to_cpu(sb->utime);
-+      info->array.chunk_size = __le32_to_cpu(sb->chunksize)*512;
-+      info->array.state =
-+              (__le64_to_cpu(sb->resync_offset) >= __le64_to_cpu(sb->size))
-+              ? 1 : 0;
-+
-+      info->data_offset = __le64_to_cpu(sb->data_offset);
-+      info->component_size = __le64_to_cpu(sb->size);
-+
-+      info->disk.major = 0;
-+      info->disk.minor = 0;
-+      info->disk.number = __le32_to_cpu(sb->dev_number);
-+      if (__le32_to_cpu(sb->dev_number) >= __le32_to_cpu(sb->max_dev) ||
-+          __le32_to_cpu(sb->max_dev) > 512)
-+              role = 0xfffe;
-+      else
-+              role = __le16_to_cpu(sb->dev_roles[__le32_to_cpu(sb->dev_number)]);
-+
-+      info->disk.raid_disk = -1;
-+      switch(role) {
-+      case 0xFFFF:
-+              info->disk.state = 2; /* spare: ACTIVE, not sync, not faulty */
-+              break;
-+      case 0xFFFE:
-+              info->disk.state = 1; /* faulty */
-+              break;
-+      default:
-+              info->disk.state = 6; /* active and in sync */
-+              info->disk.raid_disk = role;
-+      }
-+      info->events = __le64_to_cpu(sb->events);
-+
-+      memcpy(info->uuid, sb->set_uuid, 16);
-+
-+      strncpy(info->name, sb->set_name, 32);
-+      info->name[32] = 0;
-+
-+      if (sb->feature_map & __le32_to_cpu(MD_FEATURE_RESHAPE_ACTIVE)) {
-+              info->reshape_active = 1;
-+              info->reshape_progress = __le64_to_cpu(sb->reshape_position);
-+              info->new_level = __le32_to_cpu(sb->new_level);
-+              info->delta_disks = __le32_to_cpu(sb->delta_disks);
-+              info->new_layout = __le32_to_cpu(sb->new_layout);
-+              info->new_chunk = __le32_to_cpu(sb->new_chunk)<<9;
-+      } else
-+              info->reshape_active = 0;
-+
-+      for (i=0; i< __le32_to_cpu(sb->max_dev); i++) {
-+              role = __le16_to_cpu(sb->dev_roles[i]);
-+              if (/*role == 0xFFFF || */role < info->array.raid_disks)
-+                      working++;
-+      }
-+
-+      info->array.working_disks = working;
-+}
-+
-+static int update_super1(struct mdinfo *info, void *sbv, char *update,
-+                       char *devname, int verbose,
-+                       int uuid_set, char *homehost)
-+{
-+      /* NOTE: for 'assemble' and 'force' we need to return non-zero if any change was made.
-+       * For others, the return value is ignored.
-+       */
-+      int rv = 0;
-+      struct mdp_superblock_1 *sb = sbv;
-+
-+      if (strcmp(update, "force-one")==0) {
-+              /* Not enough devices for a working array,
-+               * so bring this one up-to-date
-+               */
-+              if (sb->events != __cpu_to_le64(info->events))
-+                      rv = 1;
-+              sb->events = __cpu_to_le64(info->events);
-+      }
-+      if (strcmp(update, "force-array")==0) {
-+              /* Degraded array and 'force' requests to
-+               * maybe need to mark it 'clean'.
-+               */
-+              switch(__le32_to_cpu(sb->level)) {
-+              case 5: case 4: case 6:
-+                      /* need to force clean */
-+                      if (sb->resync_offset != ~0ULL)
-+                              rv = 1;
-+                      sb->resync_offset = ~0ULL;
-+              }
-+      }
-+      if (strcmp(update, "assemble")==0) {
-+              int d = info->disk.number;
-+              int want;
-+              if (info->disk.state == 6)
-+                      want = __cpu_to_le32(info->disk.raid_disk);
-+              else
-+                      want = 0xFFFF;
-+              if (sb->dev_roles[d] != want) {
-+                      sb->dev_roles[d] = want;
-+                      rv = 1;
-+              }
-+      }
-+      if (strcmp(update, "linear-grow-new") == 0) {
-+              int i;
-+              int rfd;
-+              int max = __le32_to_cpu(sb->max_dev);
-+
-+              for (i=0 ; i < max ; i++)
-+                      if (__le16_to_cpu(sb->dev_roles[i]) >= 0xfffe)
-+                              break;
-+              sb->dev_number = __cpu_to_le32(i);
-+              info->disk.number = i;
-+              if (max >= __le32_to_cpu(sb->max_dev))
-+                      sb->max_dev = __cpu_to_le32(max+1);
-+
-+              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();
-+              }
-+
-+              sb->dev_roles[i] =
-+                      __cpu_to_le16(info->disk.raid_disk);
-+      }
-+      if (strcmp(update, "linear-grow-update") == 0) {
-+              sb->raid_disks = __cpu_to_le32(info->array.raid_disks);
-+              sb->dev_roles[info->disk.number] =
-+                      __cpu_to_le16(info->disk.raid_disk);
-+      }
-+      if (strcmp(update, "resync") == 0) {
-+              /* make sure resync happens */
-+              sb->resync_offset = 0ULL;
-+      }
-+      if (strcmp(update, "uuid") == 0) {
-+              copy_uuid(sb->set_uuid, info->uuid, super1.swapuuid);
-+
-+              if (__le32_to_cpu(sb->feature_map)&MD_FEATURE_BITMAP_OFFSET) {
-+                      struct bitmap_super_s *bm;
-+                      bm = (struct bitmap_super_s*)(sbv+1024);
-+                      memcpy(bm->uuid, sb->set_uuid, 16);
-+              }
-+      }
-+      if (strcmp(update, "homehost") == 0 &&
-+          homehost) {
-+              char *c;
-+              update = "name";
-+              c = strchr(sb->set_name, ':');
-+              if (c)
-+                      strncpy(info->name, c+1, 31 - (c-sb->set_name));
-+              else
-+                      strncpy(info->name, sb->set_name, 32);
-+              info->name[32] = 0;
-+      }
-+      if (strcmp(update, "name") == 0) {
-+              if (info->name[0] == 0)
-+                      sprintf(info->name, "%d", info->array.md_minor);
-+              memset(sb->set_name, 0, sizeof(sb->set_name));
-+              if (homehost &&
-+                  strchr(info->name, ':') == NULL &&
-+                  strlen(homehost)+1+strlen(info->name) < 32) {
-+                      strcpy(sb->set_name, homehost);
-+                      strcat(sb->set_name, ":");
-+                      strcat(sb->set_name, info->name);
-+              } else
-+                      strcpy(sb->set_name, info->name);
-+      }
-+      if (strcmp(update, "devicesize") == 0 &&
-+          __le64_to_cpu(sb->super_offset) <
-+          __le64_to_cpu(sb->data_offset)) {
-+              /* set data_size to device size less data_offset */
-+              struct misc_dev_info *misc = (struct misc_dev_info*)
-+                      (sbv + 1024 + sizeof(struct bitmap_super_s));
-+              printf("Size was %llu\n", (unsigned long long)
-+                     __le64_to_cpu(sb->data_size));
-+              sb->data_size = __cpu_to_le64(
-+                      misc->device_size - __le64_to_cpu(sb->data_offset));
-+              printf("Size is %llu\n", (unsigned long long)
-+                     __le64_to_cpu(sb->data_size));
-+      }
-+      if (strcmp(update, "_reshape_progress")==0)
-+              sb->reshape_position = __cpu_to_le64(info->reshape_progress);
-+
-+      sb->sb_csum = calc_sb_1_csum(sb);
-+      return rv;
-+}
-+
-+static void locate_bitmap1(struct supertype *st, int fd, void *sbv);
-+
-+static int store_super1(struct supertype *st, int fd, void *sbv)
-+{
-+      struct mdp_superblock_1 *sb = sbv;
-+      unsigned long long sb_offset;
-+      int sbsize;
-+      unsigned long long dsize;
-+
-+      if (!get_dev_size(fd, NULL, &dsize))
-+              return 1;
-+
-+      dsize >>= 9;
-+
-+      if (dsize < 24)
-+              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.
-+       */
-+      switch(st->minor_version) {
-+      case 0:
-+              sb_offset = dsize;
-+              sb_offset -= 8*2;
-+              sb_offset &= ~(4*2-1);
-+              break;
-+      case 1:
-+              sb_offset = 0;
-+              break;
-+      case 2:
-+              sb_offset = 4*2;
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+
-+
-+
-+      if (sb_offset != __le64_to_cpu(sb->super_offset) &&
-+          0 != __le64_to_cpu(sb->super_offset)
-+              ) {
-+              fprintf(stderr, Name ": internal error - sb_offset is wrong\n");
-+              abort();
-+      }
-+
-+      if (lseek64(fd, sb_offset << 9, 0)< 0LL)
-+              return 3;
-+
-+      sbsize = sizeof(*sb) + 2 * __le32_to_cpu(sb->max_dev);
-+
-+      if (write(fd, sb, sbsize) != sbsize)
-+              return 4;
-+
-+      if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) {
-+              struct bitmap_super_s *bm = (struct bitmap_super_s*)
-+                      (((char*)sb)+1024);
-+              if (__le32_to_cpu(bm->magic) == BITMAP_MAGIC) {
-+                      locate_bitmap1(st, fd, sbv);
-+                      if (write(fd, bm, sizeof(*bm)) != sizeof(*bm))
-+                          return 5;
-+              }
-+      }
-+      fsync(fd);
-+      return 0;
-+}
-+
-+static int load_super1(struct supertype *st, int fd, void **sbp, char *devname);
-+
-+static int compare_super1(void **firstp, void *secondv)
-+{
-+      /*
-+       * return:
-+       *  0 same, or first was empty, and second was copied
-+       *  1 second had wrong number
-+       *  2 wrong uuid
-+       *  3 wrong other info
-+       */
-+      struct mdp_superblock_1 *first = *firstp;
-+      struct mdp_superblock_1 *second = secondv;
-+
-+      if (second->magic != __cpu_to_le32(MD_SB_MAGIC))
-+              return 1;
-+      if (second->major_version != __cpu_to_le32(1))
-+              return 1;
-+
-+      if (!first) {
-+              first = malloc(1024+sizeof(bitmap_super_t) +
-+                             sizeof(struct misc_dev_info));
-+              memcpy(first, second, 1024+sizeof(bitmap_super_t) +
-+                     sizeof(struct misc_dev_info));
-+              *firstp = first;
-+              return 0;
-+      }
-+      if (memcmp(first->set_uuid, second->set_uuid, 16)!= 0)
-+              return 2;
-+
-+      if (first->ctime      != second->ctime     ||
-+          first->level      != second->level     ||
-+          first->layout     != second->layout    ||
-+          first->size       != second->size      ||
-+          first->chunksize  != second->chunksize ||
-+          first->raid_disks != second->raid_disks)
-+              return 3;
-+      return 0;
-+}
-+
-+static int load_super1(struct supertype *st, int fd, void **sbp, char *devname)
-+{
-+      unsigned long long dsize;
-+      unsigned long long sb_offset;
-+      struct mdp_superblock_1 *super;
-+      int uuid[4];
-+      struct bitmap_super_s *bsb;
-+      struct misc_dev_info *misc;
-+
-+
-+      if (st->ss == NULL) {
-+              int bestvers = -1;
-+              __u64 bestctime = 0;
-+              /* guess... choose latest ctime */
-+              st->ss = &super1;
-+              for (st->minor_version = 0; st->minor_version <= 2 ; st->minor_version++) {
-+                      switch(load_super1(st, fd, sbp, devname)) {
-+                      case 0: super = *sbp;
-+                              if (bestvers == -1 ||
-+                                  bestctime < __le64_to_cpu(super->ctime)) {
-+                                      bestvers = st->minor_version;
-+                                      bestctime = __le64_to_cpu(super->ctime);
-+                              }
-+                              free(super);
-+                              *sbp = NULL;
-+                              break;
-+                      case 1: st->ss = NULL; return 1; /*bad device */
-+                      case 2: break; /* bad, try next */
-+                      }
-+              }
-+              if (bestvers != -1) {
-+                      int rv;
-+                      st->minor_version = bestvers;
-+                      st->ss = &super1;
-+                      st->max_devs = 384;
-+                      rv = load_super1(st, fd, sbp, devname);
-+                      if (rv) st->ss = NULL;
-+                      return rv;
-+              }
-+              st->ss = NULL;
-+              return 2;
-+      }
-+      if (!get_dev_size(fd, devname, &dsize))
-+              return 1;
-+      dsize >>= 9;
-+
-+      if (dsize < 24) {
-+              if (devname)
-+                      fprintf(stderr, Name ": %s is too small for md: size is %llu sectors.\n",
-+                              devname, dsize);
-+              return 1;
-+      }
-+
-+      /*
-+       * 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.
-+       */
-+      switch(st->minor_version) {
-+      case 0:
-+              sb_offset = dsize;
-+              sb_offset -= 8*2;
-+              sb_offset &= ~(4*2-1);
-+              break;
-+      case 1:
-+              sb_offset = 0;
-+              break;
-+      case 2:
-+              sb_offset = 4*2;
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+
-+      ioctl(fd, BLKFLSBUF, 0); /* make sure we read current data */
-+
-+
-+      if (lseek64(fd, sb_offset << 9, 0)< 0LL) {
-+              if (devname)
-+                      fprintf(stderr, Name ": Cannot seek to superblock on %s: %s\n",
-+                              devname, strerror(errno));
-+              return 1;
-+      }
-+
-+      super = malloc(1024 + sizeof(bitmap_super_t) +
-+                     sizeof(struct misc_dev_info));
-+
-+      if (read(fd, super, 1024) != 1024) {
-+              if (devname)
-+                      fprintf(stderr, Name ": Cannot read superblock on %s\n",
-+                              devname);
-+              free(super);
-+              return 1;
-+      }
-+
-+      if (__le32_to_cpu(super->magic) != MD_SB_MAGIC) {
-+              if (devname)
-+                      fprintf(stderr, Name ": No super block found on %s (Expected magic %08x, got %08x)\n",
-+                              devname, MD_SB_MAGIC, __le32_to_cpu(super->magic));
-+              free(super);
-+              return 2;
-+      }
-+
-+      if (__le32_to_cpu(super->major_version) != 1) {
-+              if (devname)
-+                      fprintf(stderr, Name ": Cannot interpret superblock on %s - version is %d\n",
-+                              devname, __le32_to_cpu(super->major_version));
-+              free(super);
-+              return 2;
-+      }
-+      if (__le64_to_cpu(super->super_offset) != sb_offset) {
-+              if (devname)
-+                      fprintf(stderr, Name ": No superblock found on %s (super_offset is wrong)\n",
-+                              devname);
-+              free(super);
-+              return 2;
-+      }
-+      *sbp = super;
-+
-+      bsb = (struct bitmap_super_s *)(((char*)super)+1024);
-+
-+      misc = (struct misc_dev_info*) (bsb+1);
-+      misc->device_size = dsize;
-+
-+      /* Now check on the bitmap superblock */
-+      if ((__le32_to_cpu(super->feature_map)&MD_FEATURE_BITMAP_OFFSET) == 0)
-+              return 0;
-+      /* Read the bitmap superblock and make sure it looks
-+       * valid.  If it doesn't clear the bit.  An --assemble --force
-+       * should get that written out.
-+       */
-+      locate_bitmap1(st, fd, super);
-+      if (read(fd, ((char*)super)+1024, sizeof(struct bitmap_super_s))
-+          != sizeof(struct bitmap_super_s))
-+              goto no_bitmap;
-+
-+      uuid_from_super1(uuid, super);
-+      if (__le32_to_cpu(bsb->magic) != BITMAP_MAGIC ||
-+          memcmp(bsb->uuid, uuid, 16) != 0)
-+              goto no_bitmap;
-+      return 0;
-+
-+ no_bitmap:
-+      super->feature_map = __cpu_to_le32(__le32_to_cpu(super->feature_map) & ~1);
-+      return 0;
-+}
-+
-+
-+static struct supertype *match_metadata_desc1(char *arg)
-+{
-+      struct supertype *st = malloc(sizeof(*st));
-+      if (!st) return st;
-+
-+      st->ss = &super1;
-+      st->max_devs = 384;
-+      if (strcmp(arg, "1") == 0 ||
-+          strcmp(arg, "1.0") == 0 ||
-+          strcmp(arg, "default/large") == 0) {
-+              st->minor_version = 0;
-+              return st;
-+      }
-+      if (strcmp(arg, "1.1") == 0) {
-+              st->minor_version = 1;
-+              return st;
-+      }
-+      if (strcmp(arg, "1.2") == 0) {
-+              st->minor_version = 2;
-+              return st;
-+      }
-+
-+      free(st);
-+      return NULL;
-+}
-+
-+static void locate_bitmap1(struct supertype *st, int fd, void *sbv)
-+{
-+      unsigned long long offset;
-+      struct mdp_superblock_1 *sb;
-+      int mustfree = 0;
-+
-+      if (!sbv) {
-+              if (st->ss->load_super(st, fd, &sbv, NULL))
-+                      return; /* no error I hope... */
-+              mustfree = 1;
-+      }
-+      sb = sbv;
-+
-+      offset = __le64_to_cpu(sb->super_offset);
-+      offset += (int32_t) __le32_to_cpu(sb->bitmap_offset);
-+      if (mustfree)
-+              free(sb);
-+      lseek64(fd, offset<<9, 0);
-+}
-+
-+struct superswitch super1 = {
-+      .examine_super = NULL,
-+      .brief_examine_super = brief_examine_super1,
-+      .detail_super = NULL,
-+      .brief_detail_super = NULL,
-+      .export_super = NULL,
-+      .match_home = match_home1,
-+      .uuid_from_super = uuid_from_super1,
-+      .getinfo_super = getinfo_super1,
-+      .update_super = update_super1,
-+      .init_super = NULL,
-+      .add_to_super = NULL,
-+      .store_super = store_super1,
-+      .write_init_super = NULL,
-+      .compare_super = compare_super1,
-+      .load_super = load_super1,
-+      .match_metadata_desc = match_metadata_desc1,
-+      .avail_size = NULL,
-+      .add_internal_bitmap = NULL,
-+      .locate_bitmap = locate_bitmap1,
-+      .write_bitmap = NULL,
-+      .major = 1,
-+#if __BYTE_ORDER == BIG_ENDIAN
-+      .swapuuid = 0,
-+#else
-+      .swapuuid = 1,
-+#endif
-+};
---- a/mdadm/util.c     1970-01-01 03:00:00.000000000 +0300
-+++ mdadm/mdadm/util.c 2011-01-12 21:33:01.000000000 +0200
-@@ -0,0 +1,652 @@
-+/*
-+ * mdadm - manage Linux "md" devices aka RAID arrays.
-+ *
-+ * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
-+ *
-+ *
-+ *    This program is free software; you can redistribute it and/or modify
-+ *    it under the terms of the GNU General Public License as published by
-+ *    the Free Software Foundation; either version 2 of the License, or
-+ *    (at your option) any later version.
-+ *
-+ *    This program is distributed in the hope that it will be useful,
-+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *    GNU General Public License for more details.
-+ *
-+ *    You should have received a copy of the GNU General Public License
-+ *    along with this program; if not, write to the Free Software
-+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ *
-+ *    Author: Neil Brown
-+ *    Email: <neilb@cse.unsw.edu.au>
-+ *    Paper: Neil Brown
-+ *           School of Computer Science and Engineering
-+ *           The University of New South Wales
-+ *           Sydney, 2052
-+ *           Australia
-+ */
-+
-+#include      "mdadm.h"
-+#include      "md_p.h"
-+#include      <sys/utsname.h>
-+#include      <ctype.h>
-+
-+/*
-+ * following taken from linux/blkpg.h because they aren't
-+ * anywhere else and it isn't safe to #include linux/ * stuff.
-+ */
-+
-+#define BLKPG      _IO(0x12,105)
-+
-+/* The argument structure */
-+struct blkpg_ioctl_arg {
-+        int op;
-+        int flags;
-+        int datalen;
-+        void *data;
-+};
-+
-+/* The subfunctions (for the op field) */
-+#define BLKPG_ADD_PARTITION   1
-+#define BLKPG_DEL_PARTITION   2
-+
-+/* Sizes of name fields. Unused at present. */
-+#define BLKPG_DEVNAMELTH      64
-+#define BLKPG_VOLNAMELTH      64
-+
-+/* The data structure for ADD_PARTITION and DEL_PARTITION */
-+struct blkpg_partition {
-+      long long start;                /* starting offset in bytes */
-+      long long length;               /* length in bytes */
-+      int pno;                        /* partition number */
-+      char devname[BLKPG_DEVNAMELTH]; /* partition name, like sda5 or c0d1p2,
-+                                         to be used in kernel messages */
-+      char volname[BLKPG_VOLNAMELTH]; /* volume label */
-+};
-+
-+/*
-+ * Parse a 128 bit uuid in 4 integers
-+ * format is 32 hexx nibbles with options :.<space> separator
-+ * If not exactly 32 hex digits are found, return 0
-+ * else return 1
-+ */
-+int parse_uuid(char *str, int uuid[4])
-+{
-+    int hit = 0; /* number of Hex digIT */
-+    int i;
-+    char c;
-+    for (i=0; i<4; i++) uuid[i]=0;
-+
-+    while ((c= *str++)) {
-+      int n;
-+      if (c>='0' && c<='9')
-+          n = c-'0';
-+      else if (c>='a' && c <= 'f')
-+          n = 10 + c - 'a';
-+      else if (c>='A' && c <= 'F')
-+          n = 10 + c - 'A';
-+      else if (strchr(":. -", c))
-+          continue;
-+      else return 0;
-+
-+      if (hit<32) {
-+          uuid[hit/8] <<= 4;
-+          uuid[hit/8] += n;
-+      }
-+      hit++;
-+    }
-+    if (hit == 32)
-+      return 1;
-+    return 0;
-+    
-+}
-+
-+
-+/*
-+ * Get the md version number.
-+ * We use the RAID_VERSION ioctl if it is supported
-+ * If not, but we have a block device with major '9', we assume
-+ * 0.36.0
-+ *
-+ * Return version number as 24 but number - assume version parts
-+ * always < 255
-+ */
-+
-+int md_get_version(int fd)
-+{
-+    struct stat stb;
-+    mdu_version_t vers;
-+
-+    if (fstat(fd, &stb)<0)
-+      return -1;
-+    if ((S_IFMT&stb.st_mode) != S_IFBLK)
-+      return -1;
-+
-+    if (ioctl(fd, RAID_VERSION, &vers) == 0)
-+      return  (vers.major*10000) + (vers.minor*100) + vers.patchlevel;
-+    if (errno == EACCES)
-+          return -1;
-+    if (major(stb.st_rdev) == MD_MAJOR)
-+      return (3600);
-+    return -1;
-+}
-+
-+    
-+int get_linux_version()
-+{
-+      struct utsname name;
-+      char *cp;
-+      int a,b,c;
-+      if (uname(&name) <0)
-+              return -1;
-+
-+      cp = name.release;
-+      a = strtoul(cp, &cp, 10);
-+      if (*cp != '.') return -1;
-+      b = strtoul(cp+1, &cp, 10);
-+      if (*cp != '.') return -1;
-+      c = strtoul(cp+1, NULL, 10);
-+
-+      return (a*1000000)+(b*1000)+c;
-+}
-+
-+void remove_partitions(int fd)
-+{
-+      /* remove partitions from this block devices.
-+       * This is used for components added to an array
-+       */
-+#ifdef BLKPG_DEL_PARTITION
-+      struct blkpg_ioctl_arg a;
-+      struct blkpg_partition p;
-+
-+      a.op = BLKPG_DEL_PARTITION;
-+      a.data = (void*)&p;
-+      a.datalen = sizeof(p);
-+      a.flags = 0;
-+      memset(a.data, 0, a.datalen);
-+      for (p.pno=0; p.pno < 16; p.pno++)
-+              ioctl(fd, BLKPG, &a);
-+#endif
-+}
-+
-+int enough(int level, int raid_disks, int layout, int clean,
-+         char *avail, int avail_disks)
-+{
-+      int copies, first;
-+      switch (level) {
-+      case 10:
-+              /* This is the tricky one - we need to check
-+               * which actual disks are present.
-+               */
-+              copies = (layout&255)* ((layout>>8) & 255);
-+              first=0;
-+              do {
-+                      /* there must be one of the 'copies' form 'first' */
-+                      int n = copies;
-+                      int cnt=0;
-+                      while (n--) {
-+                              if (avail[first])
-+                                      cnt++;
-+                              first = (first+1) % raid_disks;
-+                      }
-+                      if (cnt == 0)
-+                              return 0;
-+
-+              } while (first != 0);
-+              return 1;
-+
-+      case -4:
-+              return avail_disks>= 1;
-+      case -1:
-+      case 0:
-+              return avail_disks == raid_disks;
-+      case 1:
-+              return avail_disks >= 1;
-+      case 4:
-+      case 5:
-+              if (clean)
-+                      return avail_disks >= raid_disks-1;
-+              else
-+                      return avail_disks >= raid_disks;
-+      case 6:
-+              if (clean)
-+                      return avail_disks >= raid_disks-2;
-+              else
-+                      return avail_disks >= raid_disks;
-+      default:
-+              return 0;
-+      }
-+}
-+
-+int same_uuid(int a[4], int b[4], int swapuuid)
-+{
-+      if (swapuuid) {
-+              /* parse uuids are hostendian.
-+               * uuid's from some superblocks are big-ending
-+               * if there is a difference, we need to swap.. 
-+               */
-+              unsigned char *ac = (unsigned char *)a;
-+              unsigned char *bc = (unsigned char *)b;
-+              int i;
-+              for (i=0; i<16; i+= 4) {
-+                      if (ac[i+0] != bc[i+3] ||
-+                          ac[i+1] != bc[i+2] ||
-+                          ac[i+2] != bc[i+1] ||
-+                          ac[i+3] != bc[i+0])
-+                              return 0;
-+              }
-+              return 1;
-+      } else {
-+              if (a[0]==b[0] &&
-+                  a[1]==b[1] &&
-+                  a[2]==b[2] &&
-+                  a[3]==b[3])
-+                      return 1;
-+              return 0;
-+      }
-+}
-+void copy_uuid(void *a, int b[4], int swapuuid)
-+{
-+      if (swapuuid) {
-+              /* parse uuids are hostendian.
-+               * uuid's from some superblocks are big-ending
-+               * if there is a difference, we need to swap..
-+               */
-+              unsigned char *ac = (unsigned char *)a;
-+              unsigned char *bc = (unsigned char *)b;
-+              int i;
-+              for (i=0; i<16; i+= 4) {
-+                      ac[i+0] = bc[i+3];
-+                      ac[i+1] = bc[i+2];
-+                      ac[i+2] = bc[i+1];
-+                      ac[i+3] = bc[i+0];
-+              }
-+      } else
-+              memcpy(a, b, 16);
-+}
-+
-+char *map_num(mapping_t *map, int num)
-+{
-+      while (map->name) {
-+              if (map->num == num)
-+                      return map->name;
-+              map++;
-+      }
-+      return NULL;
-+}
-+
-+int map_name(mapping_t *map, char *name)
-+{
-+      while (map->name) {
-+              if (strcmp(map->name, name)==0)
-+                      return map->num;
-+              map++;
-+      }
-+      return UnSet;
-+}
-+
-+
-+int is_standard(char *dev, int *nump)
-+{
-+      /* tests if dev is a "standard" md dev name.
-+       * i.e if the last component is "/dNN" or "/mdNN",
-+       * where NN is a string of digits 
-+       */
-+      char *d = strrchr(dev, '/');
-+      int type=0;
-+      int num;
-+      if (!d)
-+              return 0;
-+      if (strncmp(d, "/d",2)==0)
-+              d += 2, type=1; /* /dev/md/dN{pM} */
-+      else if (strncmp(d, "/md_d", 5)==0)
-+              d += 5, type=1; /* /dev/md_dNpM */
-+      else if (strncmp(d, "/md", 3)==0)
-+              d += 3, type=-1; /* /dev/mdN */
-+      else if (d-dev > 3 && strncmp(d-2, "md/", 3)==0)
-+              d += 1, type=-1; /* /dev/md/N */
-+      else
-+              return 0;
-+      if (!*d)
-+              return 0;
-+      num = atoi(d);
-+      while (isdigit(*d))
-+              d++;
-+      if (*d)
-+              return 0;
-+      if (nump) *nump = num;
-+
-+      return type;
-+}
-+
-+
-+/*
-+ * convert a major/minor pair for a block device into a name in /dev, if possible.
-+ * On the first call, walk /dev collecting name.
-+ * Put them in a simple linked listfor now.
-+ */
-+struct devmap {
-+    int major, minor;
-+    char *name;
-+    struct devmap *next;
-+} *devlist = NULL;
-+int devlist_ready = 0;
-+
-+int add_dev(const char *name, const struct stat *stb, int flag, struct FTW *s)
-+{
-+      struct stat st;
-+      if (S_ISLNK(stb->st_mode)) {
-+              stat(name, &st);
-+              stb = &st;
-+      }
-+
-+      if ((stb->st_mode&S_IFMT)== S_IFBLK) {
-+              char *n = strdup(name);
-+              struct devmap *dm = malloc(sizeof(*dm));
-+              if (strncmp(n, "/dev/./", 7)==0)
-+                      strcpy(n+4, name+6);
-+              if (dm) {
-+                      dm->major = major(stb->st_rdev);
-+                      dm->minor = minor(stb->st_rdev);
-+                      dm->name = n;
-+                      dm->next = devlist;
-+                      devlist = dm;
-+              }
-+      }
-+      return 0;
-+}
-+
-+#ifndef HAVE_NFTW
-+#ifdef HAVE_FTW
-+int add_dev_1(const char *name, const struct stat *stb, int flag)
-+{
-+      return add_dev(name, stb, flag, NULL);
-+}
-+int nftw(const char *path, int (*han)(const char *name, const struct stat *stb, int flag, struct FTW *s), int nopenfd, int flags)
-+{
-+      return ftw(path, add_dev_1, nopenfd);
-+}
-+#else
-+int nftw(const char *path, int (*han)(const char *name, const struct stat *stb, int flag, struct FTW *s), int nopenfd, int flags)
-+{
-+      return 0;
-+}
-+#endif /* HAVE_FTW */
-+#endif /* HAVE_NFTW */
-+
-+/*
-+ * Find a block device with the right major/minor number.
-+ * If we find multiple names, choose the shortest.
-+ * If we find a non-standard name, it is probably there
-+ * deliberately so prefer it over a standard name.
-+ * This applies only to names for MD devices.
-+ */
-+char *map_dev(int major, int minor, int create)
-+{
-+      struct devmap *p;
-+      char *std = NULL, *nonstd=NULL;
-+      int did_check = 0;
-+
-+      if (major == 0 && minor == 0)
-+                      return NULL;
-+
-+ retry:
-+      if (!devlist_ready) {
-+              char *dev = "/dev";
-+              struct stat stb;
-+              while(devlist) {
-+                      struct devmap *d = devlist;
-+                      devlist = d->next;
-+                      free(d->name);
-+                      free(d);
-+              }
-+              if (lstat(dev, &stb)==0 &&
-+                  S_ISLNK(stb.st_mode))
-+                      dev = "/dev/.";
-+              nftw(dev, add_dev, 10, FTW_PHYS);
-+              devlist_ready=1;
-+              did_check = 1;
-+      }
-+
-+      for (p=devlist; p; p=p->next)
-+              if (p->major == major &&
-+                  p->minor == minor) {
-+                      if (is_standard(p->name, NULL)) {
-+                              if (std == NULL ||
-+                                  strlen(p->name) < strlen(std))
-+                                      std = p->name;
-+                      } else {
-+                              if (nonstd == NULL ||
-+                                  strlen(p->name) < strlen(nonstd))
-+                                      nonstd = p->name;
-+                      }
-+              }
-+      if (!std && !nonstd && !did_check) {
-+              devlist_ready = 0;
-+              goto retry;
-+      }
-+      if (create && !std && !nonstd) {
-+              static char buf[30];
-+              snprintf(buf, sizeof(buf), "%d:%d", major, minor);
-+              nonstd = buf;
-+      }
-+
-+      return nonstd ? nonstd : std;
-+}
-+
-+unsigned long calc_csum(void *super, int bytes)
-+{
-+      unsigned long long newcsum = 0;
-+      int i;
-+      unsigned int csum;
-+      unsigned int *superc = (unsigned int*) super;
-+
-+      for(i=0; i<bytes/4; i++)
-+              newcsum+= superc[i];
-+      csum = (newcsum& 0xffffffff) + (newcsum>>32);
-+#ifdef __alpha__
-+/* The in-kernel checksum calculation is always 16bit on 
-+ * the alpha, though it is 32 bit on i386...
-+ * I wonder what it is elsewhere... (it uses and API in
-+ * a way that it shouldn't).
-+ */
-+      csum = (csum & 0xffff) + (csum >> 16);
-+      csum = (csum & 0xffff) + (csum >> 16);
-+#endif
-+      return csum;
-+}
-+
-+char *human_size(long long bytes)
-+{
-+      static char buf[30];
-+
-+      /* We convert bytes to either centi-M{ega,ibi}bytes or
-+       * centi-G{igi,ibi}bytes, with appropriate rounding,
-+       * and then print 1/100th of those as a decimal.
-+       * We allow upto 2048Megabytes before converting to
-+       * gigabytes, as that shows more precision and isn't
-+       * too large a number.
-+       * Terrabytes are not yet handled.
-+       */
-+
-+      if (bytes < 5000*1024)
-+              buf[0]=0;
-+      else if (bytes < 2*1024LL*1024LL*1024LL) {
-+              long cMiB = (bytes / ( (1LL<<20) / 200LL ) +1) /2;
-+              long cMB  = (bytes / ( 1000000LL / 200LL ) +1) /2;
-+              snprintf(buf, sizeof(buf), " (%ld.%02ld MiB %ld.%02ld MB)",
-+                      cMiB/100 , cMiB % 100,
-+                      cMB/100, cMB % 100);
-+      } else {
-+              long cGiB = (bytes / ( (1LL<<30) / 200LL ) +1) /2;
-+              long cGB  = (bytes / (1000000000LL/200LL ) +1) /2;
-+              snprintf(buf, sizeof(buf), " (%ld.%02ld GiB %ld.%02ld GB)",
-+                      cGiB/100 , cGiB % 100,
-+                      cGB/100, cGB % 100);
-+      }
-+      return buf;
-+}
-+
-+char *human_size_brief(long long bytes)
-+{
-+      static char buf[30];
-+      
-+
-+      if (bytes < 5000*1024)
-+              snprintf(buf, sizeof(buf), "%ld.%02ldKiB",
-+                      (long)(bytes>>10), (long)(((bytes&1023)*100+512)/1024)
-+                      );
-+      else if (bytes < 2*1024LL*1024LL*1024LL)
-+              snprintf(buf, sizeof(buf), "%ld.%02ldMiB",
-+                      (long)(bytes>>20),
-+                      (long)((bytes&0xfffff)+0x100000/200)/(0x100000/100)
-+                      );
-+      else
-+              snprintf(buf, sizeof(buf), "%ld.%02ldGiB",
-+                      (long)(bytes>>30),
-+                      (long)(((bytes>>10)&0xfffff)+0x100000/200)/(0x100000/100)
-+                      );
-+      return buf;
-+}
-+
-+int get_mdp_major(void)
-+{
-+static int mdp_major = -1;
-+      FILE *fl;
-+      char *w;
-+      int have_block = 0;
-+      int have_devices = 0;
-+      int last_num = -1;
-+
-+      if (mdp_major != -1)
-+              return mdp_major;
-+      fl = fopen("/proc/devices", "r");
-+      if (!fl)
-+              return -1;
-+      while ((w = conf_word(fl, 1))) {
-+              if (have_block && strcmp(w, "devices:")==0)
-+                      have_devices = 1;
-+              have_block =  (strcmp(w, "Block")==0);
-+              if (isdigit(w[0]))
-+                      last_num = atoi(w);
-+              if (have_devices && strcmp(w, "mdp")==0)
-+                      mdp_major = last_num;
-+              free(w);
-+      }
-+      fclose(fl);
-+      return mdp_major;
-+}
-+
-+int dev_open(char *dev, int flags)
-+{
-+      /* like 'open', but if 'dev' matches %d:%d, create a temp
-+       * block device and open that
-+       */
-+      char *e;
-+      int fd = -1;
-+      char devname[32];
-+      int major;
-+      int minor;
-+
-+      if (!dev) return -1;
-+
-+      major = strtoul(dev, &e, 0);
-+      if (e > dev && *e == ':' && e[1] &&
-+          (minor = strtoul(e+1, &e, 0)) >= 0 &&
-+          *e == 0) {
-+              snprintf(devname, sizeof(devname), "/dev/.tmp.md.%d:%d", major, minor);
-+              if (mknod(devname, S_IFBLK|0600, makedev(major, minor))==0) {
-+                      fd = open(devname, flags);
-+                      unlink(devname);
-+              }
-+      } else
-+              fd = open(dev, flags);
-+      return fd;
-+}
-+
-+struct superswitch *superlist[] = { &super0, &super1, NULL };
-+
-+struct supertype *super_by_version(int vers, int minor)
-+{
-+      struct supertype *st = malloc(sizeof(*st));
-+      if (!st) return st;
-+      if (vers == 0) {
-+              st->ss = &super0;
-+              st->max_devs = MD_SB_DISKS;
-+      }
-+
-+      if (vers == 1) {
-+              st->ss = &super1;
-+              st->max_devs = 384;
-+      }
-+      st->minor_version = minor;
-+      return st;
-+}
-+
-+struct supertype *guess_super(int fd)
-+{
-+      /* try each load_super to find the best match,
-+       * and return the best superswitch
-+       */
-+      struct superswitch  *ss;
-+      struct supertype *st;
-+      unsigned long besttime = 0;
-+      int bestsuper = -1;
-+      
-+      void *sbp = NULL;
-+      int i;
-+
-+      st = malloc(sizeof(*st));
-+      memset(st, 0, sizeof(*st));
-+      for (i=0 ; superlist[i]; i++) {
-+              int rv;
-+              ss = superlist[i];
-+              st->ss = NULL;
-+              rv = ss->load_super(st, fd, &sbp, NULL);
-+              if (rv == 0) {
-+                      struct mdinfo info;
-+                      ss->getinfo_super(&info, sbp);
-+                      if (bestsuper == -1 ||
-+                          besttime < info.array.ctime) {
-+                              bestsuper = i;
-+                              besttime = info.array.ctime;
-+                      }
-+                      free(sbp);
-+              }
-+      }
-+      if (bestsuper != -1) {
-+              int rv;
-+              st->ss = NULL;
-+              rv = superlist[bestsuper]->load_super(st, fd, &sbp, NULL);
-+              if (rv == 0) {
-+                      free(sbp);
-+                      return st;
-+              }
-+      }
-+      free(st);
-+      return NULL;
-+}
-+
-+/* Return size of device in bytes */
-+int get_dev_size(int fd, char *dname, unsigned long long *sizep)
-+{
-+      unsigned long long ldsize;
-+#ifdef BLKGETSIZE64
-+      if (ioctl(fd, BLKGETSIZE64, &ldsize) != 0)
-+#endif
-+      {
-+              unsigned long dsize;
-+              if (ioctl(fd, BLKGETSIZE, &dsize) == 0) {
-+                      ldsize = dsize;
-+                      ldsize <<= 9;
-+              } else {
-+                      if (dname)
-+                              fprintf(stderr, Name ": Cannot get size of %s: %s\b",
-+                                      dname, strerror(errno));
-+                      return 0;
-+              }
-+      }
-+      *sizep = ldsize;
-+      return 1;
-+}
index 27c23fe75481cea4067bceaa73a7e3e79d3a5245..654c172514bd41d62d602ac38cf5baa5f16b9036 100644 (file)
@@ -1,8 +1,3 @@
-1.18.1-mdadm.diff:
-This adds a minimal mdadm implementation to busybox for scanning for and
-activating mdraid arrays. You can blame robbat2 for this one :)
-Patch ported from 1.7.4 to 1.18.1 by Denis Kaganovich.
-
 1.18.1-mdstart.diff:
 This adds a 'mdstart' command to busybox, which is used for the activation of
 individual mdraid arrays. It originated with 1.1.3+gentoo or earlier.
diff --git a/patches/busybox/1.7.4/1.7.4-mdadm.diff b/patches/busybox/1.7.4/1.7.4-mdadm.diff
deleted file mode 100644 (file)
index deb8993..0000000
+++ /dev/null
@@ -1,5882 +0,0 @@
-Forward-port the mdadm tool from the Gentoo Busybox-1.1.3.
-Should handle all types of metadata 0.90, 1.0, 1.1, 1.2.
-If /etc/mdadm.conf does not exist in the initrd, it is created first, by
-scanning devices, and then it is used.
-
-Signed-off-by: Robin H. Johnson <robbat2@gentoo.org>
-
-diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/Config.in busybox-1.7.4+gentoo+mdadm/Config.in
---- busybox-1.7.4+gentoo/Config.in     2007-09-03 04:48:58.000000000 -0700
-+++ busybox-1.7.4+gentoo+mdadm/Config.in       2008-03-11 10:31:00.000000000 -0700
-@@ -499,2 +499,3 @@
- source e2fsprogs/Config.in
-+source mdadm/Config.in
- source modutils/Config.in
-diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/include/applets.h busybox-1.7.4+gentoo+mdadm/include/applets.h
---- busybox-1.7.4+gentoo/include/applets.h     2008-03-11 10:25:43.000000000 -0700
-+++ busybox-1.7.4+gentoo+mdadm/include/applets.h       2008-03-11 10:32:22.000000000 -0700
-@@ -223,2 +223,3 @@
- USE_MD5SUM(APPLET_ODDNAME(md5sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_NEVER, md5sum))
-+USE_MDADM(APPLET(mdadm, _BB_DIR_SBIN, _BB_SUID_NEVER))
- USE_MDEV(APPLET(mdev, _BB_DIR_SBIN, _BB_SUID_NEVER))
-diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/include/usage.h busybox-1.7.4+gentoo+mdadm/include/usage.h
---- busybox-1.7.4+gentoo/include/usage.h       2008-03-11 10:19:04.000000000 -0700
-+++ busybox-1.7.4+gentoo+mdadm/include/usage.h 2008-03-11 10:31:00.000000000 -0700
-@@ -2048,2 +2048,7 @@
-+#define mdadm_trivial_usage \
-+      ""
-+#define mdadm_full_usage \
-+      "Assemble or Examine the mdadm arrays."
-+
- #define mdev_trivial_usage \
-diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/Makefile busybox-1.7.4+gentoo+mdadm/Makefile
---- busybox-1.7.4+gentoo/Makefile      2007-11-23 20:34:41.000000000 -0800
-+++ busybox-1.7.4+gentoo+mdadm/Makefile        2008-03-11 10:31:49.000000000 -0700
-@@ -442,6 +442,7 @@
-               libpwdgrp/ \
-               loginutils/ \
-               miscutils/ \
-+              mdadm/ \
-               modutils/ \
-               networking/ \
-               networking/libiproute/ \
-diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/bitmap.h busybox-1.7.4+gentoo+mdadm/mdadm/bitmap.h
---- busybox-1.7.4+gentoo/mdadm/bitmap.h        1969-12-31 16:00:00.000000000 -0800
-+++ busybox-1.7.4+gentoo+mdadm/mdadm/bitmap.h  2008-03-11 10:31:00.000000000 -0700
-@@ -0,0 +1,287 @@
-+/*
-+ * bitmap.h: Copyright (C) Peter T. Breuer (ptb@ot.uc3m.es) 2003
-+ *
-+ * additions: Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc.
-+ */
-+#ifndef BITMAP_H
-+#define BITMAP_H 1
-+
-+#define BITMAP_MAJOR_LO 3
-+/* version 4 insists the bitmap is in little-endian order
-+ * with version 3, it is host-endian which is non-portable
-+ */
-+#define BITMAP_MAJOR_HI 4
-+#define       BITMAP_MAJOR_HOSTENDIAN 3
-+
-+#define BITMAP_MINOR 39
-+
-+/*
-+ * in-memory bitmap:
-+ *
-+ * Use 16 bit block counters to track pending writes to each "chunk".
-+ * The 2 high order bits are special-purpose, the first is a flag indicating
-+ * whether a resync is needed.  The second is a flag indicating whether a
-+ * resync is active.
-+ * This means that the counter is actually 14 bits:
-+ *
-+ * +--------+--------+------------------------------------------------+
-+ * | resync | resync |               counter                          |
-+ * | needed | active |                                                |
-+ * |  (0-1) |  (0-1) |              (0-16383)                         |
-+ * +--------+--------+------------------------------------------------+
-+ *
-+ * The "resync needed" bit is set when:
-+ *    a '1' bit is read from storage at startup.
-+ *    a write request fails on some drives
-+ *    a resync is aborted on a chunk with 'resync active' set
-+ * It is cleared (and resync-active set) when a resync starts across all drives
-+ * of the chunk.
-+ *
-+ *
-+ * The "resync active" bit is set when:
-+ *    a resync is started on all drives, and resync_needed is set.
-+ *       resync_needed will be cleared (as long as resync_active wasn't already set).
-+ * It is cleared when a resync completes.
-+ *
-+ * The counter counts pending write requests, plus the on-disk bit.
-+ * When the counter is '1' and the resync bits are clear, the on-disk
-+ * bit can be cleared aswell, thus setting the counter to 0.
-+ * When we set a bit, or in the counter (to start a write), if the fields is
-+ * 0, we first set the disk bit and set the counter to 1.
-+ *
-+ * If the counter is 0, the on-disk bit is clear and the stipe is clean
-+ * Anything that dirties the stipe pushes the counter to 2 (at least)
-+ * and sets the on-disk bit (lazily).
-+ * If a periodic sweep find the counter at 2, it is decremented to 1.
-+ * If the sweep find the counter at 1, the on-disk bit is cleared and the
-+ * counter goes to zero.
-+ *
-+ * Also, we'll hijack the "map" pointer itself and use it as two 16 bit block
-+ * counters as a fallback when "page" memory cannot be allocated:
-+ *
-+ * Normal case (page memory allocated):
-+ *
-+ *     page pointer (32-bit)
-+ *
-+ *     [ ] ------+
-+ *               |
-+ *               +-------> [   ][   ]..[   ] (4096 byte page == 2048 counters)
-+ *                          c1   c2    c2048
-+ *
-+ * Hijacked case (page memory allocation failed):
-+ *
-+ *     hijacked page pointer (32-bit)
-+ *
-+ *     [                ][              ] (no page memory allocated)
-+ *      counter #1 (16-bit) counter #2 (16-bit)
-+ *
-+ */
-+
-+#ifdef __KERNEL__
-+
-+#define PAGE_BITS (PAGE_SIZE << 3)
-+#define PAGE_BIT_SHIFT (PAGE_SHIFT + 3)
-+
-+typedef __u16 bitmap_counter_t;
-+#define COUNTER_BITS 16
-+#define COUNTER_BIT_SHIFT 4
-+#define COUNTER_BYTE_RATIO (COUNTER_BITS / 8)
-+#define COUNTER_BYTE_SHIFT (COUNTER_BIT_SHIFT - 3)
-+
-+#define NEEDED_MASK ((bitmap_counter_t) (1 << (COUNTER_BITS - 1)))
-+#define RESYNC_MASK ((bitmap_counter_t) (1 << (COUNTER_BITS - 2)))
-+#define COUNTER_MAX ((bitmap_counter_t) RESYNC_MASK - 1)
-+#define NEEDED(x) (((bitmap_counter_t) x) & NEEDED_MASK)
-+#define RESYNC(x) (((bitmap_counter_t) x) & RESYNC_MASK)
-+#define COUNTER(x) (((bitmap_counter_t) x) & COUNTER_MAX)
-+
-+/* how many counters per page? */
-+#define PAGE_COUNTER_RATIO (PAGE_BITS / COUNTER_BITS)
-+/* same, except a shift value for more efficient bitops */
-+#define PAGE_COUNTER_SHIFT (PAGE_BIT_SHIFT - COUNTER_BIT_SHIFT)
-+/* same, except a mask value for more efficient bitops */
-+#define PAGE_COUNTER_MASK  (PAGE_COUNTER_RATIO - 1)
-+
-+#define BITMAP_BLOCK_SIZE 512
-+#define BITMAP_BLOCK_SHIFT 9
-+
-+/* how many blocks per chunk? (this is variable) */
-+#define CHUNK_BLOCK_RATIO(bitmap) ((bitmap)->chunksize >> BITMAP_BLOCK_SHIFT)
-+#define CHUNK_BLOCK_SHIFT(bitmap) ((bitmap)->chunkshift - BITMAP_BLOCK_SHIFT)
-+#define CHUNK_BLOCK_MASK(bitmap) (CHUNK_BLOCK_RATIO(bitmap) - 1)
-+
-+/* when hijacked, the counters and bits represent even larger "chunks" */
-+/* there will be 1024 chunks represented by each counter in the page pointers */
-+#define PAGEPTR_BLOCK_RATIO(bitmap) \
-+                      (CHUNK_BLOCK_RATIO(bitmap) << PAGE_COUNTER_SHIFT >> 1)
-+#define PAGEPTR_BLOCK_SHIFT(bitmap) \
-+                      (CHUNK_BLOCK_SHIFT(bitmap) + PAGE_COUNTER_SHIFT - 1)
-+#define PAGEPTR_BLOCK_MASK(bitmap) (PAGEPTR_BLOCK_RATIO(bitmap) - 1)
-+
-+/*
-+ * on-disk bitmap:
-+ *
-+ * Use one bit per "chunk" (block set). We do the disk I/O on the bitmap
-+ * file a page at a time. There's a superblock at the start of the file.
-+ */
-+
-+/* map chunks (bits) to file pages - offset by the size of the superblock */
-+#define CHUNK_BIT_OFFSET(chunk) ((chunk) + (sizeof(bitmap_super_t) << 3))
-+
-+#endif
-+
-+/*
-+ * bitmap structures:
-+ */
-+
-+#define BITMAP_MAGIC 0x6d746962
-+
-+/* use these for bitmap->flags and bitmap->sb->state bit-fields */
-+enum bitmap_state {
-+      BITMAP_ACTIVE = 0x001, /* the bitmap is in use */
-+      BITMAP_STALE  = 0x002  /* the bitmap file is out of date or had -EIO */
-+};
-+
-+/* the superblock at the front of the bitmap file -- little endian */
-+typedef struct bitmap_super_s {
-+      __u32 magic;        /*  0  BITMAP_MAGIC */
-+      __u32 version;      /*  4  the bitmap major for now, could change... */
-+      __u8  uuid[16];     /*  8  128 bit uuid - must match md device uuid */
-+      __u64 events;       /* 24  event counter for the bitmap (1)*/
-+      __u64 events_cleared;/*32  event counter when last bit cleared (2) */
-+      __u64 sync_size;    /* 40  the size of the md device's sync range(3) */
-+      __u32 state;        /* 48  bitmap state information */
-+      __u32 chunksize;    /* 52  the bitmap chunk size in bytes */
-+      __u32 daemon_sleep; /* 56  seconds between disk flushes */
-+      __u32 write_behind; /* 60  number of outstanding write-behind writes */
-+
-+      __u8  pad[256 - 64]; /* set to zero */
-+} bitmap_super_t;
-+
-+/* notes:
-+ * (1) This event counter is updated before the eventcounter in the md superblock
-+ *    When a bitmap is loaded, it is only accepted if this event counter is equal
-+ *    to, or one greater than, the event counter in the superblock.
-+ * (2) This event counter is updated when the other one is *if*and*only*if* the 
-+ *    array is not degraded.  As bits are not cleared when the array is degraded,
-+ *    this represents the last time that any bits were cleared.
-+ *    If a device is being added that has an event count with this value or
-+ *    higher, it is accepted as conforming to the bitmap.
-+ * (3)This is the number of sectors represented by the bitmap, and is the range that
-+ *    resync happens across.  For raid1 and raid5/6 it is the size of individual
-+ *    devices.  For raid10 it is the size of the array.
-+ */
-+
-+#ifdef __KERNEL__
-+
-+/* the in-memory bitmap is represented by bitmap_pages */
-+struct bitmap_page {
-+      /*
-+       * map points to the actual memory page
-+       */
-+      char *map;
-+      /*
-+       * in emergencies (when map cannot be alloced), hijack the map
-+       * pointer and use it as two counters itself
-+       */
-+      unsigned int hijacked;
-+      /*
-+       * count of dirty bits on the page
-+       */ 
-+      int count;
-+};
-+
-+/* keep track of bitmap file pages that have pending writes on them */
-+struct page_list {
-+      struct list_head list;
-+      struct page *page;
-+};
-+
-+/* the main bitmap structure - one per mddev */
-+struct bitmap {
-+      struct bitmap_page *bp;
-+      unsigned long pages; /* total number of pages in the bitmap */
-+      unsigned long missing_pages; /* number of pages not yet allocated */
-+
-+      mddev_t *mddev; /* the md device that the bitmap is for */
-+
-+      int counter_bits; /* how many bits per block counter */
-+
-+      /* bitmap chunksize -- how much data does each bit represent? */
-+      unsigned long chunksize;
-+      unsigned long chunkshift; /* chunksize = 2^chunkshift (for bitops) */
-+      unsigned long chunks; /* total number of data chunks for the array */
-+
-+      /* We hold a count on the chunk currently being synced, and drop
-+       * it when the last block is started.  If the resync is aborted
-+       * midway, we need to be able to drop that count, so we remember
-+       * the counted chunk..
-+       */
-+      unsigned long syncchunk;
-+
-+      __u64   events_cleared;
-+
-+      /* bitmap spinlock */
-+      spinlock_t lock;
-+
-+      struct file *file; /* backing disk file */
-+      struct page *sb_page; /* cached copy of the bitmap file superblock */
-+      struct page **filemap; /* list of cache pages for the file */
-+      unsigned long *filemap_attr; /* attributes associated w/ filemap pages */
-+      unsigned long file_pages; /* number of pages in the file */
-+
-+      unsigned long flags;
-+
-+      /*
-+       * the bitmap daemon - periodically wakes up and sweeps the bitmap
-+       * file, cleaning up bits and flushing out pages to disk as necessary
-+       */
-+      mdk_thread_t *daemon;
-+      unsigned long daemon_sleep; /* how many seconds between updates? */
-+
-+      /*
-+       * bitmap write daemon - this daemon performs writes to the bitmap file
-+       * this thread is only needed because of a limitation in ext3 (jbd)
-+       * that does not allow a task to have two journal transactions ongoing
-+       * simultaneously (even if the transactions are for two different
-+       * filesystems) -- in the case of bitmap, that would be the filesystem
-+       * that the bitmap file resides on and the filesystem that is mounted
-+       * on the md device -- see current->journal_info in jbd/transaction.c
-+       */
-+      mdk_thread_t *write_daemon;
-+      mdk_thread_t *writeback_daemon;
-+      spinlock_t write_lock;
-+      struct semaphore write_ready;
-+      struct semaphore write_done;
-+      unsigned long writes_pending;
-+      wait_queue_head_t write_wait;
-+      struct list_head write_pages;
-+      struct list_head complete_pages;
-+      mempool_t *write_pool;
-+};
-+
-+/* the bitmap API */
-+
-+/* these are used only by md/bitmap */
-+int  bitmap_create(mddev_t *mddev);
-+void bitmap_destroy(mddev_t *mddev);
-+int  bitmap_active(struct bitmap *bitmap);
-+
-+char *file_path(struct file *file, char *buf, int count);
-+void bitmap_print_sb(struct bitmap *bitmap);
-+int bitmap_update_sb(struct bitmap *bitmap);
-+
-+int  bitmap_setallbits(struct bitmap *bitmap);
-+
-+/* these are exported */
-+void bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors);
-+void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors,
-+                   int success);
-+int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks);
-+void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int aborted);
-+void bitmap_close_sync(struct bitmap *bitmap);
-+
-+int bitmap_unplug(struct bitmap *bitmap);
-+#endif
-+
-+#endif
-diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/config.c busybox-1.7.4+gentoo+mdadm/mdadm/config.c
---- busybox-1.7.4+gentoo/mdadm/config.c        1969-12-31 16:00:00.000000000 -0800
-+++ busybox-1.7.4+gentoo+mdadm/mdadm/config.c  2008-03-11 10:31:00.000000000 -0700
-@@ -0,0 +1,824 @@
-+/*
-+ * mdadm - manage Linux "md" devices aka RAID arrays.
-+ *
-+ * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
-+ *
-+ *
-+ *    This program is free software; you can redistribute it and/or modify
-+ *    it under the terms of the GNU General Public License as published by
-+ *    the Free Software Foundation; either version 2 of the License, or
-+ *    (at your option) any later version.
-+ *
-+ *    This program is distributed in the hope that it will be useful,
-+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *    GNU General Public License for more details.
-+ *
-+ *    You should have received a copy of the GNU General Public License
-+ *    along with this program; if not, write to the Free Software
-+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ *
-+ *    Author: Neil Brown
-+ *    Email: <neilb@cse.unsw.edu.au>
-+ *    Paper: Neil Brown
-+ *           School of Computer Science and Engineering
-+ *           The University of New South Wales
-+ *           Sydney, 2052
-+ *           Australia
-+ */
-+
-+#include      "mdadm.h"
-+#include      "dlink.h"
-+#include      <sys/dir.h>
-+#include      <glob.h>
-+#include      <fnmatch.h>
-+#include      <ctype.h>
-+#include      <pwd.h>
-+#include      <grp.h>
-+
-+mapping_t r5layout[] = {
-+      { "left-asymmetric", 0},
-+      { "right-asymmetric", 1},
-+      { "left-symmetric", 2},
-+      { "right-symmetric", 3},
-+
-+      { "default", 2},
-+      { "la", 0},
-+      { "ra", 1},
-+      { "ls", 2},
-+      { "rs", 3},
-+      { NULL, 0}
-+};
-+
-+mapping_t pers[] = {
-+      { "linear", -1},
-+      { "raid0", 0},
-+      { "0", 0},
-+      { "stripe", 0},
-+      { "raid1", 1},
-+      { "1", 1},
-+      { "mirror", 1},
-+      { "raid4", 4},
-+      { "4", 4},
-+      { "raid5", 5},
-+      { "5", 5},
-+      { "multipath", -4},
-+      { "mp", -4},
-+      { "raid6", 6},
-+      { "6", 6},
-+      { "raid10", 10},
-+      { "10", 10},
-+      { "faulty", -5},
-+      { NULL, 0}
-+};
-+/*
-+ * Read the config file
-+ *
-+ * conf_get_uuids gets a list of devicename+uuid pairs
-+ * conf_get_devs gets device names after expanding wildcards
-+ *
-+ * Each keeps the returned list and frees it when asked to make
-+ * a new list.
-+ *
-+ * The format of the config file needs to be fairly extensible.
-+ * Now, arrays only have names and uuids and devices merely are.
-+ * But later arrays might want names, and devices might want superblock
-+ * versions, and who knows what else.
-+ * I like free format, abhore backslash line continuation, adore
-+ *   indentation for structure and am ok about # comments.
-+ *
-+ * So, each line that isn't blank or a #comment must either start
-+ *  with a key word, and not be indented, or must start with a
-+ *  non-key-word and must be indented.
-+ *
-+ * Keywords are DEVICE and ARRAY
-+ * DEV{ICE} introduces some devices that might contain raid components.
-+ * e.g.
-+ *   DEV style=0 /dev/sda* /dev/hd*
-+ *   DEV style=1 /dev/sd[b-f]*
-+ * ARR{AY} describes an array giving md device and attributes like uuid=whatever
-+ * e.g.
-+ *   ARRAY /dev/md0 uuid=whatever name=something
-+ * Spaces separate words on each line.  Quoting, with "" or '' protects them,
-+ * but may not wrap over lines
-+ *
-+ */
-+
-+#ifndef CONFFILE
-+#define CONFFILE "/etc/mdadm.conf"
-+#endif
-+#ifndef CONFFILE2
-+/* for Debian compatibility .... */
-+#define CONFFILE2 "/etc/mdadm/mdadm.conf"
-+#endif
-+char DefaultConfFile[] = CONFFILE;
-+char DefaultAltConfFile[] = CONFFILE2;
-+
-+enum linetype { Devices, Array, Mailaddr, Mailfrom, Program, CreateDev, Homehost, LTEnd };
-+char *keywords[] = {
-+      [Devices]  = "devices",
-+      [Array]    = "array",
-+      [Mailaddr] = "mailaddr",
-+      [Mailfrom] = "mailfrom",
-+      [Program]  = "program",
-+      [CreateDev]= "create",
-+      [Homehost] = "homehost",
-+      [LTEnd]    = NULL
-+};
-+
-+/*
-+ * match_keyword returns an index into the keywords array, or -1 for no match
-+ * case is ignored, and at least three characters must be given
-+ */
-+
-+int match_keyword(char *word)
-+{
-+      int len = strlen(word);
-+      int n;
-+    
-+      if (len < 3) return -1;
-+      for (n=0; keywords[n]; n++) {
-+              if (strncasecmp(word, keywords[n], len)==0)
-+                      return n;
-+      }
-+      return -1;
-+}
-+
-+/* conf_word gets one word from the conf file.
-+ * if "allow_key", then accept words at the start of a line,
-+ * otherwise stop when such a word is found.
-+ * We assume that the file pointer is at the end of a word, so the
-+ * next character is a space, or a newline.  If not, it is the start of a line.
-+ */
-+
-+char *conf_word(FILE *file, int allow_key)
-+{
-+      int wsize = 100;
-+      int len = 0;
-+      int c;
-+      int quote;
-+      int wordfound = 0;
-+      char *word = malloc(wsize);
-+
-+      if (!word) abort();
-+
-+      while (wordfound==0) {
-+              /* at the end of a word.. */
-+              c = getc(file);
-+              if (c == '#')
-+                      while (c != EOF && c != '\n')
-+                              c = getc(file);
-+              if (c == EOF) break;
-+              if (c == '\n') continue;
-+
-+              if (c != ' ' && c != '\t' && ! allow_key) {
-+                      ungetc(c, file);
-+                      break;
-+              }
-+              /* looks like it is safe to get a word here, if there is one */
-+              quote = 0;
-+              /* first, skip any spaces */
-+              while (c == ' ' || c == '\t')
-+                      c = getc(file);
-+              if (c != EOF && c != '\n' && c != '#') {
-+                      /* we really have a character of a word, so start saving it */
-+                      while (c != EOF && c != '\n' && (quote || (c!=' ' && c != '\t'))) {
-+                              wordfound = 1;
-+                              if (quote && c == quote) quote = 0;
-+                              else if (quote == 0 && (c == '\'' || c == '"'))
-+                                      quote = c;
-+                              else {
-+                                      if (len == wsize-1) {
-+                                              wsize += 100;
-+                                              word = realloc(word, wsize);
-+                                              if (!word) abort();
-+                                      }
-+                                      word[len++] = c;
-+                              }
-+                              c = getc(file);
-+                      }
-+              }
-+              if (c != EOF) ungetc(c, file);
-+      }
-+      word[len] = 0;
-+/*    printf("word is <%s>\n", word); */
-+      if (!wordfound) {
-+              free(word);
-+              word = NULL;
-+      }
-+      return word;
-+}
-+      
-+/*
-+ * conf_line reads one logical line from the conffile.
-+ * It skips comments and continues until it finds a line that starts
-+ * with a non blank/comment.  This character is pushed back for the next call
-+ * A doubly linked list of words is returned.
-+ * the first word will be a keyword.  Other words will have had quotes removed.
-+ */
-+
-+char *conf_line(FILE *file)
-+{
-+      char *w;
-+      char *list;
-+
-+      w = conf_word(file, 1);
-+      if (w == NULL) return NULL;
-+
-+      list = dl_strdup(w);
-+      free(w);
-+      dl_init(list);
-+
-+      while ((w = conf_word(file,0))){
-+              char *w2 = dl_strdup(w);
-+              free(w);
-+              dl_add(list, w2);
-+      }
-+/*    printf("got a line\n");*/
-+      return list;
-+}
-+
-+void free_line(char *line)
-+{
-+      char *w;
-+      for (w=dl_next(line); w != line; w=dl_next(line)) {
-+              dl_del(w);
-+              dl_free(w);
-+      }
-+      dl_free(line);
-+}
-+
-+
-+struct conf_dev {
-+    struct conf_dev *next;
-+    char *name;
-+} *cdevlist = NULL;
-+
-+mddev_dev_t load_partitions(void)
-+{
-+      FILE *f = fopen("/proc/partitions", "r");
-+      char buf[1024];
-+      mddev_dev_t rv = NULL;
-+      if (f == NULL) {
-+              fprintf(stderr, Name ": cannot open /proc/partitions\n");
-+              return NULL;
-+      }
-+      while (fgets(buf, 1024, f)) {
-+              int major, minor;
-+              char *name, *mp;
-+              mddev_dev_t d;
-+
-+              buf[1023] = '\0';
-+              if (buf[0] != ' ')
-+                      continue;
-+              major = strtoul(buf, &mp, 10);
-+              if (mp == buf || *mp != ' ') 
-+                      continue;
-+              minor = strtoul(mp, NULL, 10);
-+
-+              name = map_dev(major, minor, 1);
-+              if (!name)
-+                      continue;
-+              d = malloc(sizeof(*d));
-+              d->devname = strdup(name);
-+              d->next = rv;
-+              d->used = 0;
-+              rv = d;
-+      }
-+      fclose(f);
-+      return rv;
-+}
-+
-+struct createinfo createinfo = {
-+      .autof = 2, /* by default, create devices with standard names */
-+      .symlinks = 1,
-+#ifdef DEBIAN
-+      .gid = 6, /* disk */
-+      .mode = 0660,
-+#else
-+      .mode = 0600,
-+#endif
-+};
-+
-+int parse_auto(char *str, char *msg, int config)
-+{
-+      int autof;
-+      if (str == NULL || *str == 0)
-+              autof = 2;
-+      else if (strcasecmp(str,"no")==0)
-+              autof = 1;
-+      else if (strcasecmp(str,"yes")==0)
-+              autof = 2;
-+      else if (strcasecmp(str,"md")==0)
-+              autof = config?5:3;
-+      else {
-+              /* There might be digits, and maybe a hypen, at the end */
-+              char *e = str + strlen(str);
-+              int num = 4;
-+              int len;
-+              while (e > str && isdigit(e[-1]))
-+                      e--;
-+              if (*e) {
-+                      num = atoi(e);
-+                      if (num <= 0) num = 1;
-+              }
-+              if (e > str && e[-1] == '-')
-+                      e--;
-+              len = e - str;
-+              if ((len == 2 && strncasecmp(str,"md",2)==0)) {
-+                      autof = config ? 5 : 3;
-+              } else if ((len == 3 && strncasecmp(str,"yes",3)==0)) {
-+                      autof = 2;
-+              } else if ((len == 3 && strncasecmp(str,"mdp",3)==0)) {
-+                      autof = config ? 6 : 4;
-+              } else if ((len == 1 && strncasecmp(str,"p",1)==0) ||
-+                         (len >= 4 && strncasecmp(str,"part",4)==0)) {
-+                      autof = 6;
-+              } else {
-+                      fprintf(stderr, Name ": %s arg of \"%s\" unrecognised: use no,yes,md,mdp,part\n"
-+                              "        optionally followed by a number.\n",
-+                              msg, str);
-+                      exit(2);
-+              }
-+              autof |= num << 3;
-+      }
-+      return autof;
-+}
-+
-+static void createline(char *line)
-+{
-+      char *w;
-+      char *ep;
-+
-+      for (w=dl_next(line); w!=line; w=dl_next(w)) {
-+              if (strncasecmp(w, "auto=", 5) == 0)
-+                      createinfo.autof = parse_auto(w+5, "auto=", 1);
-+              else if (strncasecmp(w, "owner=", 6) == 0) {
-+                      if (w[6] == 0) {
-+                              fprintf(stderr, Name ": missing owner name\n");
-+                              continue;
-+                      }
-+                      createinfo.uid = strtoul(w+6, &ep, 10);
-+                      if (*ep != 0) {
-+                              struct passwd *pw;
-+                              /* must be a name */
-+                              pw = getpwnam(w+6);
-+                              if (pw)
-+                                      createinfo.uid = pw->pw_uid;
-+                              else
-+                                      fprintf(stderr, Name ": CREATE user %s not found\n", w+6);
-+                      }
-+              } else if (strncasecmp(w, "group=", 6) == 0) {
-+                      if (w[6] == 0) {
-+                              fprintf(stderr, Name ": missing group name\n");
-+                              continue;
-+                      }
-+                      createinfo.gid = strtoul(w+6, &ep, 10);
-+                      if (*ep != 0) {
-+                              struct group *gr;
-+                              /* must be a name */
-+                              gr = getgrnam(w+6);
-+                              if (gr)
-+                                      createinfo.gid = gr->gr_gid;
-+                              else
-+                                      fprintf(stderr, Name ": CREATE group %s not found\n", w+6);
-+                      }
-+              } else if (strncasecmp(w, "mode=", 5) == 0) {
-+                      if (w[5] == 0) {
-+                              fprintf(stderr, Name ": missing CREATE mode\n");
-+                              continue;
-+                      }
-+                      createinfo.mode = strtoul(w+5, &ep, 8);
-+                      if (*ep != 0) {
-+                              createinfo.mode = 0600;
-+                              fprintf(stderr, Name ": unrecognised CREATE mode %s\n",
-+                                      w+5);
-+                      }
-+              } else if (strncasecmp(w, "metadata=", 9) == 0) {
-+                      /* style of metadata to use by default */
-+                      int i;
-+                      for (i=0; superlist[i] && !createinfo.supertype; i++)
-+                              createinfo.supertype =
-+                                      superlist[i]->match_metadata_desc(w+9);
-+                      if (!createinfo.supertype)
-+                              fprintf(stderr, Name ": metadata format %s unknown, ignoring\n",
-+                                      w+9);
-+              } else if (strncasecmp(w, "symlinks=yes", 12) == 0)
-+                      createinfo.symlinks = 1;
-+              else if  (strncasecmp(w, "symlinks=no", 11) == 0)
-+                      createinfo.symlinks = 0;
-+              else {
-+                      fprintf(stderr, Name ": unrecognised word on CREATE line: %s\n",
-+                              w);
-+              }
-+      }
-+}
-+
-+void devline(char *line) 
-+{
-+      char *w;
-+      struct conf_dev *cd;
-+
-+      for (w=dl_next(line); w != line; w=dl_next(w)) {
-+              if (w[0] == '/' || strcasecmp(w, "partitions") == 0) {
-+                      cd = malloc(sizeof(*cd));
-+                      cd->name = strdup(w);
-+                      cd->next = cdevlist;
-+                      cdevlist = cd;
-+              } else {
-+                      fprintf(stderr, Name ": unreconised word on DEVICE line: %s\n",
-+                              w);
-+              }
-+      }
-+}
-+
-+mddev_ident_t mddevlist = NULL;
-+mddev_ident_t *mddevlp = &mddevlist;
-+
-+void arrayline(char *line)
-+{
-+      char *w;
-+
-+      struct mddev_ident_s mis;
-+      mddev_ident_t mi;
-+
-+      mis.uuid_set = 0;
-+      mis.super_minor = UnSet;
-+      mis.level = UnSet;
-+      mis.raid_disks = UnSet;
-+      mis.spare_disks = 0;
-+      mis.devices = NULL;
-+      mis.devname = NULL;
-+      mis.spare_group = NULL;
-+      mis.autof = 0;
-+      mis.next = NULL;
-+      mis.st = NULL;
-+      mis.bitmap_fd = -1;
-+      mis.bitmap_file = NULL;
-+      mis.name[0] = 0;
-+
-+      for (w=dl_next(line); w!=line; w=dl_next(w)) {
-+              if (w[0] == '/') {
-+                      if (mis.devname)
-+                              fprintf(stderr, Name ": only give one device per ARRAY line: %s and %s\n",
-+                                      mis.devname, w);
-+                      else mis.devname = w;
-+              } else if (strncasecmp(w, "uuid=", 5)==0 ) {
-+                      if (mis.uuid_set)
-+                              fprintf(stderr, Name ": only specify uuid once, %s ignored.\n",
-+                                      w);
-+                      else {
-+                              if (parse_uuid(w+5, mis.uuid))
-+                                      mis.uuid_set = 1;
-+                              else
-+                                      fprintf(stderr, Name ": bad uuid: %s\n", w);
-+                      }
-+              } else if (strncasecmp(w, "super-minor=", 12)==0 ) {
-+                      if (mis.super_minor != UnSet)
-+                              fprintf(stderr, Name ": only specify super-minor once, %s ignored.\n",
-+                                      w);
-+                      else {
-+                              char *endptr;
-+                              mis.super_minor= strtol(w+12, &endptr, 10);
-+                              if (w[12]==0 || endptr[0]!=0 || mis.super_minor < 0) {
-+                                      fprintf(stderr, Name ": invalid super-minor number: %s\n",
-+                                              w);
-+                                      mis.super_minor = UnSet;
-+                              }
-+                      }
-+              } else if (strncasecmp(w, "name=", 5)==0) {
-+                      if (mis.name[0])
-+                              fprintf(stderr, Name ": only specify name once, %s ignored.\n",
-+                                      w);
-+                      else if (strlen(w+5) > 32)
-+                              fprintf(stderr, Name ": name too long, ignoring %s\n", w);
-+                      else
-+                              strcpy(mis.name, w+5);
-+
-+              } else if (strncasecmp(w, "bitmap=", 7) == 0) {
-+                      if (mis.bitmap_file)
-+                              fprintf(stderr, Name ": only specify bitmap file once. %s ignored\n",
-+                                      w);
-+                      else
-+                              mis.bitmap_file = strdup(w+7);
-+
-+              } else if (strncasecmp(w, "devices=", 8 ) == 0 ) {
-+                      if (mis.devices)
-+                              fprintf(stderr, Name ": only specify devices once (use a comma separated list). %s ignored\n",
-+                                      w);
-+                      else
-+                              mis.devices = strdup(w+8);
-+              } else if (strncasecmp(w, "spare-group=", 12) == 0 ) {
-+                      if (mis.spare_group)
-+                              fprintf(stderr, Name ": only specify one spare group per array. %s ignored.\n",
-+                                      w);
-+                      else
-+                              mis.spare_group = strdup(w+12);
-+              } else if (strncasecmp(w, "level=", 6) == 0 ) {
-+                      /* this is mainly for compatability with --brief output */
-+                      mis.level = map_name(pers, w+6);
-+              } else if (strncasecmp(w, "disks=", 6) == 0 ) {
-+                      /* again, for compat */
-+                      mis.raid_disks = atoi(w+6);
-+              } else if (strncasecmp(w, "num-devices=", 12) == 0 ) {
-+                      /* again, for compat */
-+                      mis.raid_disks = atoi(w+12);
-+              } else if (strncasecmp(w, "spares=", 7) == 0 ) {
-+                      /* for warning if not all spares present */
-+                      mis.spare_disks = atoi(w+7);
-+              } else if (strncasecmp(w, "metadata=", 9) == 0) {
-+                      /* style of metadata on the devices. */
-+                      int i;
-+                      
-+                      for(i=0; superlist[i] && !mis.st; i++)
-+                              mis.st = superlist[i]->match_metadata_desc(w+9);
-+
-+                      if (!mis.st)
-+                              fprintf(stderr, Name ": metadata format %s unknown, ignored.\n", w+9);
-+              } else if (strncasecmp(w, "auto=", 5) == 0 ) {
-+                      /* whether to create device special files as needed */
-+                      mis.autof = parse_auto(w+5, "auto type", 0);
-+              } else {
-+                      fprintf(stderr, Name ": unrecognised word on ARRAY line: %s\n",
-+                              w);
-+              }
-+      }
-+      if (mis.devname == NULL)
-+              fprintf(stderr, Name ": ARRAY line with no device\n");
-+      else if (mis.uuid_set == 0 && mis.devices == NULL && mis.super_minor == UnSet && mis.name[0] == 0)
-+              fprintf(stderr, Name ": ARRAY line %s has no identity information.\n", mis.devname);
-+      else {
-+              mi = malloc(sizeof(*mi));
-+              *mi = mis;
-+              mi->devname = strdup(mis.devname);
-+              mi->next = NULL;
-+              *mddevlp = mi;
-+              mddevlp = &mi->next;
-+      }
-+}
-+
-+static char *alert_email = NULL;
-+void mailline(char *line)
-+{
-+      char *w;
-+
-+      for (w=dl_next(line); w != line ; w=dl_next(w)) {
-+              if (alert_email == NULL)
-+                      alert_email = strdup(w);
-+              else
-+                      fprintf(stderr, Name ": excess address on MAIL line: %s - ignored\n",
-+                              w);
-+      }
-+}
-+
-+static char *alert_mail_from = NULL;
-+void mailfromline(char *line)
-+{
-+      char *w;
-+
-+      for (w=dl_next(line); w != line ; w=dl_next(w)) {
-+              if (alert_mail_from == NULL)
-+                      alert_mail_from = strdup(w);
-+              else {
-+                      char *t= NULL;
-+                      asprintf(&t, "%s %s", alert_mail_from, w);
-+                      free(alert_mail_from);
-+                      alert_mail_from = t;
-+              }
-+      }
-+}
-+
-+
-+static char *alert_program = NULL;
-+void programline(char *line)
-+{
-+      char *w;
-+
-+      for (w=dl_next(line); w != line ; w=dl_next(w)) {
-+              if (alert_program == NULL)
-+                      alert_program = strdup(w);
-+              else
-+                      fprintf(stderr, Name ": excess program on PROGRAM line: %s - ignored\n",
-+                              w);
-+      }
-+}
-+
-+static char *home_host = NULL;
-+void homehostline(char *line)
-+{
-+      char *w;
-+
-+      for (w=dl_next(line); w != line ; w=dl_next(w)) {
-+              if (home_host == NULL)
-+                      home_host = strdup(w);
-+              else
-+                      fprintf(stderr, Name ": excess host name on HOMEHOST line: %s - ignored\n",
-+                              w);
-+      }
-+}
-+
-+
-+int loaded = 0;
-+
-+static char *conffile = NULL;
-+void set_conffile(char *file)
-+{
-+      conffile = file;
-+}
-+
-+void load_conffile(void)
-+{
-+      FILE *f;
-+      char *line;
-+
-+      if (loaded) return;
-+      if (conffile == NULL)
-+              conffile = DefaultConfFile;
-+
-+      if (strcmp(conffile, "none") == 0) {
-+              loaded = 1;
-+              return;
-+      }
-+      if (strcmp(conffile, "partitions")==0) {
-+              char *list = dl_strdup("DEV");
-+              dl_init(list);
-+              dl_add(list, dl_strdup("partitions"));
-+              devline(list);
-+              free_line(list);
-+              loaded = 1;
-+              return;
-+      }
-+      f = fopen(conffile, "r");
-+      /* Debian chose to relocate mdadm.conf into /etc/mdadm/.
-+       * To allow Debian users to compile from clean source and still
-+       * have a working mdadm, we read /etc/mdadm/mdadm.conf
-+       * if /etc/mdadm.conf doesn't exist
-+       */
-+      if (f == NULL &&
-+          conffile == DefaultConfFile) {
-+              f = fopen(DefaultAltConfFile, "r");
-+              if (f)
-+                      conffile = DefaultAltConfFile;
-+      }
-+      if (f == NULL)
-+              return;
-+
-+      loaded = 1;
-+      while ((line=conf_line(f))) {
-+              switch(match_keyword(line)) {
-+              case Devices:
-+                      devline(line);
-+                      break;
-+              case Array:
-+                      arrayline(line);
-+                      break;
-+              case Mailaddr:
-+                      mailline(line);
-+                      break;
-+              case Mailfrom:
-+                      mailfromline(line);
-+                      break;
-+              case Program:
-+                      programline(line);
-+                      break;
-+              case CreateDev:
-+                      createline(line);
-+                      break;
-+              case Homehost:
-+                      homehostline(line);
-+                      break;
-+              default:
-+                      fprintf(stderr, Name ": Unknown keyword %s\n", line);
-+              }
-+              free_line(line);
-+      }
-+    
-+      fclose(f);
-+
-+/*    printf("got file\n"); */
-+}
-+
-+char *conf_get_mailaddr(void)
-+{
-+      load_conffile();
-+      return alert_email;
-+}
-+
-+char *conf_get_mailfrom(void)
-+{
-+      load_conffile();
-+      return alert_mail_from;
-+}
-+
-+char *conf_get_program(void)
-+{
-+      load_conffile();
-+      return alert_program;
-+}
-+
-+char *conf_get_homehost(void)
-+{
-+      load_conffile();
-+      return home_host;
-+}
-+
-+struct createinfo *conf_get_create_info(void)
-+{
-+      load_conffile();
-+      return &createinfo;
-+}
-+
-+mddev_ident_t conf_get_ident(char *dev)
-+{
-+      mddev_ident_t rv;
-+      load_conffile();
-+      rv = mddevlist;
-+      while (dev && rv && strcmp(dev, rv->devname)!=0)
-+              rv = rv->next;
-+      return rv;
-+}
-+
-+mddev_dev_t conf_get_devs()
-+{
-+      glob_t globbuf;
-+      struct conf_dev *cd;
-+      int flags = 0;
-+      static mddev_dev_t dlist = NULL;
-+      unsigned int i;
-+
-+      while (dlist) {
-+              mddev_dev_t t = dlist;
-+              dlist = dlist->next;
-+              free(t->devname);
-+              free(t);
-+      }
-+    
-+      load_conffile();
-+
-+      if (cdevlist == NULL)
-+              /* default to 'partitions */
-+              dlist = load_partitions();
-+
-+      for (cd=cdevlist; cd; cd=cd->next) {
-+              if (strcasecmp(cd->name, "partitions")==0 && dlist == NULL)
-+                      dlist = load_partitions();
-+              else {
-+                      glob(cd->name, flags, NULL, &globbuf);
-+                      flags |= GLOB_APPEND;
-+              }
-+      }
-+      if (flags & GLOB_APPEND) {
-+              for (i=0; i<globbuf.gl_pathc; i++) {
-+                      mddev_dev_t t = malloc(sizeof(*t));
-+                      t->devname = strdup(globbuf.gl_pathv[i]);
-+                      t->next = dlist;
-+                      t->used = 0;
-+                      dlist = t;
-+/*    printf("one dev is %s\n", t->devname);*/
-+              }
-+              globfree(&globbuf);
-+      }
-+
-+      return dlist;
-+}
-+
-+int conf_test_dev(char *devname)
-+{
-+      struct conf_dev *cd;
-+      if (cdevlist == NULL)
-+              /* allow anything by default */
-+              return 1;
-+      for (cd = cdevlist ; cd ; cd = cd->next) {
-+              if (strcasecmp(cd->name, "partitions") == 0)
-+                      return 1;
-+              if (fnmatch(cd->name, devname, FNM_PATHNAME) == 0)
-+                      return 1;
-+      }
-+      return 0;
-+}
-+
-+
-+int match_oneof(char *devices, char *devname)
-+{
-+    /* check if one of the comma separated patterns in devices
-+     * matches devname
-+     */
-+
-+
-+    while (devices && *devices) {
-+      char patn[1024];
-+      char *p = devices;
-+      devices = strchr(devices, ',');
-+      if (!devices)
-+          devices = p + strlen(p);
-+      if (devices-p < 1024) {
-+              strncpy(patn, p, devices-p);
-+              patn[devices-p] = 0;
-+              if (fnmatch(patn, devname, FNM_PATHNAME)==0)
-+                      return 1;
-+      }
-+      if (*devices == ',')
-+              devices++;
-+    }
-+    return 0;
-+}
-diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/Config.in busybox-1.7.4+gentoo+mdadm/mdadm/Config.in
---- busybox-1.7.4+gentoo/mdadm/Config.in       1969-12-31 16:00:00.000000000 -0800
-+++ busybox-1.7.4+gentoo+mdadm/mdadm/Config.in 2008-03-11 10:31:00.000000000 -0700
-@@ -0,0 +1,15 @@
-+#
-+# For a description of the syntax of this configuration file,
-+# see scripts/kbuild/config-language.txt.
-+#
-+
-+menu "Linux mdadm Utilities"
-+
-+config MDADM
-+      bool "mdadm"
-+      default n
-+      help
-+        assemble or examine raid array
-+
-+endmenu
-+
-diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/dlink.c busybox-1.7.4+gentoo+mdadm/mdadm/dlink.c
---- busybox-1.7.4+gentoo/mdadm/dlink.c 1969-12-31 16:00:00.000000000 -0800
-+++ busybox-1.7.4+gentoo+mdadm/mdadm/dlink.c   2008-03-11 10:31:00.000000000 -0700
-@@ -0,0 +1,79 @@
-+
-+/* doubly linked lists */
-+/* This is free software. No strings attached. No copyright claimed */
-+
-+#include      <unistd.h>
-+#include      <stdlib.h>
-+#include      <string.h>
-+#ifdef __dietlibc__
-+char *strncpy(char *dest, const char *src, size_t n) __THROW;
-+#endif
-+#include      "dlink.h"
-+
-+
-+void *dl_head()
-+{
-+    void *h;
-+    h = dl_alloc(0);
-+    dl_next(h) = h;
-+    dl_prev(h) = h;
-+    return h;
-+}
-+
-+void dl_free(void *v)
-+{
-+    struct __dl_head *vv  = v;
-+    free(vv-1);
-+}
-+
-+void dl_init(void *v)
-+{
-+    dl_next(v) = v;
-+    dl_prev(v) = v;
-+}
-+
-+void dl_insert(void *head, void *val)
-+{
-+    dl_next(val) = dl_next(head);
-+    dl_prev(val) = head;
-+    dl_next(dl_prev(val)) = val;
-+    dl_prev(dl_next(val)) = val;
-+}
-+
-+void dl_add(void *head, void *val)
-+{
-+    dl_prev(val) = dl_prev(head);
-+    dl_next(val) = head;
-+    dl_next(dl_prev(val)) = val;
-+    dl_prev(dl_next(val)) = val;
-+}
-+
-+void dl_del(void *val)
-+{
-+    if (dl_prev(val) == 0 || dl_next(val) == 0)
-+      return;
-+    dl_prev(dl_next(val)) = dl_prev(val);
-+    dl_next(dl_prev(val)) = dl_next(val);
-+    dl_prev(val) = dl_next(val) = 0;
-+}
-+
-+char *dl_strndup(char *s, int l)
-+{
-+    char *n;
-+    if (s == NULL)
-+      return NULL;
-+    n = dl_newv(char, l+1);
-+    if (n == NULL)
-+      return NULL;
-+    else
-+    {
-+      strncpy(n, s, l);
-+      n[l] = 0;
-+      return n;
-+    }
-+}
-+
-+char *dl_strdup(char *s)
-+{
-+    return dl_strndup(s, (int)strlen(s));
-+}
-diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/dlink.h busybox-1.7.4+gentoo+mdadm/mdadm/dlink.h
---- busybox-1.7.4+gentoo/mdadm/dlink.h 1969-12-31 16:00:00.000000000 -0800
-+++ busybox-1.7.4+gentoo+mdadm/mdadm/dlink.h   2008-03-11 10:31:00.000000000 -0700
-@@ -0,0 +1,25 @@
-+
-+/* doubley linked lists */
-+/* This is free software. No strings attached. No copyright claimed */
-+
-+struct __dl_head
-+{
-+    void * dh_prev;
-+    void * dh_next;
-+};
-+
-+#define       dl_alloc(size)  ((void*)(((char*)calloc(1,(size)+sizeof(struct __dl_head)))+sizeof(struct __dl_head)))
-+#define       dl_new(t)       ((t*)dl_alloc(sizeof(t)))
-+#define       dl_newv(t,n)    ((t*)dl_alloc(sizeof(t)*n))
-+
-+#define dl_next(p) *(&(((struct __dl_head*)(p))[-1].dh_next))
-+#define dl_prev(p) *(&(((struct __dl_head*)(p))[-1].dh_prev))
-+
-+void *dl_head(void);
-+char *dl_strdup(char *);
-+char *dl_strndup(char *, int);
-+void dl_insert(void*, void*);
-+void dl_add(void*, void*);
-+void dl_del(void*);
-+void dl_free(void*);
-+void dl_init(void*);
-diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/md5.h busybox-1.7.4+gentoo+mdadm/mdadm/md5.h
---- busybox-1.7.4+gentoo/mdadm/md5.h   1969-12-31 16:00:00.000000000 -0800
-+++ busybox-1.7.4+gentoo+mdadm/mdadm/md5.h     2008-03-11 10:31:00.000000000 -0700
-@@ -0,0 +1,134 @@
-+/* Declaration of functions and data types used for MD5 sum computing
-+   library functions.
-+   Copyright (C) 1995-1997,1999-2005 Free Software Foundation, Inc.
-+
-+   NOTE: The canonical source of this file is maintained with the GNU C
-+   Library.  Bugs can be reported to bug-glibc@prep.ai.mit.edu.
-+
-+   This program is free software; you can redistribute it and/or modify it
-+   under the terms of the GNU General Public License as published by the
-+   Free Software Foundation; either version 2, or (at your option) any
-+   later version.
-+
-+   This program is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+   GNU General Public License for more details.
-+
-+   You should have received a copy of the GNU General Public License
-+   along with this program; if not, write to the Free Software Foundation,
-+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
-+
-+#ifndef _MD5_H
-+#define _MD5_H 1
-+
-+#include <stdio.h>
-+
-+# include <inttypes.h>
-+#if HAVE_STDINT_H || _LIBC
-+# include <stdint.h>
-+#endif
-+
-+#ifndef __GNUC_PREREQ
-+# if defined __GNUC__ && defined __GNUC_MINOR__
-+#  define __GNUC_PREREQ(maj, min) \
-+      ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
-+# else
-+#  define __GNUC_PREREQ(maj, min) 0
-+# endif
-+#endif
-+
-+#ifndef __THROW
-+# if defined __cplusplus && __GNUC_PREREQ (2,8)
-+#  define __THROW     throw ()
-+# else
-+#  define __THROW
-+# endif
-+#endif
-+
-+#ifndef __attribute__
-+# if ! __GNUC_PREREQ (2,8) || __STRICT_ANSI__
-+#  define __attribute__(x)
-+# endif
-+#endif
-+
-+#ifndef _LIBC
-+# define __md5_buffer md5_buffer
-+# define __md5_finish_ctx md5_finish_ctx
-+# define __md5_init_ctx md5_init_ctx
-+# define __md5_process_block md5_process_block
-+# define __md5_process_bytes md5_process_bytes
-+# define __md5_read_ctx md5_read_ctx
-+# define __md5_stream md5_stream
-+#endif
-+
-+typedef uint32_t md5_uint32;
-+
-+/* Structure to save state of computation between the single steps.  */
-+struct md5_ctx
-+{
-+  md5_uint32 A;
-+  md5_uint32 B;
-+  md5_uint32 C;
-+  md5_uint32 D;
-+
-+  md5_uint32 total[2];
-+  md5_uint32 buflen;
-+  char buffer[128] __attribute__ ((__aligned__ (__alignof__ (md5_uint32))));
-+};
-+
-+/*
-+ * The following three functions are build up the low level used in
-+ * the functions `md5_stream' and `md5_buffer'.
-+ */
-+
-+/* Initialize structure containing state of computation.
-+   (RFC 1321, 3.3: Step 3)  */
-+extern void __md5_init_ctx (struct md5_ctx *ctx) __THROW;
-+
-+/* Starting with the result of former calls of this function (or the
-+   initialization function update the context for the next LEN bytes
-+   starting at BUFFER.
-+   It is necessary that LEN is a multiple of 64!!! */
-+extern void __md5_process_block (const void *buffer, size_t len,
-+                               struct md5_ctx *ctx) __THROW;
-+
-+/* Starting with the result of former calls of this function (or the
-+   initialization function update the context for the next LEN bytes
-+   starting at BUFFER.
-+   It is NOT required that LEN is a multiple of 64.  */
-+extern void __md5_process_bytes (const void *buffer, size_t len,
-+                               struct md5_ctx *ctx) __THROW;
-+
-+/* Process the remaining bytes in the buffer and put result from CTX
-+   in first 16 bytes following RESBUF.  The result is always in little
-+   endian byte order, so that a byte-wise output yields to the wanted
-+   ASCII representation of the message digest.
-+
-+   IMPORTANT: On some systems it is required that RESBUF be correctly
-+   aligned for a 32 bits value.  */
-+extern void *__md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) __THROW;
-+
-+
-+/* Put result from CTX in first 16 bytes following RESBUF.  The result is
-+   always in little endian byte order, so that a byte-wise output yields
-+   to the wanted ASCII representation of the message digest.
-+
-+   IMPORTANT: On some systems it is required that RESBUF is correctly
-+   aligned for a 32 bits value.  */
-+extern void *__md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) __THROW;
-+
-+
-+/* Compute MD5 message digest for bytes read from STREAM.  The
-+   resulting message digest number will be written into the 16 bytes
-+   beginning at RESBLOCK.  */
-+extern int __md5_stream (FILE *stream, void *resblock) __THROW;
-+
-+/* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
-+   result is always in little endian byte order, so that a byte-wise
-+   output yields to the wanted ASCII representation of the message
-+   digest.  */
-+extern void *__md5_buffer (const char *buffer, size_t len,
-+                         void *resblock) __THROW;
-+
-+#endif /* md5.h */
-diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/mdadm.c busybox-1.7.4+gentoo+mdadm/mdadm/mdadm.c
---- busybox-1.7.4+gentoo/mdadm/mdadm.c 1969-12-31 16:00:00.000000000 -0800
-+++ busybox-1.7.4+gentoo+mdadm/mdadm/mdadm.c   2008-03-11 10:31:00.000000000 -0700
-@@ -0,0 +1,18 @@
-+/*
-+ * mdadm support for busybox.
-+ * added by Alan Hourihane <alanh@fairlite.demon.co.uk>
-+ */
-+#include <string.h>
-+
-+extern int mdassemble_main(int argc, char **argv);
-+extern int mdexamine_main(int argc, char **argv);
-+
-+int mdadm_main(int argc, char **argv) {
-+      if (argc >= 2) {
-+              if (!strncmp(argv[1],"--assemble",10))
-+                      return mdassemble_main(argc, argv);
-+              if (!strncmp(argv[1],"--examine",9))
-+                      return mdexamine_main(argc, argv);
-+      }
-+      return 0;
-+}
-diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/mdadm.h busybox-1.7.4+gentoo+mdadm/mdadm/mdadm.h
---- busybox-1.7.4+gentoo/mdadm/mdadm.h 1969-12-31 16:00:00.000000000 -0800
-+++ busybox-1.7.4+gentoo+mdadm/mdadm/mdadm.h   2008-03-11 10:31:00.000000000 -0700
-@@ -0,0 +1,540 @@
-+/*
-+ * mdadm - manage Linux "md" devices aka RAID arrays.
-+ *
-+ * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
-+ *
-+ *
-+ *    This program is free software; you can redistribute it and/or modify
-+ *    it under the terms of the GNU General Public License as published by
-+ *    the Free Software Foundation; either version 2 of the License, or
-+ *    (at your option) any later version.
-+ *
-+ *    This program is distributed in the hope that it will be useful,
-+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *    GNU General Public License for more details.
-+ *
-+ *    You should have received a copy of the GNU General Public License
-+ *    along with this program; if not, write to the Free Software
-+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ *
-+ *    Author: Neil Brown
-+ *    Email: <neilb@cse.unsw.edu.au>
-+ *    Paper: Neil Brown
-+ *           School of Computer Science and Engineering
-+ *           The University of New South Wales
-+ *           Sydney, 2052
-+ *           Australia
-+ */
-+
-+#include      <unistd.h>
-+#ifndef __dietlibc__
-+extern __off64_t lseek64 __P ((int __fd, __off64_t __offset, int __whence));
-+#else
-+# if defined(__NO_STAT64) || __WORDSIZE != 32
-+# define lseek64 lseek
-+# endif
-+#endif
-+
-+#include      <sys/types.h>
-+#include      <sys/stat.h>
-+#include      <stdlib.h>
-+#include      <time.h>
-+#include      <sys/time.h>
-+#include      <getopt.h>
-+#include      <fcntl.h>
-+#include      <stdio.h>
-+#include      <errno.h>
-+#include      <string.h>
-+#include      <syslog.h>
-+#ifdef __dietlibc__
-+#include      <strings.h>
-+/* dietlibc has deprecated random and srandom!! */
-+#define random rand
-+#define srandom srand
-+#endif
-+
-+
-+#include      <linux/kdev_t.h>
-+/*#include    <linux/fs.h> */
-+#include      <sys/mount.h>
-+#include      <asm/types.h>
-+#include      <sys/ioctl.h>
-+#define       MD_MAJOR 9
-+#define MdpMinorShift 6
-+
-+#ifndef BLKGETSIZE64
-+#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
-+#endif
-+
-+#define DEFAULT_BITMAP_CHUNK 4096
-+#define DEFAULT_BITMAP_DELAY 5
-+#define DEFAULT_MAX_WRITE_BEHIND 256
-+
-+#include      "md_u.h"
-+#include      "md_p.h"
-+#include      "bitmap.h"
-+
-+#include <endian.h>
-+/* Redhat don't like to #include <asm/byteorder.h>, and
-+ * some time include <linux/byteorder/xxx_endian.h> isn't enough,
-+ * and there is no standard conversion function so... */
-+/* And dietlibc doesn't think byteswap is ok, so.. */
-+/*  #include <byteswap.h> */
-+#define bswap_16(x) (((x) & 0x00ffU) << 8 | \
-+                   ((x) & 0xff00U) >> 8)
-+#define bswap_32(x) (((x) & 0x000000ffU) << 24 | \
-+                   ((x) & 0xff000000U) >> 24 | \
-+                   ((x) & 0x0000ff00U) << 8  | \
-+                   ((x) & 0x00ff0000U) >> 8)
-+#define bswap_64(x) (((x) & 0x00000000000000ffULL) << 56 | \
-+                   ((x) & 0xff00000000000000ULL) >> 56 | \
-+                   ((x) & 0x000000000000ff00ULL) << 40 | \
-+                   ((x) & 0x00ff000000000000ULL) >> 40 | \
-+                   ((x) & 0x0000000000ff0000ULL) << 24 | \
-+                   ((x) & 0x0000ff0000000000ULL) >> 24 | \
-+                   ((x) & 0x00000000ff000000ULL) << 8 | \
-+                   ((x) & 0x000000ff00000000ULL) >> 8)
-+
-+#if BYTE_ORDER == LITTLE_ENDIAN
-+#define       __cpu_to_le16(_x) (_x)
-+#define __cpu_to_le32(_x) (_x)
-+#define __cpu_to_le64(_x) (_x)
-+#define       __le16_to_cpu(_x) (_x)
-+#define __le32_to_cpu(_x) (_x)
-+#define __le64_to_cpu(_x) (_x)
-+#elif BYTE_ORDER == BIG_ENDIAN
-+#define       __cpu_to_le16(_x) bswap_16(_x)
-+#define __cpu_to_le32(_x) bswap_32(_x)
-+#define __cpu_to_le64(_x) bswap_64(_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)
-+#else
-+#  error "unknown endianness."
-+#endif
-+
-+
-+
-+/* general information that might be extracted from a superblock */
-+struct mdinfo {
-+      mdu_array_info_t        array;
-+      mdu_disk_info_t         disk;
-+      __u64                   events;
-+      int                     uuid[4];
-+      char                    name[33];
-+      unsigned long long      data_offset;
-+      unsigned long long      component_size;
-+      int                     reshape_active;
-+      unsigned long long      reshape_progress;
-+      int                     new_level, delta_disks, new_layout, new_chunk;
-+};
-+
-+struct createinfo {
-+      int     uid;
-+      int     gid;
-+      int     autof;
-+      int     mode;
-+      int     symlinks;
-+      struct supertype *supertype;
-+};
-+
-+#define Name "mdadm"
-+
-+enum mode {
-+      ASSEMBLE=1,
-+      BUILD,
-+      CREATE,
-+      MANAGE,
-+      MISC,
-+      MONITOR,
-+      GROW,
-+      INCREMENTAL,
-+      AUTODETECT,
-+};
-+
-+extern char short_options[];
-+extern char short_bitmap_auto_options[];
-+extern struct option long_options[];
-+extern char Version[], Usage[], Help[], OptionHelp[],
-+      Help_create[], Help_build[], Help_assemble[], Help_grow[],
-+      Help_incr[],
-+      Help_manage[], Help_misc[], Help_monitor[], Help_config[];
-+
-+/* for option that don't have short equivilents, we assign arbitrary
-+ * small numbers.  '1' means an undecorated option, so we start at '2'.
-+ */
-+enum special_options {
-+      AssumeClean = 2,
-+      BitmapChunk,
-+      WriteBehind,
-+      ReAdd,
-+      NoDegraded,
-+      Sparc22,
-+      BackupFile,
-+      HomeHost,
-+      AutoHomeHost,
-+      Symlinks,
-+      AutoDetect,
-+};
-+
-+/* structures read from config file */
-+/* List of mddevice names and identifiers
-+ * Identifiers can be:
-+ *    uuid=128-hex-uuid
-+ *    super-minor=decimal-minor-number-from-superblock
-+ *    devices=comma,separated,list,of,device,names,with,wildcards
-+ *
-+ * If multiple fields are present, the intersection of all matching
-+ * devices is considered
-+ */
-+#define UnSet (0xfffe)
-+typedef struct mddev_ident_s {
-+      char    *devname;
-+      
-+      int     uuid_set;
-+      int     uuid[4];
-+      char    name[33];
-+
-+      unsigned int super_minor;
-+
-+      char    *devices;       /* comma separated list of device
-+                               * names with wild cards
-+                               */
-+      int     level;
-+      unsigned int raid_disks;
-+      unsigned int spare_disks;
-+      struct supertype *st;
-+      int     autof;          /* 1 for normal, 2 for partitioned */
-+      char    *spare_group;
-+      char    *bitmap_file;
-+      int     bitmap_fd;
-+
-+      struct mddev_ident_s *next;
-+} *mddev_ident_t;
-+
-+/* List of device names - wildcards expanded */
-+typedef struct mddev_dev_s {
-+      char *devname;
-+      char disposition;       /* 'a' for add, 'r' for remove, 'f' for fail.
-+                               * Not set for names read from .config
-+                               */
-+      char writemostly;
-+      char re_add;
-+      char used;              /* set when used */
-+      struct mddev_dev_s *next;
-+} *mddev_dev_t;
-+
-+typedef struct mapping {
-+      char *name;
-+      int num;
-+} mapping_t;
-+
-+
-+struct mdstat_ent {
-+      char            *dev;
-+      int             devnum;
-+      int             active;
-+      char            *level;
-+      char            *pattern; /* U or up, _ for down */
-+      int             percent; /* -1 if no resync */
-+      int             resync; /* 1 if resync, 0 if recovery */
-+      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 int mddev_busy(int devnum);
-+
-+struct map_ent {
-+      struct map_ent *next;
-+      int     devnum;
-+      int     major,minor;
-+      int     uuid[4];
-+      char    *path;
-+};
-+extern int map_update(struct map_ent **mpp, int devnum, int major, int minor,
-+                    int uuid[4], char *path);
-+extern struct map_ent *map_by_uuid(struct map_ent **map, int uuid[4]);
-+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);
-+
-+/* Data structure for holding info read from sysfs */
-+struct sysdev {
-+      char    name[20];
-+      int     role;
-+      int     major, minor;
-+      unsigned long long offset, size;
-+      int     state;
-+      int     errors;
-+      struct sysdev *next;
-+};
-+struct sysarray {
-+      char    name[20];
-+      struct sysdev *devs;
-+      int     chunk;
-+      unsigned long long component_size;
-+      int     layout;
-+      int     level;
-+      int     spares;
-+      int     cache_size;
-+      int     mismatch_cnt;
-+      int     major_version, minor_version;
-+};
-+/* various details can be requested */
-+#define       GET_LEVEL       1
-+#define       GET_LAYOUT      2
-+#define       GET_COMPONENT   4
-+#define       GET_CHUNK       8
-+#define GET_CACHE     16
-+#define       GET_MISMATCH    32
-+#define       GET_VERSION     64
-+
-+#define       GET_DEVS        1024 /* gets role, major, minor */
-+#define       GET_OFFSET      2048
-+#define       GET_SIZE        4096
-+#define       GET_STATE       8192
-+#define       GET_ERROR       16384
-+
-+/* If fd >= 0, get the array it is open on,
-+ * else use devnum. >=0 -> major9. <0.....
-+ */
-+extern void sysfs_free(struct sysarray *sra);
-+extern struct sysarray *sysfs_read(int fd, int devnum, unsigned long options);
-+extern int sysfs_set_str(struct sysarray *sra, struct sysdev *dev,
-+                       char *name, char *val);
-+extern int sysfs_set_num(struct sysarray *sra, struct sysdev *dev,
-+                       char *name, unsigned long long val);
-+extern int sysfs_get_ll(struct sysarray *sra, struct sysdev *dev,
-+                      char *name, unsigned long long *val);
-+
-+
-+extern int save_stripes(int *source, unsigned long long *offsets,
-+                      int raid_disks, int chunk_size, int level, int layout,
-+                      int nwrites, int *dest,
-+                      unsigned long long start, unsigned long long length);
-+extern int restore_stripes(int *dest, unsigned long long *offsets,
-+                         int raid_disks, int chunk_size, int level, int layout,
-+                         int source, unsigned long long read_offset,
-+                         unsigned long long start, unsigned long long length);
-+
-+#ifndef Sendmail
-+#define Sendmail "/usr/lib/sendmail -t"
-+#endif
-+
-+#define SYSLOG_FACILITY LOG_DAEMON
-+
-+extern char *map_num(mapping_t *map, int num);
-+extern int map_name(mapping_t *map, char *name);
-+extern mapping_t r5layout[], pers[], modes[], faultylayout[];
-+
-+extern char *map_dev(int major, int minor, int create);
-+
-+
-+extern struct superswitch {
-+      void (*examine_super)(void *sbv, char *homehost);
-+      void (*brief_examine_super)(void *sbv);
-+      void (*detail_super)(void *sbv, char *homehost);
-+      void (*export_super)(void *sbv);
-+      void (*brief_detail_super)(void *sbv);
-+      void (*uuid_from_super)(int uuid[4], void *sbv);
-+      void (*getinfo_super)(struct mdinfo *info, void *sbv);
-+      int (*match_home)(void *sbv, char *homehost);
-+      int (*update_super)(struct mdinfo *info, void *sbv, char *update,
-+                          char *devname, int verbose,
-+                          int uuid_set, char *homehost);
-+      int (*init_super)(struct supertype *st, void **sbp, mdu_array_info_t *info, unsigned long long size, char *name, char *homehost, int *uuid);
-+      void (*add_to_super)(void *sbv, mdu_disk_info_t *dinfo);
-+      int (*store_super)(struct supertype *st, int fd, void *sbv);
-+      int (*write_init_super)(struct supertype *st, void *sbv, mdu_disk_info_t *dinfo, char *devname);
-+      int (*compare_super)(void **firstp, void *secondv);
-+      int (*load_super)(struct supertype *st, int fd, void **sbp, char *devname);
-+      struct supertype * (*match_metadata_desc)(char *arg);
-+      __u64 (*avail_size)(struct supertype *st, __u64 size);
-+      int (*add_internal_bitmap)(struct supertype *st, void *sbv, int *chunkp,
-+                                 int delay, int write_behind,
-+                                 unsigned long long size, int may_change, int major);
-+      void (*locate_bitmap)(struct supertype *st, int fd, void *sbv);
-+      int (*write_bitmap)(struct supertype *st, int fd, void *sbv);
-+      int major;
-+      int swapuuid; /* true if uuid is bigending rather than hostendian */
-+} super0, super1, *superlist[];
-+
-+struct supertype {
-+      struct superswitch *ss;
-+      int minor_version;
-+      int max_devs;
-+};
-+
-+extern struct supertype *super_by_version(int vers, int minor);
-+extern struct supertype *guess_super(int fd);
-+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);
-+
-+#if __GNUC__ < 3
-+struct stat64;
-+#endif
-+
-+#define HAVE_NFTW  we assume
-+#define HAVE_FTW
-+
-+#ifdef UCLIBC
-+# include <features.h>
-+# ifndef  __UCLIBC_HAS_FTW__
-+#  undef HAVE_FTW
-+#  undef HAVE_NFTW
-+# endif
-+#endif
-+
-+#ifdef __dietlibc__
-+# undef HAVE_NFTW
-+#endif
-+
-+#ifndef HAVE_NFTW
-+# define FTW_PHYS 1
-+# ifndef HAVE_FTW
-+  struct FTW {};
-+# endif
-+#endif
-+
-+#ifdef HAVE_FTW
-+# include <ftw.h>
-+#endif
-+
-+extern int add_dev(const char *name, const struct stat *stb, int flag, struct FTW *s);
-+
-+
-+extern int Manage_ro(char *devname, int fd, int readonly);
-+extern int Manage_runstop(char *devname, int fd, int runstop, int quiet);
-+extern int Manage_resize(char *devname, int fd, long long size, int raid_disks);
-+extern int Manage_reconfig(char *devname, int fd, int layout);
-+extern int Manage_subdevs(char *devname, int fd,
-+                        mddev_dev_t devlist, int verbose);
-+extern int autodetect(void);
-+extern int Grow_Add_device(char *devname, int fd, char *newdev);
-+extern int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int write_behind, int force);
-+extern int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
-+                      long long size,
-+                      int level, int layout, int chunksize, int raid_disks);
-+extern int Grow_restart(struct supertype *st, struct mdinfo *info,
-+                      int *fdlist, int cnt, char *backup_file);
-+
-+
-+extern int Assemble(struct supertype *st, char *mddev, int mdfd,
-+                  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 Create(struct supertype *st, char *mddev, int mdfd,
-+                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);
-+
-+extern int Detail(char *dev, int brief, int export, int test, char *homehost);
-+extern int Query(char *dev);
-+
-+extern int md_get_version(int fd);
-+extern int get_linux_version(void);
-+extern int parse_uuid(char *str, int uuid[4]);
-+extern int check_ext2(int fd, char *name);
-+extern int check_reiser(int fd, char *name);
-+extern int check_raid(int fd, char *name);
-+
-+extern int get_mdp_major(void);
-+extern int dev_open(char *dev, int flags);
-+extern int is_standard(char *dev, int *nump);
-+
-+extern int parse_auto(char *str, char *msg, int config);
-+extern mddev_ident_t conf_get_ident(char *dev);
-+extern mddev_dev_t conf_get_devs(void);
-+extern int conf_test_dev(char *devname);
-+extern struct createinfo *conf_get_create_info(void);
-+extern void set_conffile(char *file);
-+extern char *conf_get_mailaddr(void);
-+extern char *conf_get_mailfrom(void);
-+extern char *conf_get_program(void);
-+extern char *conf_get_homehost(void);
-+extern char *conf_line(FILE *file);
-+extern char *conf_word(FILE *file, int allow_key);
-+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 int same_uuid(int a[4], int b[4], int swapuuid);
-+extern void copy_uuid(void *a, int b[4], int swapuuid);
-+/* extern int compare_super(mdp_super_t *first, mdp_super_t *second);*/
-+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 char *human_size(long long bytes);
-+char *human_size_brief(long long bytes);
-+
-+extern void put_md_name(char *name);
-+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);
-+
-+
-+#define       LEVEL_MULTIPATH         (-4)
-+#define       LEVEL_LINEAR            (-1)
-+#define       LEVEL_FAULTY            (-5)
-+
-+
-+/* faulty stuff */
-+
-+#define       WriteTransient  0
-+#define       ReadTransient   1
-+#define       WritePersistent 2
-+#define       ReadPersistent  3
-+#define       WriteAll        4 /* doesn't go to device */
-+#define       ReadFixable     5
-+#define       Modes   6
-+
-+#define       ClearErrors     31
-+#define       ClearFaults     30
-+
-+#define AllPersist    100 /* internal use only */
-+#define       NoPersist       101
-+
-+#define       ModeMask        0x1f
-+#define       ModeShift       5
-+
-+
-+#ifdef __TINYC__
-+#undef minor
-+#undef major
-+#undef makedev
-+#define minor(x) ((x)&0xff)
-+#define major(x) (((x)>>8)&0xff)
-+#define makedev(M,m) (((M)<<8) | (m))
-+#endif
-+
-+/* for raid5 */
-+#define ALGORITHM_LEFT_ASYMMETRIC     0
-+#define ALGORITHM_RIGHT_ASYMMETRIC    1
-+#define ALGORITHM_LEFT_SYMMETRIC      2
-+#define ALGORITHM_RIGHT_SYMMETRIC     3
-diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/mdassemble.c busybox-1.7.4+gentoo+mdadm/mdadm/mdassemble.c
---- busybox-1.7.4+gentoo/mdadm/mdassemble.c    1969-12-31 16:00:00.000000000 -0800
-+++ busybox-1.7.4+gentoo+mdadm/mdadm/mdassemble.c      2008-03-11 10:31:00.000000000 -0700
-@@ -0,0 +1,908 @@
-+/*
-+ * mdadm - manage Linux "md" devices aka RAID arrays.
-+ *
-+ * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
-+ *
-+ *
-+ *    This program is free software; you can redistribute it and/or modify
-+ *    it under the terms of the GNU General Public License as published by
-+ *    the Free Software Foundation; either version 2 of the License, or
-+ *    (at your option) any later version.
-+ *
-+ *    This program is distributed in the hope that it will be useful,
-+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *    GNU General Public License for more details.
-+ *
-+ *    You should have received a copy of the GNU General Public License
-+ *    along with this program; if not, write to the Free Software
-+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ *
-+ *    Author: Neil Brown
-+ *    Email: <neilb@cse.unsw.edu.au>
-+ *    Paper: Neil Brown
-+ *           School of Computer Science and Engineering
-+ *           The University of New South Wales
-+ *           Sydney, 2052
-+ *           Australia
-+ */
-+
-+#include      "mdadm.h"
-+#include      <ctype.h>
-+
-+static int name_matches(char *found, char *required, char *homehost)
-+{
-+      /* See if the name found matches the required name, possibly
-+       * prefixed with 'homehost'
-+       */
-+      char fnd[33];
-+
-+      strncpy(fnd, found, 32);
-+      fnd[32] = 0;
-+      if (strcmp(found, required)==0)
-+              return 1;
-+      if (homehost) {
-+              int l = strlen(homehost);
-+              if (l < 32 && fnd[l] == ':' &&
-+                  strcmp(fnd+l+1, required)==0)
-+                      return 1;
-+      }
-+      return 0;
-+}
-+
-+int open_mddev(char *dev, int autof/*unused */)
-+{
-+      int mdfd = open(dev, O_RDWR, 0);
-+      if (mdfd < 0)
-+              fprintf(stderr, Name ": error opening %s: %s\n",
-+                      dev, strerror(errno));
-+      else if (md_get_version(mdfd) <= 0) {
-+              fprintf(stderr, Name ": %s does not appear to be an md device\n",
-+                      dev);
-+              close(mdfd);
-+              mdfd = -1;
-+      }
-+      return mdfd;
-+}
-+
-+int Assemble(struct supertype *st, char *mddev, int mdfd,
-+           mddev_ident_t ident,
-+           mddev_dev_t devlist, char *backup_file,
-+           int readonly, int runstop,
-+           char *update, char *homehost,
-+           int verbose, int force)
-+{
-+      /*
-+       * The task of Assemble is to find a collection of
-+       * devices that should (according to their superblocks)
-+       * form an array, and to give this collection to the MD driver.
-+       * In Linux-2.4 and later, this involves submitting a
-+       * SET_ARRAY_INFO ioctl with no arg - to prepare
-+       * the array - and then submit a number of
-+       * ADD_NEW_DISK ioctls to add disks into
-+       * the array.  Finally RUN_ARRAY might
-+       * be submitted to start the array.
-+       *
-+       * Much of the work of Assemble is in finding and/or
-+       * checking the disks to make sure they look right.
-+       *
-+       * If mddev is not set, then scan must be set and we
-+       *  read through the config file for dev+uuid mapping
-+       *  We recurse, setting mddev, for each device that
-+       *    - isn't running
-+       *    - has a valid uuid (or any uuid if !uuidset)
-+       *
-+       * If mddev is set, we try to determine state of md.
-+       *   check version - must be at least 0.90.0
-+       *   check kernel version.  must be at least 2.4.
-+       *    If not, we can possibly fall back on START_ARRAY
-+       *   Try to GET_ARRAY_INFO.
-+       *     If possible, give up
-+       *     If not, try to STOP_ARRAY just to make sure
-+       *
-+       * If !uuidset and scan, look in conf-file for uuid
-+       *       If not found, give up
-+       * If !devlist and scan and uuidset, get list of devs from conf-file
-+       *
-+       * For each device:
-+       *   Check superblock - discard if bad
-+       *   Check uuid (set if we don't have one) - discard if no match
-+       *   Check superblock similarity if we have a superblock - discard if different
-+       *   Record events, devicenum
-+       * This should give us a list of devices for the array
-+       * We should collect the most recent event number
-+       *
-+       * Count disks with recent enough event count
-+       * While force && !enough disks
-+       *    Choose newest rejected disks, update event count
-+       *     mark clean and rewrite superblock
-+       * If recent kernel:
-+       *    SET_ARRAY_INFO
-+       *    foreach device with recent events : ADD_NEW_DISK
-+       *    if runstop == 1 || "enough" disks and runstop==0 -> RUN_ARRAY
-+       * If old kernel:
-+       *    Check the device numbers in superblock are right
-+       *    update superblock if any changes
-+       *    START_ARRAY
-+       *
-+       */
-+      int clean = 0;
-+      int old_linux = 0;
-+      int vers = 0; /* Keep gcc quite - it really is initialised */
-+      void *first_super = NULL, *super = NULL;
-+      struct {
-+              char *devname;
-+              unsigned int major, minor;
-+              unsigned int oldmajor, oldminor;
-+              long long events;
-+              int uptodate;
-+              int state;
-+              int raid_disk;
-+              int disk_nr;
-+      } *devices;
-+      int *best = NULL; /* indexed by raid_disk */
-+      unsigned int bestcnt = 0;
-+      int devcnt = 0;
-+      unsigned int okcnt, sparecnt;
-+      unsigned int req_cnt;
-+      unsigned int i;
-+      int most_recent = 0;
-+      int chosen_drive;
-+      int change = 0;
-+      int inargv = 0;
-+      int bitmap_done;
-+      int start_partial_ok = (runstop >= 0) && (force || devlist==NULL || mdfd < 0);
-+      unsigned int num_devs;
-+      mddev_dev_t tmpdev;
-+      struct mdinfo info;
-+      char *avail;
-+      int nextspare = 0;
-+
-+      if (mdfd < 0)
-+              return 2;
-+
-+      if (get_linux_version() < 2004000)
-+              old_linux = 1;
-+
-+      if (mdfd >= 0) {
-+              vers = md_get_version(mdfd);
-+              if (vers <= 0) {
-+                      fprintf(stderr, Name ": %s appears not to be an md device.\n", mddev);
-+                      return 1;
-+              }
-+              if (vers < 9000) {
-+                      fprintf(stderr, Name ": Assemble requires driver version 0.90.0 or later.\n"
-+                              "    Upgrade your kernel or try --build\n");
-+                      return 1;
-+              }
-+
-+              if (ioctl(mdfd, GET_ARRAY_INFO, &info.array)>=0) {
-+                      fprintf(stderr, Name ": device %s already active - cannot assemble it\n",
-+                              mddev);
-+                      return 1;
-+              }
-+              ioctl(mdfd, STOP_ARRAY, NULL); /* just incase it was started but has no content */
-+      }
-+      /*
-+       * If any subdevs are listed, then any that don't
-+       * match ident are discarded.  Remainder must all match and
-+       * become the array.
-+       * If no subdevs, then we scan all devices in the config file, but
-+       * there must be something in the identity
-+       */
-+
-+      if (!devlist &&
-+          ident->uuid_set == 0 &&
-+          ident->super_minor < 0 &&
-+          ident->devices == NULL) {
-+              fprintf(stderr, Name ": No identity information available for %s - cannot assemble.\n",
-+                      mddev ? mddev : "further assembly");
-+              return 1;
-+      }
-+      if (devlist == NULL)
-+              devlist = conf_get_devs();
-+      else if (mdfd >= 0)
-+              inargv = 1;
-+
-+      tmpdev = devlist; num_devs = 0;
-+      while (tmpdev) {
-+              if (tmpdev->used)
-+                      tmpdev->used = 2;
-+              else
-+                      num_devs++;
-+              tmpdev = tmpdev->next;
-+      }
-+      devices = malloc(num_devs * sizeof(*devices));
-+
-+      if (!st && ident->st) st = ident->st;
-+
-+      if (verbose>0)
-+          fprintf(stderr, Name ": looking for devices for %s\n",
-+                  mddev ? mddev : "further assembly");
-+
-+      /* first walk the list of devices to find a consistent set
-+       * that match the criterea, if that is possible.
-+       * We flag the one we like with 'used'.
-+       */
-+      for (tmpdev = devlist;
-+           tmpdev;
-+           tmpdev = tmpdev->next) {
-+              char *devname = tmpdev->devname;
-+              int dfd;
-+              struct stat stb;
-+              struct supertype *tst = st;
-+
-+              if (tmpdev->used > 1) continue;
-+
-+              if (ident->devices &&
-+                  !match_oneof(ident->devices, devname)) {
-+                      if ((inargv && verbose>=0) || verbose > 0)
-+                              fprintf(stderr, Name ": %s is not one of %s\n", devname, ident->devices);
-+                      continue;
-+              }
-+
-+              if (super) {
-+                      free(super);
-+                      super = NULL;
-+              }
-+              
-+              dfd = dev_open(devname, O_RDONLY|O_EXCL);
-+              if (dfd < 0) {
-+                      if ((inargv && verbose >= 0) || verbose > 0)
-+                              fprintf(stderr, Name ": cannot open device %s: %s\n",
-+                                      devname, strerror(errno));
-+                      tmpdev->used = 2;
-+              } else if (fstat(dfd, &stb)< 0) {
-+                      /* Impossible! */
-+                      fprintf(stderr, Name ": fstat failed for %s: %s\n",
-+                              devname, strerror(errno));
-+                      tmpdev->used = 2;
-+              } else if ((stb.st_mode & S_IFMT) != S_IFBLK) {
-+                      fprintf(stderr, Name ": %s is not a block device.\n",
-+                              devname);
-+                      tmpdev->used = 2;
-+              } else if (!tst && (tst = guess_super(dfd)) == NULL) {
-+                      if ((inargv && verbose >= 0) || verbose > 0)
-+                              fprintf(stderr, Name ": no recogniseable superblock on %s\n",
-+                                      devname);
-+                      tmpdev->used = 2;
-+              } else if (tst->ss->load_super(tst,dfd, &super, NULL)) {
-+                      if ((inargv && verbose >= 0) || verbose > 0)
-+                              fprintf( stderr, Name ": no RAID superblock on %s\n",
-+                                       devname);
-+              } else {
-+                      tst->ss->getinfo_super(&info, super);
-+              }
-+              if (dfd >= 0) close(dfd);
-+
-+              if (ident->uuid_set && (!update || strcmp(update, "uuid")!= 0) &&
-+                  (!super || same_uuid(info.uuid, ident->uuid, tst->ss->swapuuid)==0)) {
-+                      if ((inargv && verbose >= 0) || verbose > 0)
-+                              fprintf(stderr, Name ": %s has wrong uuid.\n",
-+                                      devname);
-+                      continue;
-+              }
-+              if (ident->name[0] && (!update || strcmp(update, "name")!= 0) &&
-+                  (!super || name_matches(info.name, ident->name, homehost)==0)) {
-+                      if ((inargv && verbose >= 0) || verbose > 0)
-+                              fprintf(stderr, Name ": %s has wrong name.\n",
-+                                      devname);
-+                      continue;
-+              }
-+              if (ident->super_minor != UnSet &&
-+                  (!super || ident->super_minor != info.array.md_minor)) {
-+                      if ((inargv && verbose >= 0) || verbose > 0)
-+                              fprintf(stderr, Name ": %s has wrong super-minor.\n",
-+                                      devname);
-+                      continue;
-+              }
-+              if (ident->level != UnSet &&
-+                  (!super|| ident->level != info.array.level)) {
-+                      if ((inargv && verbose >= 0) || verbose > 0)
-+                              fprintf(stderr, Name ": %s has wrong raid level.\n",
-+                                      devname);
-+                      continue;
-+              }
-+              if (ident->raid_disks != UnSet &&
-+                  (!super || ident->raid_disks!= info.array.raid_disks)) {
-+                      if ((inargv && verbose >= 0) || verbose > 0)
-+                              fprintf(stderr, Name ": %s requires wrong number of drives.\n",
-+                                      devname);
-+                      continue;
-+              }
-+              if (mdfd < 0) {
-+                      if (tst == NULL || super == NULL)
-+                              continue;
-+                      if (update == NULL &&
-+                          tst->ss->match_home(super, homehost)==0) {
-+                              if ((inargv && verbose >= 0) || verbose > 0)
-+                                      fprintf(stderr, Name ": %s is not built for host %s.\n",
-+                                              devname, homehost);
-+                              /* Auto-assemble, and this is not a usable host */
-+                              /* if update != NULL, we are updating the host
-+                               * name... */
-+                              continue;
-+                      }
-+              }
-+              /* If we are this far, then we are nearly commited to this device.
-+               * If the super_block doesn't exist, or doesn't match others,
-+               * then we probably cannot continue
-+               * However if one of the arrays is for the homehost, and
-+               * the other isn't that can disambiguate.
-+               */
-+
-+              if (!super) {
-+                      fprintf(stderr, Name ": %s has no superblock - assembly aborted\n",
-+                              devname);
-+                      free(first_super);
-+                      return 1;
-+              }
-+
-+              if (st == NULL)
-+                      st = tst;
-+              if (st->ss != tst->ss ||
-+                  st->minor_version != tst->minor_version ||
-+                  st->ss->compare_super(&first_super, super) != 0) {
-+                      /* Some mismatch. If exactly one array matches this host,
-+                       * we can resolve on that one.
-+                       * Or, if we are auto assembling, we just ignore the second
-+                       * for now.
-+                       */
-+                      if (mdfd < 0)
-+                              continue;
-+                      if (homehost) {
-+                              int first = st->ss->match_home(first_super, homehost);
-+                              int last = tst->ss->match_home(super, homehost);
-+                              if (first+last == 1) {
-+                                      /* We can do something */
-+                                      if (first) {/* just ignore this one */
-+                                              if ((inargv && verbose >= 0) || verbose > 0)
-+                                                      fprintf(stderr, Name ": %s misses out due to wrong homehost\n",
-+                                                              devname);
-+                                              continue;
-+                                      } else { /* reject all those sofar */
-+                                              mddev_dev_t td;
-+                                              if ((inargv && verbose >= 0) || verbose > 0)
-+                                                      fprintf(stderr, Name ": %s overrides previous devices due to good homehost\n",
-+                                                              devname);
-+                                              for (td=devlist; td != tmpdev; td=td->next)
-+                                                      if (td->used == 1)
-+                                                              td->used = 0;
-+                                              tmpdev->used = 1;
-+                                              continue;
-+                                      }
-+                              }
-+                      }
-+                      fprintf(stderr, Name ": superblock on %s doesn't match others - assembly aborted\n",
-+                              devname);
-+                      free(super);
-+                      free(first_super);
-+                      return 1;
-+              }
-+
-+              tmpdev->used = 1;
-+      }
-+
-+      /* Ok, no bad inconsistancy, we can try updating etc */
-+      bitmap_done = 0;
-+      for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) if (tmpdev->used == 1) {
-+              char *devname = tmpdev->devname;
-+              struct stat stb;
-+              /* looks like a good enough match to update the super block if needed */
-+              {
-+                      int dfd;
-+                      dfd = dev_open(devname, O_RDWR|O_EXCL);
-+
-+                      remove_partitions(dfd);
-+
-+                      if (super) {
-+                              free(super);
-+                              super = NULL;
-+                      }
-+
-+                      st->ss->load_super(st, dfd, &super, NULL);
-+                      st->ss->getinfo_super(&info, super);
-+                      close(dfd);
-+              }
-+
-+              stat(devname, &stb);
-+
-+              if (verbose > 0)
-+                      fprintf(stderr, Name ": %s is identified as a member of %s, slot %d.\n",
-+                              devname, mddev, info.disk.raid_disk);
-+              devices[devcnt].devname = devname;
-+              devices[devcnt].major = major(stb.st_rdev);
-+              devices[devcnt].minor = minor(stb.st_rdev);
-+              devices[devcnt].oldmajor = info.disk.major;
-+              devices[devcnt].oldminor = info.disk.minor;
-+              devices[devcnt].events = info.events;
-+              devices[devcnt].raid_disk = info.disk.raid_disk;
-+              devices[devcnt].disk_nr = info.disk.number;
-+              devices[devcnt].uptodate = 0;
-+              devices[devcnt].state = info.disk.state;
-+              if (most_recent < devcnt) {
-+                      if (devices[devcnt].events
-+                          > devices[most_recent].events)
-+                              most_recent = devcnt;
-+              }
-+              if (info.array.level == -4)
-+                      /* with multipath, the raid_disk from the superblock is meaningless */
-+                      i = devcnt;
-+              else
-+                      i = devices[devcnt].raid_disk;
-+              if (i+1 == 0) {
-+                      if (nextspare < info.array.raid_disks)
-+                              nextspare = info.array.raid_disks;
-+                      i = nextspare++;
-+              } else {
-+                      if (i >= info.array.raid_disks &&
-+                          i >= nextspare)
-+                              nextspare = i+1;
-+              }
-+              if (i < 10000) {
-+                      if (i >= bestcnt) {
-+                              unsigned int newbestcnt = i+10;
-+                              int *newbest = malloc(sizeof(int)*newbestcnt);
-+                              unsigned int c;
-+                              for (c=0; c < newbestcnt; c++)
-+                                      if (c < bestcnt)
-+                                              newbest[c] = best[c];
-+                                      else
-+                                              newbest[c] = -1;
-+                              if (best)free(best);
-+                              best = newbest;
-+                              bestcnt = newbestcnt;
-+                      }
-+                      if (best[i] >=0 &&
-+                          devices[best[i]].events == devices[devcnt].events &&
-+                          devices[best[i]].minor != devices[devcnt].minor &&
-+                          st->ss->major == 0 &&
-+                          info.array.level != -4) {
-+                              /* two different devices with identical superblock.
-+                               * Could be a mis-detection caused by overlapping
-+                               * partitions.  fail-safe.
-+                               */
-+                              fprintf(stderr, Name ": WARNING %s and %s appear"
-+                                      " to have very similar superblocks.\n"
-+                                      "      If they are really different, "
-+                                      "please --zero the superblock on one\n"
-+                                      "      If they are the same or overlap,"
-+                                      " please remove one from %s.\n",
-+                                      devices[best[i]].devname, devname,
-+                                      inargv ? "the list" :
-+                                         "the\n      DEVICE list in mdadm.conf"
-+                                      );
-+                              return 1;
-+                      }
-+                      if (best[i] == -1
-+                          || devices[best[i]].events < devices[devcnt].events)
-+                              best[i] = devcnt;
-+              }
-+              devcnt++;
-+      }
-+
-+      if (super)
-+              free(super);
-+      super = NULL;
-+
-+      if (update && strcmp(update, "byteorder")==0)
-+              st->minor_version = 90;
-+
-+      if (devcnt == 0) {
-+              fprintf(stderr, Name ": no devices found for %s\n",
-+                      mddev);
-+              free(first_super);
-+              return 1;
-+      }
-+
-+      st->ss->getinfo_super(&info, first_super);
-+      clean = info.array.state & 1;
-+
-+      /* now we have some devices that might be suitable.
-+       * I wonder how many
-+       */
-+      avail = malloc(info.array.raid_disks);
-+      memset(avail, 0, info.array.raid_disks);
-+      okcnt = 0;
-+      sparecnt=0;
-+      for (i=0; i< bestcnt ;i++) {
-+              int j = best[i];
-+              int event_margin = 1; /* always allow a difference of '1'
-+                                     * like the kernel does
-+                                     */
-+              if (j < 0) continue;
-+              /* note: we ignore error flags in multipath arrays
-+               * as they don't make sense
-+               */
-+              if (info.array.level != -4)
-+                      if (!(devices[j].state & (1<<MD_DISK_SYNC))) {
-+                              if (!(devices[j].state & (1<<MD_DISK_FAULTY)))
-+                                      sparecnt++;
-+                              continue;
-+                      }
-+              if (devices[j].events+event_margin >=
-+                  devices[most_recent].events) {
-+                      devices[j].uptodate = 1;
-+                      if (i < info.array.raid_disks) {
-+                              okcnt++;
-+                              avail[i]=1;
-+                      } else
-+                              sparecnt++;
-+              }
-+      }
-+      while (force && !enough(info.array.level, info.array.raid_disks,
-+                              info.array.layout, 1,
-+                              avail, okcnt)) {
-+              /* Choose the newest best drive which is
-+               * not up-to-date, update the superblock
-+               * and add it.
-+               */
-+              int fd;
-+              long long current_events;
-+              chosen_drive = -1;
-+              for (i=0; i<info.array.raid_disks && i < bestcnt; i++) {
-+                      int j = best[i];
-+                      if (j>=0 &&
-+                          !devices[j].uptodate &&
-+                          devices[j].events > 0 &&
-+                          (chosen_drive < 0 ||
-+                           devices[j].events > devices[chosen_drive].events))
-+                              chosen_drive = j;
-+              }
-+              if (chosen_drive < 0)
-+                      break;
-+              current_events = devices[chosen_drive].events;
-+      add_another:
-+              if (verbose >= 0)
-+                      fprintf(stderr, Name ": forcing event count in %s(%d) from %d upto %d\n",
-+                              devices[chosen_drive].devname, devices[chosen_drive].raid_disk,
-+                              (int)(devices[chosen_drive].events),
-+                              (int)(devices[most_recent].events));
-+              fd = dev_open(devices[chosen_drive].devname, O_RDWR|O_EXCL);
-+              if (fd < 0) {
-+                      fprintf(stderr, Name ": Couldn't open %s for write - not updating\n",
-+                              devices[chosen_drive].devname);
-+                      devices[chosen_drive].events = 0;
-+                      continue;
-+              }
-+              if (st->ss->load_super(st,fd, &super, NULL)) {
-+                      close(fd);
-+                      fprintf(stderr, Name ": RAID superblock disappeared from %s - not updating.\n",
-+                              devices[chosen_drive].devname);
-+                      devices[chosen_drive].events = 0;
-+                      continue;
-+              }
-+              info.events = devices[most_recent].events;
-+              st->ss->update_super(&info, super, "force-one",
-+                                   devices[chosen_drive].devname, verbose,
-+                                   0, NULL);
-+
-+              if (st->ss->store_super(st, fd, super)) {
-+                      close(fd);
-+                      fprintf(stderr, Name ": Could not re-write superblock on %s\n",
-+                              devices[chosen_drive].devname);
-+                      devices[chosen_drive].events = 0;
-+                      free(super);
-+                      continue;
-+              }
-+              close(fd);
-+              devices[chosen_drive].events = devices[most_recent].events;
-+              devices[chosen_drive].uptodate = 1;
-+              avail[chosen_drive] = 1;
-+              okcnt++;
-+              free(super);
-+
-+              /* If there are any other drives of the same vintage,
-+               * add them in as well.  We can't lose and we might gain
-+               */
-+              for (i=0; i<info.array.raid_disks && i < bestcnt ; i++) {
-+                      int j = best[i];
-+                      if (j >= 0 &&
-+                          !devices[j].uptodate &&
-+                          devices[j].events > 0 &&
-+                          devices[j].events == current_events) {
-+                              chosen_drive = j;
-+                              goto add_another;
-+                      }
-+              }
-+      }
-+
-+      /* Now we want to look at the superblock which the kernel will base things on
-+       * and compare the devices that we think are working with the devices that the
-+       * superblock thinks are working.
-+       * If there are differences and --force is given, then update this chosen
-+       * superblock.
-+       */
-+      chosen_drive = -1;
-+      super = NULL;
-+      for (i=0; chosen_drive < 0 && i<bestcnt; i++) {
-+              int j = best[i];
-+              int fd;
-+
-+              if (j<0)
-+                      continue;
-+              if (!devices[j].uptodate)
-+                      continue;
-+              chosen_drive = j;
-+              if ((fd=dev_open(devices[j].devname, O_RDONLY|O_EXCL))< 0) {
-+                      fprintf(stderr, Name ": Cannot open %s: %s\n",
-+                              devices[j].devname, strerror(errno));
-+                      return 1;
-+              }
-+              if (st->ss->load_super(st,fd, &super, NULL)) {
-+                      close(fd);
-+                      fprintf(stderr, Name ": RAID superblock has disappeared from %s\n",
-+                              devices[j].devname);
-+                      return 1;
-+              }
-+              close(fd);
-+      }
-+      if (super == NULL) {
-+              fprintf(stderr, Name ": No suitable drives found for %s\n", mddev);
-+              return 1;
-+      }
-+      st->ss->getinfo_super(&info, super);
-+      for (i=0; i<bestcnt; i++) {
-+              int j = best[i];
-+              unsigned int desired_state;
-+
-+              if (i < info.array.raid_disks)
-+                      desired_state = (1<<MD_DISK_ACTIVE) | (1<<MD_DISK_SYNC);
-+              else
-+                      desired_state = 0;
-+
-+              if (j<0)
-+                      continue;
-+              if (!devices[j].uptodate)
-+                      continue;
-+              info.disk.number = devices[j].disk_nr;
-+              info.disk.raid_disk = i;
-+              info.disk.state = desired_state;
-+
-+              if (devices[j].uptodate &&
-+                  st->ss->update_super(&info, super, "assemble", NULL, verbose, 0, NULL)) {
-+                      if (force) {
-+                              if (verbose >= 0)
-+                                      fprintf(stderr, Name ": "
-+                                              "clearing FAULTY flag for device %d in %s for %s\n",
-+                                              j, mddev, devices[j].devname);
-+                              change = 1;
-+                      } else {
-+                              if (verbose >= -1)
-+                                      fprintf(stderr, Name ": "
-+                                              "device %d in %s has wrong state in superblock, but %s seems ok\n",
-+                                              i, mddev, devices[j].devname);
-+                      }
-+              }
-+#if 0
-+              if (!devices[j].uptodate &&
-+                  !(super.disks[i].state & (1 << MD_DISK_FAULTY))) {
-+                      fprintf(stderr, Name ": devices %d of %s is not marked FAULTY in superblock, but cannot be found\n",
-+                              i, mddev);
-+              }
-+#endif
-+      }
-+      if (force && !clean &&
-+          !enough(info.array.level, info.array.raid_disks,
-+                  info.array.layout, clean,
-+                  avail, okcnt)) {
-+              change += st->ss->update_super(&info, super, "force-array",
-+                                      devices[chosen_drive].devname, verbose,
-+                                             0, NULL);
-+              clean = 1;
-+      }
-+
-+      if (change) {
-+              int fd;
-+              fd = dev_open(devices[chosen_drive].devname, O_RDWR|O_EXCL);
-+              if (fd < 0) {
-+                      fprintf(stderr, Name ": Could not open %s for write - cannot Assemble array.\n",
-+                              devices[chosen_drive].devname);
-+                      return 1;
-+              }
-+              if (st->ss->store_super(st, fd, super)) {
-+                      close(fd);
-+                      fprintf(stderr, Name ": Could not re-write superblock on %s\n",
-+                              devices[chosen_drive].devname);
-+                      return 1;
-+              }
-+              close(fd);
-+      }
-+
-+      /* count number of in-sync devices according to the superblock.
-+       * We must have this number to start the array without -s or -R
-+       */
-+      req_cnt = info.array.working_disks;
-+
-+      /* Almost ready to actually *do* something */
-+      if (!old_linux) {
-+              int rv;
-+              if ((vers % 100) >= 1) { /* can use different versions */
-+                      mdu_array_info_t inf;
-+                      memset(&inf, 0, sizeof(inf));
-+                      inf.major_version = st->ss->major;
-+                      inf.minor_version = st->minor_version;
-+                      rv = ioctl(mdfd, SET_ARRAY_INFO, &inf);
-+              } else
-+                      rv = ioctl(mdfd, SET_ARRAY_INFO, NULL);
-+
-+              if (rv) {
-+                      fprintf(stderr, Name ": SET_ARRAY_INFO failed for %s: %s\n",
-+                              mddev, strerror(errno));
-+                      return 1;
-+              }
-+              if (ident->bitmap_fd >= 0) {
-+                      if (ioctl(mdfd, SET_BITMAP_FILE, ident->bitmap_fd) != 0) {
-+                              fprintf(stderr, Name ": SET_BITMAP_FILE failed.\n");
-+                              return 1;
-+                      }
-+              } else if (ident->bitmap_file) {
-+                      /* From config file */
-+                      int bmfd = open(ident->bitmap_file, O_RDWR);
-+                      if (bmfd < 0) {
-+                              fprintf(stderr, Name ": Could not open bitmap file %s\n",
-+                                      ident->bitmap_file);
-+                              return 1;
-+                      }
-+                      if (ioctl(mdfd, SET_BITMAP_FILE, bmfd) != 0) {
-+                              fprintf(stderr, Name ": Failed to set bitmapfile for %s\n", mddev);
-+                              close(bmfd);
-+                              return 1;
-+                      }
-+                      close(bmfd);
-+              }
-+
-+              /* First, add the raid disks, but add the chosen one last */
-+              for (i=0; i<= bestcnt; i++) {
-+                      int j;
-+                      if (i < bestcnt) {
-+                              j = best[i];
-+                              if (j == chosen_drive)
-+                                      continue;
-+                      } else
-+                              j = chosen_drive;
-+
-+                      if (j >= 0 /* && devices[j].uptodate */) {
-+                              mdu_disk_info_t disk;
-+                              memset(&disk, 0, sizeof(disk));
-+                              disk.major = devices[j].major;
-+                              disk.minor = devices[j].minor;
-+                              if (ioctl(mdfd, ADD_NEW_DISK, &disk)!=0) {
-+                                      fprintf(stderr, Name ": failed to add %s to %s: %s\n",
-+                                              devices[j].devname,
-+                                              mddev,
-+                                              strerror(errno));
-+                                      if (i < info.array.raid_disks || i == bestcnt)
-+                                              okcnt--;
-+                                      else
-+                                              sparecnt--;
-+                              } else if (verbose > 0)
-+                                      fprintf(stderr, Name ": added %s to %s as %d\n",
-+                                              devices[j].devname, mddev, devices[j].raid_disk);
-+                      } else if (verbose > 0 && i < info.array.raid_disks)
-+                              fprintf(stderr, Name ": no uptodate device for slot %d of %s\n",
-+                                      i, mddev);
-+              }
-+              
-+              if (runstop == 1 ||
-+                  (runstop <= 0 &&
-+                   ( enough(info.array.level, info.array.raid_disks,
-+                            info.array.layout, clean, avail, okcnt) &&
-+                     (okcnt >= req_cnt || start_partial_ok)
-+                           ))) {
-+                      if (ioctl(mdfd, RUN_ARRAY, NULL)==0) {
-+                              if (verbose >= 0) {
-+                                      fprintf(stderr, Name ": %s has been started with %d drive%s",
-+                                              mddev, okcnt, okcnt==1?"":"s");
-+                                      if (okcnt < info.array.raid_disks)
-+                                              fprintf(stderr, " (out of %d)", info.array.raid_disks);
-+                                      if (sparecnt)
-+                                              fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s");
-+                                      fprintf(stderr, ".\n");
-+                              }
-+                              return 0;
-+                      }
-+                      fprintf(stderr, Name ": failed to RUN_ARRAY %s: %s\n",
-+                              mddev, strerror(errno));
-+
-+                      if (!enough(info.array.level, info.array.raid_disks,
-+                                  info.array.layout, 1, avail, okcnt))
-+                              fprintf(stderr, Name ": Not enough devices to "
-+                                      "start the array.\n");
-+                      else if (!enough(info.array.level,
-+                                       info.array.raid_disks,
-+                                       info.array.layout, clean,
-+                                       avail, okcnt))
-+                              fprintf(stderr, Name ": Not enough devices to "
-+                                      "start the array while not clean "
-+                                      "- consider --force.\n");
-+
-+                      return 1;
-+              }
-+              if (runstop == -1) {
-+                      fprintf(stderr, Name ": %s assembled from %d drive%s",
-+                              mddev, okcnt, okcnt==1?"":"s");
-+                      if (okcnt != info.array.raid_disks)
-+                              fprintf(stderr, " (out of %d)", info.array.raid_disks);
-+                      fprintf(stderr, ", but not started.\n");
-+                      return 0;
-+              }
-+              if (verbose >= -1) {
-+                      fprintf(stderr, Name ": %s assembled from %d drive%s", mddev, okcnt, okcnt==1?"":"s");
-+                      if (sparecnt)
-+                              fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s");
-+                      if (!enough(info.array.level, info.array.raid_disks,
-+                                  info.array.layout, 1, avail, okcnt))
-+                              fprintf(stderr, " - not enough to start the array.\n");
-+                      else if (!enough(info.array.level,
-+                                       info.array.raid_disks,
-+                                       info.array.layout, clean,
-+                                       avail, okcnt))
-+                              fprintf(stderr, " - not enough to start the "
-+                                      "array while not clean - consider "
-+                                      "--force.\n");
-+                      else {
-+                              if (req_cnt == info.array.raid_disks)
-+                                      fprintf(stderr, " - need all %d to start it", req_cnt);
-+                              else
-+                                      fprintf(stderr, " - need %d of %d to start", req_cnt, info.array.raid_disks);
-+                              fprintf(stderr, " (use --run to insist).\n");
-+                      }
-+              }
-+              return 1;
-+      } else {
-+              /* The "chosen_drive" is a good choice, and if necessary, the superblock has
-+               * been updated to point to the current locations of devices.
-+               * so we can just start the array
-+               */
-+              unsigned long dev;
-+              dev = makedev(devices[chosen_drive].major,
-+                          devices[chosen_drive].minor);
-+              if (ioctl(mdfd, START_ARRAY, dev)) {
-+                  fprintf(stderr, Name ": Cannot start array: %s\n",
-+                          strerror(errno));
-+              }
-+              
-+      }
-+      return 0;
-+}
-+
-+int mdfd = -1;
-+int runstop = 0;
-+int readonly = 0;
-+int verbose = 0;
-+int force = 0;
-+
-+int mdassemble_main(int argc, char **argv) {
-+      mddev_ident_t array_list =  conf_get_ident(NULL);
-+      int minor;
-+      if (!array_list) {
-+              fprintf(stderr, Name ": No arrays found in config file\n");
-+              return 1;
-+      } else {
-+              for (; array_list; array_list = array_list->next) {
-+                      mdu_array_info_t array;
-+                      if (!strncmp("/dev/md", array_list->devname, 7)) {
-+                              errno = 0;
-+                              minor = strtoul(array_list->devname + 7, NULL, 0);
-+                              if (!errno) {
-+                                      mknod(array_list->devname, S_IFBLK|0600, makedev(MD_MAJOR, minor));
-+                              }
-+                      }
-+                      mdfd = open_mddev(array_list->devname, array_list->autof);
-+                      if (mdfd < 0) {
-+
-+                              fprintf(stderr, Name ": failed to open array\n");
-+                              continue;
-+                      }
-+                      if (ioctl(mdfd, GET_ARRAY_INFO, &array) < 0) {
-+                              Assemble(array_list->st, array_list->devname, mdfd,
-+                                         array_list, NULL, NULL,
-+                                         readonly, runstop, NULL, NULL, verbose, force);
-+                      }
-+                      close(mdfd);
-+              }
-+      }
-+      return 0;
-+}
-+
-diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/mdexamine.c busybox-1.7.4+gentoo+mdadm/mdadm/mdexamine.c
---- busybox-1.7.4+gentoo/mdadm/mdexamine.c     1969-12-31 16:00:00.000000000 -0800
-+++ busybox-1.7.4+gentoo+mdadm/mdadm/mdexamine.c       2008-03-11 10:31:00.000000000 -0700
-@@ -0,0 +1,157 @@
-+/*
-+ * mdadm - manage Linux "md" devices aka RAID arrays.
-+ *
-+ * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
-+ *
-+ *
-+ *    This program is free software; you can redistribute it and/or modify
-+ *    it under the terms of the GNU General Public License as published by
-+ *    the Free Software Foundation; either version 2 of the License, or
-+ *    (at your option) any later version.
-+ *
-+ *    This program is distributed in the hope that it will be useful,
-+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *    GNU General Public License for more details.
-+ *
-+ *    You should have received a copy of the GNU General Public License
-+ *    along with this program; if not, write to the Free Software
-+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ *
-+ *    Author: Neil Brown
-+ *    Email: <neilb@cse.unsw.edu.au>
-+ *    Paper: Neil Brown
-+ *           School of Computer Science and Engineering
-+ *           The University of New South Wales
-+ *           Sydney, 2052
-+ *           Australia
-+ */
-+
-+#include      "mdadm.h"
-+#include      "dlink.h"
-+
-+#if ! defined(__BIG_ENDIAN) && ! defined(__LITTLE_ENDIAN)
-+#error no endian defined
-+#endif
-+#include      "md_u.h"
-+#include      "md_p.h"
-+
-+static int Examine(mddev_dev_t devlist, int brief, int scan,
-+          int SparcAdjust, struct supertype *forcest,
-+          char *homehost)
-+{
-+
-+      /* Read the raid superblock from a device and
-+       * display important content.
-+       *
-+       * If cannot be found, print reason: too small, bad magic
-+       *
-+       * Print:
-+       *   version, ctime, level, size, raid+spare+
-+       *   prefered minor
-+       *   uuid
-+       *
-+       *   utime, state etc
-+       *
-+       * If (brief) gather devices for same array and just print a mdadm.conf line including devices=
-+       * if devlist==NULL, use conf_get_devs()
-+       */
-+      int fd; 
-+      void *super = NULL;
-+      int rv = 0;
-+      int err = 0;
-+
-+      struct array {
-+              void *super;
-+              struct supertype *st;
-+              struct mdinfo info;
-+              void *devs;
-+              struct array *next;
-+              int spares;
-+      } *arrays = NULL;
-+
-+      for (; devlist ; devlist=devlist->next) {
-+              struct supertype *st = forcest;
-+
-+              fd = dev_open(devlist->devname, O_RDONLY);
-+              if (fd < 0) {
-+                      if (!scan) {
-+                              fprintf(stderr,Name ": cannot open %s: %s\n",
-+                                      devlist->devname, strerror(errno));
-+                              rv = 1;
-+                      }
-+                      err = 1;
-+              }
-+              else {
-+                      if (!st)
-+                              st = guess_super(fd);
-+                      if (st)
-+                              err = st->ss->load_super(st, fd, &super, (brief||scan)?NULL:devlist->devname);
-+                      else {
-+                              if (!brief) {
-+                                      fprintf(stderr, Name ": No md superblock detected on %s.\n", devlist->devname);
-+                                      rv = 1;
-+                              }
-+                              err = 1;
-+                      }
-+                      close(fd);
-+              }
-+              if (err)
-+                      continue;
-+
-+              if (SparcAdjust)
-+                      st->ss->update_super(NULL, super, "sparc2.2", devlist->devname, 0, 0, NULL);
-+              /* Ok, its good enough to try, though the checksum could be wrong */
-+              if (brief) {
-+                      struct array *ap;
-+                      char *d;
-+                      for (ap=arrays; ap; ap=ap->next) {
-+                              if (st->ss == ap->st->ss && st->ss->compare_super(&ap->super, super)==0)
-+                                      break;
-+                      }
-+                      if (!ap) {
-+                              ap = malloc(sizeof(*ap));
-+                              ap->super = super;
-+                              ap->devs = dl_head();
-+                              ap->next = arrays;
-+                              ap->spares = 0;
-+                              ap->st = st;
-+                              arrays = ap;
-+                              st->ss->getinfo_super(&ap->info, super);
-+                      } else {
-+                              st->ss->getinfo_super(&ap->info, super);
-+                              free(super);
-+                      }
-+                      if (!(ap->info.disk.state & MD_DISK_SYNC))
-+                              ap->spares++;
-+                      d = dl_strdup(devlist->devname);
-+                      dl_add(ap->devs, d);
-+              }
-+      }
-+      if (brief) {
-+              struct array *ap;
-+              for (ap=arrays; ap; ap=ap->next) {
-+                      char sep='=';
-+                      char *d;
-+                      ap->st->ss->brief_examine_super(ap->super);
-+                      if (ap->spares) printf("   spares=%d", ap->spares);
-+                      if (brief > 1) {
-+                              printf("   devices");
-+                              for (d=dl_next(ap->devs); d!= ap->devs; d=dl_next(d)) {
-+                                      printf("%c%s", sep, d);
-+                                      sep=',';
-+                              }
-+                      }
-+                      free(ap->super);
-+                      /* FIXME free ap */
-+                      if (ap->spares || brief > 1)
-+                              printf("\n");
-+              }
-+      }
-+      return rv;
-+}
-+
-+int mdexamine_main(int argc, char **argv) {
-+      return Examine(conf_get_devs(), 1, 0, 0, NULL, NULL);
-+}
-+
-diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/md_p.h busybox-1.7.4+gentoo+mdadm/mdadm/md_p.h
---- busybox-1.7.4+gentoo/mdadm/md_p.h  1969-12-31 16:00:00.000000000 -0800
-+++ busybox-1.7.4+gentoo+mdadm/mdadm/md_p.h    2008-03-11 10:31:00.000000000 -0700
-@@ -0,0 +1,194 @@
-+/*
-+   md_p.h : physical layout of Linux RAID devices
-+          Copyright (C) 1996-98 Ingo Molnar, Gadi Oxman
-+        
-+   This program is free software; you can redistribute it and/or modify
-+   it under the terms of the GNU General Public License as published by
-+   the Free Software Foundation; either version 2, or (at your option)
-+   any later version.
-+   
-+   You should have received a copy of the GNU General Public License
-+   (for example /usr/src/linux/COPYING); if not, write to the Free
-+   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
-+*/
-+
-+#ifndef _MD_P_H
-+#define _MD_P_H
-+
-+/*
-+ * RAID superblock.
-+ *
-+ * The RAID superblock maintains some statistics on each RAID configuration.
-+ * Each real device in the RAID set contains it near the end of the device.
-+ * Some of the ideas are copied from the ext2fs implementation.
-+ *
-+ * We currently use 4096 bytes as follows:
-+ *
-+ *    word offset     function
-+ *
-+ *       0  -    31   Constant generic RAID device information.
-+ *        32  -    63   Generic state information.
-+ *      64  -   127   Personality specific information.
-+ *     128  -   511   12 32-words descriptors of the disks in the raid set.
-+ *     512  -   911   Reserved.
-+ *     912  -  1023   Disk specific descriptor.
-+ */
-+
-+/*
-+ * If x is the real device size in bytes, we return an apparent size of:
-+ *
-+ *    y = (x & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES
-+ *
-+ * and place the 4kB superblock at offset y.
-+ */
-+#define MD_RESERVED_BYTES             (64 * 1024)
-+#define MD_RESERVED_SECTORS           (MD_RESERVED_BYTES / 512)
-+#define MD_RESERVED_BLOCKS            (MD_RESERVED_BYTES / BLOCK_SIZE)
-+
-+#define MD_NEW_SIZE_SECTORS(x)                ((x & ~(MD_RESERVED_SECTORS - 1)) - MD_RESERVED_SECTORS)
-+#define MD_NEW_SIZE_BLOCKS(x)         ((x & ~(MD_RESERVED_BLOCKS - 1)) - MD_RESERVED_BLOCKS)
-+
-+#define MD_SB_BYTES                   4096
-+#define MD_SB_WORDS                   (MD_SB_BYTES / 4)
-+#define MD_SB_BLOCKS                  (MD_SB_BYTES / BLOCK_SIZE)
-+#define MD_SB_SECTORS                 (MD_SB_BYTES / 512)
-+
-+/*
-+ * The following are counted in 32-bit words
-+ */
-+#define       MD_SB_GENERIC_OFFSET            0
-+#define MD_SB_PERSONALITY_OFFSET      64
-+#define MD_SB_DISKS_OFFSET            128
-+#define MD_SB_DESCRIPTOR_OFFSET               992
-+
-+#define MD_SB_GENERIC_CONSTANT_WORDS  32
-+#define MD_SB_GENERIC_STATE_WORDS     32
-+#define MD_SB_GENERIC_WORDS           (MD_SB_GENERIC_CONSTANT_WORDS + MD_SB_GENERIC_STATE_WORDS)
-+#define MD_SB_PERSONALITY_WORDS               64
-+#define MD_SB_DESCRIPTOR_WORDS                32
-+#define MD_SB_DISKS                   27
-+#define MD_SB_DISKS_WORDS             (MD_SB_DISKS*MD_SB_DESCRIPTOR_WORDS)
-+#define MD_SB_RESERVED_WORDS          (1024 - MD_SB_GENERIC_WORDS - MD_SB_PERSONALITY_WORDS - MD_SB_DISKS_WORDS - MD_SB_DESCRIPTOR_WORDS)
-+#define MD_SB_EQUAL_WORDS             (MD_SB_GENERIC_WORDS + MD_SB_PERSONALITY_WORDS + MD_SB_DISKS_WORDS)
-+
-+/*
-+ * Device "operational" state bits
-+ */
-+#define MD_DISK_FAULTY                0 /* disk is faulty / operational */
-+#define MD_DISK_ACTIVE                1 /* disk is running or spare disk */
-+#define MD_DISK_SYNC          2 /* disk is in sync with the raid set */
-+#define MD_DISK_REMOVED               3 /* disk is in sync with the raid set */
-+
-+#define       MD_DISK_WRITEMOSTLY     9 /* disk is "write-mostly" is RAID1 config.
-+                                 * read requests will only be sent here in 
-+                                 * dire need
-+                                 */
-+
-+typedef struct mdp_device_descriptor_s {
-+      __u32 number;           /* 0 Device number in the entire set          */
-+      __u32 major;            /* 1 Device major number                      */
-+      __u32 minor;            /* 2 Device minor number                      */
-+      __u32 raid_disk;        /* 3 The role of the device in the raid set   */
-+      __u32 state;            /* 4 Operational state                        */
-+      __u32 reserved[MD_SB_DESCRIPTOR_WORDS - 5];
-+} mdp_disk_t;
-+
-+#define MD_SB_MAGIC           0xa92b4efc
-+
-+/*
-+ * Superblock state bits
-+ */
-+#define MD_SB_CLEAN           0
-+#define MD_SB_ERRORS          1
-+
-+#define       MD_SB_BITMAP_PRESENT    8 /* bitmap may be present nearby */
-+
-+typedef struct mdp_superblock_s {
-+      /*
-+       * Constant generic information
-+       */
-+      __u32 md_magic;         /*  0 MD identifier                           */
-+      __u32 major_version;    /*  1 major version to which the set conforms */
-+      __u32 minor_version;    /*  2 minor version ...                       */
-+      __u32 patch_version;    /*  3 patchlevel version ...                  */
-+      __u32 gvalid_words;     /*  4 Number of used words in this section    */
-+      __u32 set_uuid0;        /*  5 Raid set identifier                     */
-+      __u32 ctime;            /*  6 Creation time                           */
-+      __u32 level;            /*  7 Raid personality                        */
-+      __u32 size;             /*  8 Apparent size of each individual disk   */
-+      __u32 nr_disks;         /*  9 total disks in the raid set             */
-+      __u32 raid_disks;       /* 10 disks in a fully functional raid set    */
-+      __u32 md_minor;         /* 11 preferred MD minor device number        */
-+      __u32 not_persistent;   /* 12 does it have a persistent superblock    */
-+      __u32 set_uuid1;        /* 13 Raid set identifier #2                  */
-+      __u32 set_uuid2;        /* 14 Raid set identifier #3                  */
-+      __u32 set_uuid3;        /* 15 Raid set identifier #4                  */
-+      __u32 gstate_creserved[MD_SB_GENERIC_CONSTANT_WORDS - 16];
-+
-+      /*
-+       * Generic state information
-+       */
-+      __u32 utime;            /*  0 Superblock update time                  */
-+      __u32 state;            /*  1 State bits (clean, ...)                 */
-+      __u32 active_disks;     /*  2 Number of currently active disks        */
-+      __u32 working_disks;    /*  3 Number of working disks                 */
-+      __u32 failed_disks;     /*  4 Number of failed disks                  */
-+      __u32 spare_disks;      /*  5 Number of spare disks                   */
-+      __u32 sb_csum;          /*  6 checksum of the whole superblock        */
-+#if  __BYTE_ORDER ==  __BIG_ENDIAN
-+      __u32 events_hi;        /*  7 high-order of superblock update count   */
-+      __u32 events_lo;        /*  8 low-order of superblock update count    */
-+      __u32 cp_events_hi;     /*  9 high-order of checkpoint update count   */
-+      __u32 cp_events_lo;     /* 10 low-order of checkpoint update count    */
-+#else
-+      __u32 events_lo;        /*  7 low-order of superblock update count    */
-+      __u32 events_hi;        /*  8 high-order of superblock update count   */
-+      __u32 cp_events_lo;     /*  9 low-order of checkpoint update count    */
-+      __u32 cp_events_hi;     /* 10 high-order of checkpoint update count   */
-+#endif
-+      __u32 recovery_cp;      /* 11 recovery checkpoint sector count        */
-+      /* There are only valid for minor_version > 90 */
-+      __u64 reshape_position; /* 12,13 next address in array-space for reshape */
-+      __u32 new_level;        /* 14 new level we are reshaping to           */
-+      __u32 delta_disks;      /* 15 change in number of raid_disks          */
-+      __u32 new_layout;       /* 16 new layout                              */
-+      __u32 new_chunk;        /* 17 new chunk size (bytes)                  */
-+      __u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 18];
-+
-+      /*
-+       * Personality information
-+       */
-+      __u32 layout;           /*  0 the array's physical layout             */
-+      __u32 chunk_size;       /*  1 chunk size in bytes                     */
-+      __u32 root_pv;          /*  2 LV root PV */
-+      __u32 root_block;       /*  3 LV root block */
-+      __u32 pstate_reserved[MD_SB_PERSONALITY_WORDS - 4];
-+
-+      /*
-+       * Disks information
-+       */
-+      mdp_disk_t disks[MD_SB_DISKS];
-+
-+      /*
-+       * Reserved
-+       */
-+      __u32 reserved[MD_SB_RESERVED_WORDS];
-+
-+      /*
-+       * Active descriptor
-+       */
-+      mdp_disk_t this_disk;
-+
-+} mdp_super_t;
-+
-+#ifdef __TINYC__
-+typedef unsigned long long __u64;
-+#endif
-+
-+static inline __u64 md_event(mdp_super_t *sb) {
-+      __u64 ev = sb->events_hi;
-+      return (ev<<32)| sb->events_lo;
-+}
-+
-+#endif 
-+
-diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/md_u.h busybox-1.7.4+gentoo+mdadm/mdadm/md_u.h
---- busybox-1.7.4+gentoo/mdadm/md_u.h  1969-12-31 16:00:00.000000000 -0800
-+++ busybox-1.7.4+gentoo+mdadm/mdadm/md_u.h    2008-03-11 10:31:00.000000000 -0700
-@@ -0,0 +1,123 @@
-+/*
-+   md_u.h : user <=> kernel API between Linux raidtools and RAID drivers
-+          Copyright (C) 1998 Ingo Molnar
-+        
-+   This program is free software; you can redistribute it and/or modify
-+   it under the terms of the GNU General Public License as published by
-+   the Free Software Foundation; either version 2, or (at your option)
-+   any later version.
-+   
-+   You should have received a copy of the GNU General Public License
-+   (for example /usr/src/linux/COPYING); if not, write to the Free
-+   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  
-+*/
-+
-+#ifndef _MD_U_H
-+#define _MD_U_H
-+
-+/* ioctls */
-+
-+/* status */
-+#define RAID_VERSION          _IOR (MD_MAJOR, 0x10, mdu_version_t)
-+#define GET_ARRAY_INFO                _IOR (MD_MAJOR, 0x11, mdu_array_info_t)
-+#define GET_DISK_INFO         _IOR (MD_MAJOR, 0x12, mdu_disk_info_t)
-+#define PRINT_RAID_DEBUG      _IO (MD_MAJOR, 0x13)
-+#define RAID_AUTORUN          _IO (MD_MAJOR, 0x14)
-+#define GET_BITMAP_FILE               _IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t)
-+
-+/* configuration */
-+#define CLEAR_ARRAY           _IO (MD_MAJOR, 0x20)
-+#define ADD_NEW_DISK          _IOW (MD_MAJOR, 0x21, mdu_disk_info_t)
-+#define HOT_REMOVE_DISK               _IO (MD_MAJOR, 0x22)
-+#define SET_ARRAY_INFO                _IOW (MD_MAJOR, 0x23, mdu_array_info_t)
-+#define SET_DISK_INFO         _IO (MD_MAJOR, 0x24)
-+#define WRITE_RAID_INFO               _IO (MD_MAJOR, 0x25)
-+#define UNPROTECT_ARRAY               _IO (MD_MAJOR, 0x26)
-+#define PROTECT_ARRAY         _IO (MD_MAJOR, 0x27)
-+#define HOT_ADD_DISK          _IO (MD_MAJOR, 0x28)
-+#define SET_DISK_FAULTY               _IO (MD_MAJOR, 0x29)
-+#define SET_BITMAP_FILE               _IOW (MD_MAJOR, 0x2b, int)
-+
-+/* usage */
-+#define RUN_ARRAY             _IOW (MD_MAJOR, 0x30, mdu_param_t)
-+#define START_ARRAY           _IO (MD_MAJOR, 0x31)
-+#define STOP_ARRAY            _IO (MD_MAJOR, 0x32)
-+#define STOP_ARRAY_RO         _IO (MD_MAJOR, 0x33)
-+#define RESTART_ARRAY_RW      _IO (MD_MAJOR, 0x34)
-+
-+typedef struct mdu_version_s {
-+      int major;
-+      int minor;
-+      int patchlevel;
-+} mdu_version_t;
-+
-+typedef struct mdu_array_info_s {
-+      /*
-+       * Generic constant information
-+       */
-+      int major_version;
-+      int minor_version;
-+      int patch_version;
-+      int ctime;
-+      int level;
-+      int size;
-+      int nr_disks;
-+      int raid_disks;
-+      int md_minor;
-+      int not_persistent;
-+
-+      /*
-+       * Generic state information
-+       */
-+      int utime;              /*  0 Superblock update time                  */
-+      int state;              /*  1 State bits (clean, ...)                 */
-+      int active_disks;       /*  2 Number of currently active disks        */
-+      int working_disks;      /*  3 Number of working disks                 */
-+      int failed_disks;       /*  4 Number of failed disks                  */
-+      int spare_disks;        /*  5 Number of spare disks                   */
-+
-+      /*
-+       * Personality information
-+       */
-+      int layout;             /*  0 the array's physical layout             */
-+      int chunk_size; /*  1 chunk size in bytes                     */
-+
-+} mdu_array_info_t;
-+
-+typedef struct mdu_disk_info_s {
-+      /*
-+       * configuration/status of one particular disk
-+       */
-+      int number;
-+      int major;
-+      int minor;
-+      int raid_disk;
-+      int state;
-+
-+} mdu_disk_info_t;
-+
-+typedef struct mdu_start_info_s {
-+      /*
-+       * configuration/status of one particular disk
-+       */
-+      int major;
-+      int minor;
-+      int raid_disk;
-+      int state;
-+
-+} mdu_start_info_t;
-+
-+typedef struct mdu_bitmap_file_s
-+{
-+      char pathname[4096];
-+} mdu_bitmap_file_t;
-+
-+typedef struct mdu_param_s
-+{
-+      int                     personality;    /* 1,2,3,4 */
-+      int                     chunk_size;     /* in bytes */
-+      int                     max_fault;      /* unused for now */
-+} mdu_param_t;
-+
-+#endif 
-+
-diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/sha1.c busybox-1.7.4+gentoo+mdadm/mdadm/sha1.c
---- busybox-1.7.4+gentoo/mdadm/sha1.c  1969-12-31 16:00:00.000000000 -0800
-+++ busybox-1.7.4+gentoo+mdadm/mdadm/sha1.c    2008-03-11 10:31:00.000000000 -0700
-@@ -0,0 +1,423 @@
-+/* sha1.c - Functions to compute SHA1 message digest of files or
-+   memory blocks according to the NIST specification FIPS-180-1.
-+
-+   Copyright (C) 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
-+
-+   This program is free software; you can redistribute it and/or modify it
-+   under the terms of the GNU General Public License as published by the
-+   Free Software Foundation; either version 2, or (at your option) any
-+   later version.
-+
-+   This program is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+   GNU General Public License for more details.
-+
-+   You should have received a copy of the GNU General Public License
-+   along with this program; if not, write to the Free Software Foundation,
-+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
-+
-+/* Written by Scott G. Miller
-+   Credits:
-+      Robert Klep <robert@ilse.nl>  -- Expansion function fix
-+*/
-+
-+#ifdef HAVE_CONFIG_H
-+# include <config.h>
-+#endif
-+
-+#include "sha1.h"
-+
-+#include <stddef.h>
-+#include <string.h>
-+
-+#if USE_UNLOCKED_IO
-+# include "unlocked-io.h"
-+#endif
-+
-+/* SWAP does an endian swap on architectures that are little-endian,
-+   as SHA1 needs some data in a big-endian form.  */
-+
-+#ifdef WORDS_BIGENDIAN
-+# define SWAP(n) (n)
-+#else
-+# define SWAP(n) \
-+    (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
-+#endif
-+
-+#define BLOCKSIZE 4096
-+#if BLOCKSIZE % 64 != 0
-+# error "invalid BLOCKSIZE"
-+#endif
-+
-+/* This array contains the bytes used to pad the buffer to the next
-+   64-byte boundary.  (RFC 1321, 3.1: Step 1)  */
-+static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ...  */ };
-+
-+
-+/*
-+  Takes a pointer to a 160 bit block of data (five 32 bit ints) and
-+  intializes it to the start constants of the SHA1 algorithm.  This
-+  must be called before using hash in the call to sha1_hash.
-+*/
-+void
-+sha1_init_ctx (struct sha1_ctx *ctx)
-+{
-+  ctx->A = 0x67452301;
-+  ctx->B = 0xefcdab89;
-+  ctx->C = 0x98badcfe;
-+  ctx->D = 0x10325476;
-+  ctx->E = 0xc3d2e1f0;
-+
-+  ctx->total[0] = ctx->total[1] = 0;
-+  ctx->buflen = 0;
-+}
-+
-+/* Put result from CTX in first 20 bytes following RESBUF.  The result
-+   must be in little endian byte order.
-+
-+   IMPORTANT: On some systems it is required that RESBUF is correctly
-+   aligned for a 32 bits value.  */
-+void *
-+sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf)
-+{
-+  ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
-+  ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
-+  ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
-+  ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
-+  ((md5_uint32 *) resbuf)[4] = SWAP (ctx->E);
-+
-+  return resbuf;
-+}
-+
-+/* Process the remaining bytes in the internal buffer and the usual
-+   prolog according to the standard and write the result to RESBUF.
-+
-+   IMPORTANT: On some systems it is required that RESBUF is correctly
-+   aligned for a 32 bits value.  */
-+void *
-+sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf)
-+{
-+  /* Take yet unprocessed bytes into account.  */
-+  md5_uint32 bytes = ctx->buflen;
-+  size_t pad;
-+
-+  /* Now count remaining bytes.  */
-+  ctx->total[0] += bytes;
-+  if (ctx->total[0] < bytes)
-+    ++ctx->total[1];
-+
-+  pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
-+  memcpy (&ctx->buffer[bytes], fillbuf, pad);
-+
-+  /* Put the 64-bit file length in *bits* at the end of the buffer.  */
-+  *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP (ctx->total[0] << 3);
-+  *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP ((ctx->total[1] << 3) |
-+                                                  (ctx->total[0] >> 29));
-+
-+  /* Process last bytes.  */
-+  sha1_process_block (ctx->buffer, bytes + pad + 8, ctx);
-+
-+  return sha1_read_ctx (ctx, resbuf);
-+}
-+
-+/* Compute SHA1 message digest for bytes read from STREAM.  The
-+   resulting message digest number will be written into the 16 bytes
-+   beginning at RESBLOCK.  */
-+int
-+sha1_stream (FILE *stream, void *resblock)
-+{
-+  struct sha1_ctx ctx;
-+  char buffer[BLOCKSIZE + 72];
-+  size_t sum;
-+
-+  /* Initialize the computation context.  */
-+  sha1_init_ctx (&ctx);
-+
-+  /* Iterate over full file contents.  */
-+  while (1)
-+    {
-+      /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
-+       computation function processes the whole buffer so that with the
-+       next round of the loop another block can be read.  */
-+      size_t n;
-+      sum = 0;
-+
-+      /* Read block.  Take care for partial reads.  */
-+      while (1)
-+      {
-+        n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
-+
-+        sum += n;
-+
-+        if (sum == BLOCKSIZE)
-+          break;
-+
-+        if (n == 0)
-+          {
-+            /* Check for the error flag IFF N == 0, so that we don't
-+               exit the loop after a partial read due to e.g., EAGAIN
-+               or EWOULDBLOCK.  */
-+            if (ferror (stream))
-+              return 1;
-+            goto process_partial_block;
-+          }
-+
-+        /* We've read at least one byte, so ignore errors.  But always
-+           check for EOF, since feof may be true even though N > 0.
-+           Otherwise, we could end up calling fread after EOF.  */
-+        if (feof (stream))
-+          goto process_partial_block;
-+      }
-+
-+      /* Process buffer with BLOCKSIZE bytes.  Note that
-+                      BLOCKSIZE % 64 == 0
-+       */
-+      sha1_process_block (buffer, BLOCKSIZE, &ctx);
-+    }
-+
-+ process_partial_block:;
-+
-+  /* Process any remaining bytes.  */
-+  if (sum > 0)
-+    sha1_process_bytes (buffer, sum, &ctx);
-+
-+  /* Construct result in desired memory.  */
-+  sha1_finish_ctx (&ctx, resblock);
-+  return 0;
-+}
-+
-+/* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
-+   result is always in little endian byte order, so that a byte-wise
-+   output yields to the wanted ASCII representation of the message
-+   digest.  */
-+void *
-+sha1_buffer (const char *buffer, size_t len, void *resblock)
-+{
-+  struct sha1_ctx ctx;
-+
-+  /* Initialize the computation context.  */
-+  sha1_init_ctx (&ctx);
-+
-+  /* Process whole buffer but last len % 64 bytes.  */
-+  sha1_process_bytes (buffer, len, &ctx);
-+
-+  /* Put result in desired memory area.  */
-+  return sha1_finish_ctx (&ctx, resblock);
-+}
-+
-+void
-+sha1_process_bytes (const void *buffer, size_t len, struct sha1_ctx *ctx)
-+{
-+  /* When we already have some bits in our internal buffer concatenate
-+     both inputs first.  */
-+  if (ctx->buflen != 0)
-+    {
-+      size_t left_over = ctx->buflen;
-+      size_t add = 128 - left_over > len ? len : 128 - left_over;
-+
-+      memcpy (&ctx->buffer[left_over], buffer, add);
-+      ctx->buflen += add;
-+
-+      if (ctx->buflen > 64)
-+      {
-+        sha1_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
-+
-+        ctx->buflen &= 63;
-+        /* The regions in the following copy operation cannot overlap.  */
-+        memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
-+                ctx->buflen);
-+      }
-+
-+      buffer = (const char *) buffer + add;
-+      len -= add;
-+    }
-+
-+  /* Process available complete blocks.  */
-+  if (len >= 64)
-+    {
-+#if !_STRING_ARCH_unaligned
-+# define alignof(type) offsetof (struct { char c; type x; }, x)
-+# define UNALIGNED_P(p) (((size_t) p) % alignof (md5_uint32) != 0)
-+      if (UNALIGNED_P (buffer))
-+      while (len > 64)
-+        {
-+          sha1_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx);
-+          buffer = (const char *) buffer + 64;
-+          len -= 64;
-+        }
-+      else
-+#endif
-+      {
-+        sha1_process_block (buffer, len & ~63, ctx);
-+        buffer = (const char *) buffer + (len & ~63);
-+        len &= 63;
-+      }
-+    }
-+
-+  /* Move remaining bytes in internal buffer.  */
-+  if (len > 0)
-+    {
-+      size_t left_over = ctx->buflen;
-+
-+      memcpy (&ctx->buffer[left_over], buffer, len);
-+      left_over += len;
-+      if (left_over >= 64)
-+      {
-+        sha1_process_block (ctx->buffer, 64, ctx);
-+        left_over -= 64;
-+        memcpy (ctx->buffer, &ctx->buffer[64], left_over);
-+      }
-+      ctx->buflen = left_over;
-+    }
-+}
-+
-+/* --- Code below is the primary difference between md5.c and sha1.c --- */
-+
-+/* SHA1 round constants */
-+#define K1 0x5a827999L
-+#define K2 0x6ed9eba1L
-+#define K3 0x8f1bbcdcL
-+#define K4 0xca62c1d6L
-+
-+/* Round functions.  Note that F2 is the same as F4.  */
-+#define F1(B,C,D) ( D ^ ( B & ( C ^ D ) ) )
-+#define F2(B,C,D) (B ^ C ^ D)
-+#define F3(B,C,D) ( ( B & C ) | ( D & ( B | C ) ) )
-+#define F4(B,C,D) (B ^ C ^ D)
-+
-+/* Process LEN bytes of BUFFER, accumulating context into CTX.
-+   It is assumed that LEN % 64 == 0.
-+   Most of this code comes from GnuPG's cipher/sha1.c.  */
-+
-+void
-+sha1_process_block (const void *buffer, size_t len, struct sha1_ctx *ctx)
-+{
-+  const md5_uint32 *words = buffer;
-+  size_t nwords = len / sizeof (md5_uint32);
-+  const md5_uint32 *endp = words + nwords;
-+  md5_uint32 x[16];
-+  md5_uint32 a = ctx->A;
-+  md5_uint32 b = ctx->B;
-+  md5_uint32 c = ctx->C;
-+  md5_uint32 d = ctx->D;
-+  md5_uint32 e = ctx->E;
-+
-+  /* First increment the byte count.  RFC 1321 specifies the possible
-+     length of the file up to 2^64 bits.  Here we only compute the
-+     number of bytes.  Do a double word increment.  */
-+  ctx->total[0] += len;
-+  if (ctx->total[0] < len)
-+    ++ctx->total[1];
-+
-+#define rol(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
-+
-+#define M(I) ( tm =   x[I&0x0f] ^ x[(I-14)&0x0f] \
-+                  ^ x[(I-8)&0x0f] ^ x[(I-3)&0x0f] \
-+             , (x[I&0x0f] = rol(tm, 1)) )
-+
-+#define R(A,B,C,D,E,F,K,M)  do { E += rol( A, 5 )     \
-+                                    + F( B, C, D )  \
-+                                    + K             \
-+                                    + M;            \
-+                               B = rol( B, 30 );    \
-+                             } while(0)
-+
-+  while (words < endp)
-+    {
-+      md5_uint32 tm;
-+      int t;
-+      for (t = 0; t < 16; t++)
-+      {
-+        x[t] = SWAP (*words);
-+        words++;
-+      }
-+
-+      R( a, b, c, d, e, F1, K1, x[ 0] );
-+      R( e, a, b, c, d, F1, K1, x[ 1] );
-+      R( d, e, a, b, c, F1, K1, x[ 2] );
-+      R( c, d, e, a, b, F1, K1, x[ 3] );
-+      R( b, c, d, e, a, F1, K1, x[ 4] );
-+      R( a, b, c, d, e, F1, K1, x[ 5] );
-+      R( e, a, b, c, d, F1, K1, x[ 6] );
-+      R( d, e, a, b, c, F1, K1, x[ 7] );
-+      R( c, d, e, a, b, F1, K1, x[ 8] );
-+      R( b, c, d, e, a, F1, K1, x[ 9] );
-+      R( a, b, c, d, e, F1, K1, x[10] );
-+      R( e, a, b, c, d, F1, K1, x[11] );
-+      R( d, e, a, b, c, F1, K1, x[12] );
-+      R( c, d, e, a, b, F1, K1, x[13] );
-+      R( b, c, d, e, a, F1, K1, x[14] );
-+      R( a, b, c, d, e, F1, K1, x[15] );
-+      R( e, a, b, c, d, F1, K1, M(16) );
-+      R( d, e, a, b, c, F1, K1, M(17) );
-+      R( c, d, e, a, b, F1, K1, M(18) );
-+      R( b, c, d, e, a, F1, K1, M(19) );
-+      R( a, b, c, d, e, F2, K2, M(20) );
-+      R( e, a, b, c, d, F2, K2, M(21) );
-+      R( d, e, a, b, c, F2, K2, M(22) );
-+      R( c, d, e, a, b, F2, K2, M(23) );
-+      R( b, c, d, e, a, F2, K2, M(24) );
-+      R( a, b, c, d, e, F2, K2, M(25) );
-+      R( e, a, b, c, d, F2, K2, M(26) );
-+      R( d, e, a, b, c, F2, K2, M(27) );
-+      R( c, d, e, a, b, F2, K2, M(28) );
-+      R( b, c, d, e, a, F2, K2, M(29) );
-+      R( a, b, c, d, e, F2, K2, M(30) );
-+      R( e, a, b, c, d, F2, K2, M(31) );
-+      R( d, e, a, b, c, F2, K2, M(32) );
-+      R( c, d, e, a, b, F2, K2, M(33) );
-+      R( b, c, d, e, a, F2, K2, M(34) );
-+      R( a, b, c, d, e, F2, K2, M(35) );
-+      R( e, a, b, c, d, F2, K2, M(36) );
-+      R( d, e, a, b, c, F2, K2, M(37) );
-+      R( c, d, e, a, b, F2, K2, M(38) );
-+      R( b, c, d, e, a, F2, K2, M(39) );
-+      R( a, b, c, d, e, F3, K3, M(40) );
-+      R( e, a, b, c, d, F3, K3, M(41) );
-+      R( d, e, a, b, c, F3, K3, M(42) );
-+      R( c, d, e, a, b, F3, K3, M(43) );
-+      R( b, c, d, e, a, F3, K3, M(44) );
-+      R( a, b, c, d, e, F3, K3, M(45) );
-+      R( e, a, b, c, d, F3, K3, M(46) );
-+      R( d, e, a, b, c, F3, K3, M(47) );
-+      R( c, d, e, a, b, F3, K3, M(48) );
-+      R( b, c, d, e, a, F3, K3, M(49) );
-+      R( a, b, c, d, e, F3, K3, M(50) );
-+      R( e, a, b, c, d, F3, K3, M(51) );
-+      R( d, e, a, b, c, F3, K3, M(52) );
-+      R( c, d, e, a, b, F3, K3, M(53) );
-+      R( b, c, d, e, a, F3, K3, M(54) );
-+      R( a, b, c, d, e, F3, K3, M(55) );
-+      R( e, a, b, c, d, F3, K3, M(56) );
-+      R( d, e, a, b, c, F3, K3, M(57) );
-+      R( c, d, e, a, b, F3, K3, M(58) );
-+      R( b, c, d, e, a, F3, K3, M(59) );
-+      R( a, b, c, d, e, F4, K4, M(60) );
-+      R( e, a, b, c, d, F4, K4, M(61) );
-+      R( d, e, a, b, c, F4, K4, M(62) );
-+      R( c, d, e, a, b, F4, K4, M(63) );
-+      R( b, c, d, e, a, F4, K4, M(64) );
-+      R( a, b, c, d, e, F4, K4, M(65) );
-+      R( e, a, b, c, d, F4, K4, M(66) );
-+      R( d, e, a, b, c, F4, K4, M(67) );
-+      R( c, d, e, a, b, F4, K4, M(68) );
-+      R( b, c, d, e, a, F4, K4, M(69) );
-+      R( a, b, c, d, e, F4, K4, M(70) );
-+      R( e, a, b, c, d, F4, K4, M(71) );
-+      R( d, e, a, b, c, F4, K4, M(72) );
-+      R( c, d, e, a, b, F4, K4, M(73) );
-+      R( b, c, d, e, a, F4, K4, M(74) );
-+      R( a, b, c, d, e, F4, K4, M(75) );
-+      R( e, a, b, c, d, F4, K4, M(76) );
-+      R( d, e, a, b, c, F4, K4, M(77) );
-+      R( c, d, e, a, b, F4, K4, M(78) );
-+      R( b, c, d, e, a, F4, K4, M(79) );
-+
-+      a = ctx->A += a;
-+      b = ctx->B += b;
-+      c = ctx->C += c;
-+      d = ctx->D += d;
-+      e = ctx->E += e;
-+    }
-+}
-diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/sha1.h busybox-1.7.4+gentoo+mdadm/mdadm/sha1.h
---- busybox-1.7.4+gentoo/mdadm/sha1.h  1969-12-31 16:00:00.000000000 -0800
-+++ busybox-1.7.4+gentoo+mdadm/mdadm/sha1.h    2008-03-11 10:31:00.000000000 -0700
-@@ -0,0 +1,87 @@
-+/* Declarations of functions and data types used for SHA1 sum
-+   library functions.
-+   Copyright (C) 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
-+
-+   This program is free software; you can redistribute it and/or modify it
-+   under the terms of the GNU General Public License as published by the
-+   Free Software Foundation; either version 2, or (at your option) any
-+   later version.
-+
-+   This program is distributed in the hope that it will be useful,
-+   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+   GNU General Public License for more details.
-+
-+   You should have received a copy of the GNU General Public License
-+   along with this program; if not, write to the Free Software Foundation,
-+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
-+
-+#ifndef SHA1_H
-+# define SHA1_H 1
-+
-+# include <stdio.h>
-+# include "md5.h"
-+
-+/* Structure to save state of computation between the single steps.  */
-+struct sha1_ctx
-+{
-+  md5_uint32 A;
-+  md5_uint32 B;
-+  md5_uint32 C;
-+  md5_uint32 D;
-+  md5_uint32 E;
-+
-+  md5_uint32 total[2];
-+  md5_uint32 buflen;
-+  char buffer[128] __attribute__ ((__aligned__ (__alignof__ (md5_uint32))));
-+};
-+
-+
-+/* Initialize structure containing state of computation. */
-+extern void sha1_init_ctx (struct sha1_ctx *ctx);
-+
-+/* Starting with the result of former calls of this function (or the
-+   initialization function update the context for the next LEN bytes
-+   starting at BUFFER.
-+   It is necessary that LEN is a multiple of 64!!! */
-+extern void sha1_process_block (const void *buffer, size_t len,
-+                              struct sha1_ctx *ctx);
-+
-+/* Starting with the result of former calls of this function (or the
-+   initialization function update the context for the next LEN bytes
-+   starting at BUFFER.
-+   It is NOT required that LEN is a multiple of 64.  */
-+extern void sha1_process_bytes (const void *buffer, size_t len,
-+                              struct sha1_ctx *ctx);
-+
-+/* Process the remaining bytes in the buffer and put result from CTX
-+   in first 20 bytes following RESBUF.  The result is always in little
-+   endian byte order, so that a byte-wise output yields to the wanted
-+   ASCII representation of the message digest.
-+
-+   IMPORTANT: On some systems it is required that RESBUF be correctly
-+   aligned for a 32 bits value.  */
-+extern void *sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf);
-+
-+
-+/* Put result from CTX in first 20 bytes following RESBUF.  The result is
-+   always in little endian byte order, so that a byte-wise output yields
-+   to the wanted ASCII representation of the message digest.
-+
-+   IMPORTANT: On some systems it is required that RESBUF is correctly
-+   aligned for a 32 bits value.  */
-+extern void *sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf);
-+
-+
-+/* Compute SHA1 message digest for bytes read from STREAM.  The
-+   resulting message digest number will be written into the 20 bytes
-+   beginning at RESBLOCK.  */
-+extern int sha1_stream (FILE *stream, void *resblock);
-+
-+/* Compute SHA1 message digest for LEN bytes beginning at BUFFER.  The
-+   result is always in little endian byte order, so that a byte-wise
-+   output yields to the wanted ASCII representation of the message
-+   digest.  */
-+extern void *sha1_buffer (const char *buffer, size_t len, void *resblock);
-+
-+#endif
-diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/super0.c busybox-1.7.4+gentoo+mdadm/mdadm/super0.c
---- busybox-1.7.4+gentoo/mdadm/super0.c        1969-12-31 16:00:00.000000000 -0800
-+++ busybox-1.7.4+gentoo+mdadm/mdadm/super0.c  2008-03-11 10:31:00.000000000 -0700
-@@ -0,0 +1,562 @@
-+/*
-+ * mdadm - manage Linux "md" devices aka RAID arrays.
-+ *
-+ * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
-+ *
-+ *
-+ *    This program is free software; you can redistribute it and/or modify
-+ *    it under the terms of the GNU General Public License as published by
-+ *    the Free Software Foundation; either version 2 of the License, or
-+ *    (at your option) any later version.
-+ *
-+ *    This program is distributed in the hope that it will be useful,
-+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *    GNU General Public License for more details.
-+ *
-+ *    You should have received a copy of the GNU General Public License
-+ *    along with this program; if not, write to the Free Software
-+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ *
-+ *    Author: Neil Brown
-+ *    Email: <neilb@cse.unsw.edu.au>
-+ *    Paper: Neil Brown
-+ *           School of Computer Science and Engineering
-+ *           The University of New South Wales
-+ *           Sydney, 2052
-+ *           Australia
-+ */
-+
-+#define HAVE_STDINT_H 1
-+#include "mdadm.h"
-+/*
-+ * All handling for the 0.90.0 version superblock is in
-+ * this file.
-+ * This includes:
-+ *   - finding, loading, and writing the superblock.
-+ *   - initialising a new superblock
-+ *   - printing the superblock for --examine
-+ *   - printing part of the superblock for --detail
-+ * .. other stuff 
-+ */
-+
-+
-+static unsigned long calc_sb0_csum(mdp_super_t *super)
-+{
-+      unsigned long csum = super->sb_csum;
-+      unsigned long newcsum;
-+      super->sb_csum= 0 ;
-+      newcsum = calc_csum(super, MD_SB_BYTES);
-+      super->sb_csum = csum;
-+      return newcsum;
-+}
-+
-+
-+void super0_swap_endian(struct mdp_superblock_s *sb)
-+{
-+      /* as super0 superblocks are host-endian, it is sometimes
-+       * useful to be able to swap the endianness 
-+       * as (almost) everything is u32's we byte-swap every 4byte
-+       * number.
-+       * We then also have to swap the events_hi and events_lo
-+       */
-+      char *sbc = (char *)sb;
-+      __u32 t32;
-+      int i;
-+
-+      for (i=0; i < MD_SB_BYTES ; i+=4) {
-+              char t = sbc[i];
-+              sbc[i] = sbc[i+3];
-+              sbc[i+3] = t;
-+              t=sbc[i+1];
-+              sbc[i+1]=sbc[i+2];
-+              sbc[i+2]=t;
-+      }
-+      t32 = sb->events_hi;
-+      sb->events_hi = sb->events_lo;
-+      sb->events_lo = t32;
-+
-+      t32 = sb->cp_events_hi;
-+      sb->cp_events_hi = sb->cp_events_lo;
-+      sb->cp_events_lo = t32;
-+
-+}
-+
-+static void brief_examine_super0(void *sbv)
-+{
-+      mdp_super_t *sb = sbv;
-+      char *c=map_num(pers, sb->level);
-+      char devname[20];
-+
-+      sprintf(devname, "/dev/md%d", sb->md_minor);
-+
-+      printf("ARRAY %s level=%s num-devices=%d UUID=",
-+             devname,
-+             c?c:"-unknown-", sb->raid_disks);
-+      if (sb->minor_version >= 90)
-+              printf("%08x:%08x:%08x:%08x", sb->set_uuid0, sb->set_uuid1,
-+                     sb->set_uuid2, sb->set_uuid3);
-+      else
-+              printf("%08x", sb->set_uuid0);
-+      printf("\n");
-+}
-+
-+static int match_home0(void *sbv, char *homehost)
-+{
-+      mdp_super_t *sb = sbv;
-+      char buf[20];
-+      char *hash = sha1_buffer(homehost,
-+                               strlen(homehost),
-+                               buf);
-+
-+      return (memcmp(&sb->set_uuid2, hash, 8)==0);
-+}
-+
-+static void uuid_from_super0(int uuid[4], void * sbv)
-+{
-+      mdp_super_t *super = sbv;
-+      uuid[0] = super->set_uuid0;
-+      if (super->minor_version >= 90) {
-+              uuid[1] = super->set_uuid1;
-+              uuid[2] = super->set_uuid2;
-+              uuid[3] = super->set_uuid3;
-+      } else {
-+              uuid[1] = 0;
-+              uuid[2] = 0;
-+              uuid[3] = 0;
-+      }
-+}
-+
-+static void getinfo_super0(struct mdinfo *info, void *sbv)
-+{
-+      mdp_super_t *sb = sbv;
-+      int working = 0;
-+      int i;
-+
-+      info->array.major_version = sb->major_version;
-+      info->array.minor_version = sb->minor_version;
-+      info->array.patch_version = sb->patch_version;
-+      info->array.raid_disks = sb->raid_disks;
-+      info->array.level = sb->level;
-+      info->array.layout = sb->layout;
-+      info->array.md_minor = sb->md_minor;
-+      info->array.ctime = sb->ctime;
-+      info->array.utime = sb->utime;
-+      info->array.chunk_size = sb->chunk_size;
-+      info->array.state = sb->state;
-+      info->component_size = sb->size*2;
-+
-+      info->disk.state = sb->this_disk.state;
-+      info->disk.major = sb->this_disk.major;
-+      info->disk.minor = sb->this_disk.minor;
-+      info->disk.raid_disk = sb->this_disk.raid_disk;
-+      info->disk.number = sb->this_disk.number;
-+
-+      info->events = md_event(sb);
-+      info->data_offset = 0;
-+
-+      uuid_from_super0(info->uuid, sbv);
-+
-+      if (sb->minor_version > 90 && (sb->reshape_position+1) != 0) {
-+              info->reshape_active = 1;
-+              info->reshape_progress = sb->reshape_position;
-+              info->new_level = sb->new_level;
-+              info->delta_disks = sb->delta_disks;
-+              info->new_layout = sb->new_layout;
-+              info->new_chunk = sb->new_chunk;
-+      } else
-+              info->reshape_active = 0;
-+
-+      sprintf(info->name, "%d", sb->md_minor);
-+      /* work_disks is calculated rather than read directly */
-+      for (i=0; i < MD_SB_DISKS; i++)
-+              if ((sb->disks[i].state & (1<<MD_DISK_SYNC)) &&
-+                  (sb->disks[i].raid_disk < info->array.raid_disks) &&
-+                  (sb->disks[i].state & (1<<MD_DISK_ACTIVE)) &&
-+                  !(sb->disks[i].state & (1<<MD_DISK_FAULTY)))
-+                      working ++;
-+      info->array.working_disks = working;
-+}
-+
-+
-+static int update_super0(struct mdinfo *info, void *sbv, char *update,
-+                       char *devname, int verbose,
-+                       int uuid_set, char *homehost)
-+{
-+      /* NOTE: for 'assemble' and 'force' we need to return non-zero if any change was made.
-+       * For others, the return value is ignored.
-+       */
-+      int rv = 0;
-+      mdp_super_t *sb = sbv;
-+      if (strcmp(update, "sparc2.2")==0 ) {
-+              /* 2.2 sparc put the events in the wrong place
-+               * So we copy the tail of the superblock
-+               * up 4 bytes before continuing
-+               */
-+              __u32 *sb32 = (__u32*)sb;
-+              memcpy(sb32+MD_SB_GENERIC_CONSTANT_WORDS+7,
-+                     sb32+MD_SB_GENERIC_CONSTANT_WORDS+7+1,
-+                     (MD_SB_WORDS - (MD_SB_GENERIC_CONSTANT_WORDS+7+1))*4);
-+              if (verbose >= 0)
-+                      fprintf (stderr, Name ": adjusting superblock of %s for 2.2/sparc compatability.\n",
-+                               devname);
-+      }
-+      if (strcmp(update, "super-minor") ==0) {
-+              sb->md_minor = info->array.md_minor;
-+              if (verbose > 0)
-+                      fprintf(stderr, Name ": updating superblock of %s with minor number %d\n",
-+                              devname, info->array.md_minor);
-+      }
-+      if (strcmp(update, "summaries") == 0) {
-+              int i;
-+              /* set nr_disks, active_disks, working_disks,
-+               * failed_disks, spare_disks based on disks[] 
-+               * array in superblock.
-+               * Also make sure extra slots aren't 'failed'
-+               */
-+              sb->nr_disks = sb->active_disks =
-+                      sb->working_disks = sb->failed_disks =
-+                      sb->spare_disks = 0;
-+              for (i=0; i < MD_SB_DISKS ; i++) 
-+                      if (sb->disks[i].major ||
-+                          sb->disks[i].minor) {
-+                              int state = sb->disks[i].state;
-+                              if (state & (1<<MD_DISK_REMOVED))
-+                                      continue;
-+                              sb->nr_disks++;
-+                              if (state & (1<<MD_DISK_ACTIVE))
-+                                      sb->active_disks++;
-+                              if (state & (1<<MD_DISK_FAULTY))
-+                                      sb->failed_disks++;
-+                              else
-+                                      sb->working_disks++;
-+                              if (state == 0)
-+                                      sb->spare_disks++;
-+                      } else if (i >= sb->raid_disks && sb->disks[i].number == 0)
-+                              sb->disks[i].state = 0;
-+      }
-+      if (strcmp(update, "force-one")==0) {
-+              /* Not enough devices for a working array, so
-+               * bring this one up-to-date.
-+               */
-+              __u32 ehi = sb->events_hi, elo = sb->events_lo;
-+              sb->events_hi = (info->events>>32) & 0xFFFFFFFF;
-+              sb->events_lo = (info->events) & 0xFFFFFFFF;
-+              if (sb->events_hi != ehi ||
-+                  sb->events_lo != elo)
-+                      rv = 1;
-+      }
-+      if (strcmp(update, "force-array")==0) {
-+              /* degraded array and 'force' requested, so
-+               * maybe need to mark it 'clean'
-+               */
-+              if ((sb->level == 5 || sb->level == 4 || sb->level == 6) &&
-+                  (sb->state & (1 << MD_SB_CLEAN)) == 0) {
-+                      /* need to force clean */
-+                      sb->state |= (1 << MD_SB_CLEAN);
-+                      rv = 1;
-+              }
-+      }
-+      if (strcmp(update, "assemble")==0) {
-+              int d = info->disk.number;
-+              int wonly = sb->disks[d].state & (1<<MD_DISK_WRITEMOSTLY);
-+              if ((sb->disks[d].state & ~(1<<MD_DISK_WRITEMOSTLY))
-+                  != info->disk.state) {
-+                      sb->disks[d].state = info->disk.state | wonly;
-+                      rv = 1;
-+              }
-+      }
-+      if (strcmp(update, "linear-grow-new") == 0) {
-+              memset(&sb->disks[info->disk.number], 0, sizeof(sb->disks[0]));
-+              sb->disks[info->disk.number].number = info->disk.number;
-+              sb->disks[info->disk.number].major = info->disk.major;
-+              sb->disks[info->disk.number].minor = info->disk.minor;
-+              sb->disks[info->disk.number].raid_disk = info->disk.raid_disk;
-+              sb->disks[info->disk.number].state = info->disk.state;
-+              sb->this_disk = sb->disks[info->disk.number];
-+      }
-+      if (strcmp(update, "linear-grow-update") == 0) {
-+              sb->raid_disks = info->array.raid_disks;
-+              sb->nr_disks = info->array.nr_disks;
-+              sb->active_disks = info->array.active_disks;
-+              sb->working_disks = info->array.working_disks;
-+              memset(&sb->disks[info->disk.number], 0, sizeof(sb->disks[0]));
-+              sb->disks[info->disk.number].number = info->disk.number;
-+              sb->disks[info->disk.number].major = info->disk.major;
-+              sb->disks[info->disk.number].minor = info->disk.minor;
-+              sb->disks[info->disk.number].raid_disk = info->disk.raid_disk;
-+              sb->disks[info->disk.number].state = info->disk.state;
-+      }
-+      if (strcmp(update, "resync") == 0) {
-+              /* make sure resync happens */
-+              sb->state &= ~(1<<MD_SB_CLEAN);
-+              sb->recovery_cp = 0;
-+      }
-+      if (strcmp(update, "homehost") == 0 &&
-+          homehost) {
-+              uuid_set = 0;
-+              update = "uuid";
-+              info->uuid[0] = sb->set_uuid0;
-+              info->uuid[1] = sb->set_uuid1;
-+      }
-+      if (strcmp(update, "uuid") == 0) {
-+              if (!uuid_set && homehost) {
-+                      char buf[20];
-+                      char *hash = sha1_buffer(homehost,
-+                                               strlen(homehost),
-+                                               buf);
-+                      memcpy(info->uuid+2, hash, 8);
-+              }
-+              sb->set_uuid0 = info->uuid[0];
-+              sb->set_uuid1 = info->uuid[1];
-+              sb->set_uuid2 = info->uuid[2];
-+              sb->set_uuid3 = info->uuid[3];
-+              if (sb->state & (1<<MD_SB_BITMAP_PRESENT)) {
-+                      struct bitmap_super_s *bm;
-+                      bm = (struct bitmap_super_s*)(sb+1);
-+                      uuid_from_super0((int*)bm->uuid, sbv);
-+              }
-+      }
-+      if (strcmp(update, "_reshape_progress")==0)
-+              sb->reshape_position = info->reshape_progress;
-+
-+      sb->sb_csum = calc_sb0_csum(sb);
-+      return rv;
-+}
-+
-+static int store_super0(struct supertype *st, int fd, void *sbv)
-+{
-+      unsigned long long dsize;
-+      unsigned long long offset;
-+      mdp_super_t *super = sbv;
-+
-+      if (!get_dev_size(fd, NULL, &dsize))
-+              return 1;
-+
-+      if (dsize < MD_RESERVED_SECTORS*2*512)
-+              return 2;
-+
-+      offset = MD_NEW_SIZE_SECTORS(dsize>>9);
-+
-+      offset *= 512;
-+
-+      if (lseek64(fd, offset, 0)< 0LL)
-+              return 3;
-+
-+      if (write(fd, super, sizeof(*super)) != sizeof(*super))
-+              return 4;
-+
-+      if (super->state & (1<<MD_SB_BITMAP_PRESENT)) {
-+              struct bitmap_super_s * bm = (struct bitmap_super_s*)(super+1);
-+              if (__le32_to_cpu(bm->magic) == BITMAP_MAGIC)
-+                      if (write(fd, bm, sizeof(*bm)) != sizeof(*bm))
-+                          return 5;
-+      }
-+
-+      fsync(fd);
-+      return 0;
-+}
-+
-+static int compare_super0(void **firstp, void *secondv)
-+{
-+      /*
-+       * return:
-+       *  0 same, or first was empty, and second was copied
-+       *  1 second had wrong number
-+       *  2 wrong uuid
-+       *  3 wrong other info
-+       */
-+      mdp_super_t *first = *firstp;
-+      mdp_super_t *second = secondv;
-+
-+      int uuid1[4], uuid2[4];
-+      if (second->md_magic != MD_SB_MAGIC)
-+              return 1;
-+      if (!first) {
-+              first = malloc(MD_SB_BYTES + sizeof(struct bitmap_super_s));
-+              memcpy(first, second, MD_SB_BYTES + sizeof(struct bitmap_super_s));
-+              *firstp = first;
-+              return 0;
-+      }
-+
-+      uuid_from_super0(uuid1, first);
-+      uuid_from_super0(uuid2, second);
-+      if (!same_uuid(uuid1, uuid2, 0))
-+              return 2;
-+      if (first->major_version != second->major_version ||
-+          first->minor_version != second->minor_version ||
-+          first->patch_version != second->patch_version ||
-+          first->gvalid_words  != second->gvalid_words  ||
-+          first->ctime         != second->ctime         ||
-+          first->level         != second->level         ||
-+          first->size          != second->size          ||
-+          first->raid_disks    != second->raid_disks    )
-+              return 3;
-+
-+      return 0;
-+}
-+
-+
-+static int load_super0(struct supertype *st, int fd, void **sbp, char *devname)
-+{
-+      /* try to read in the superblock
-+       * Return:
-+       *  0 on success
-+       *  1 on cannot get superblock
-+       *  2 on superblock meaningless
-+       */
-+      unsigned long long dsize;
-+      unsigned long long offset;
-+      mdp_super_t *super;
-+      int uuid[4];
-+      struct bitmap_super_s *bsb;
-+    
-+      if (!get_dev_size(fd, devname, &dsize))
-+              return 1;
-+
-+      if (dsize < MD_RESERVED_SECTORS*512 * 2) {
-+              if (devname)
-+                      fprintf(stderr, Name
-+                          ": %s is too small for md: size is %llu sectors.\n",
-+                              devname, dsize);
-+              return 1;
-+      }
-+
-+      offset = MD_NEW_SIZE_SECTORS(dsize>>9);
-+
-+      offset *= 512;
-+
-+      ioctl(fd, BLKFLSBUF, 0); /* make sure we read current data */
-+
-+      if (lseek64(fd, offset, 0)< 0LL) {
-+              if (devname)
-+                      fprintf(stderr, Name ": Cannot seek to superblock on %s: %s\n",
-+                              devname, strerror(errno));
-+              return 1;
-+      }
-+
-+      super = malloc(MD_SB_BYTES + sizeof(bitmap_super_t));
-+
-+      if (read(fd, super, sizeof(*super)) != MD_SB_BYTES) {
-+              if (devname)
-+                      fprintf(stderr, Name ": Cannot read superblock on %s\n",
-+                              devname);
-+              free(super);
-+              return 1;
-+      }
-+
-+      if (st->ss && st->minor_version == 9)
-+              super0_swap_endian(super);
-+
-+      if (super->md_magic != MD_SB_MAGIC) {
-+              if (devname)
-+                      fprintf(stderr, Name ": No super block found on %s (Expected magic %08x, got %08x)\n",
-+                              devname, MD_SB_MAGIC, super->md_magic);
-+              free(super);
-+              return 2;
-+      }
-+
-+      if (super->major_version != 0) {
-+              if (devname)
-+                      fprintf(stderr, Name ": Cannot interpret superblock on %s - version is %d\n",
-+                              devname, super->major_version);
-+              free(super);
-+              return 2;
-+      }
-+      *sbp = super;
-+      if (st->ss == NULL) {
-+              st->ss = &super0;
-+              st->minor_version = 90;
-+              st->max_devs = MD_SB_DISKS;
-+      }
-+
-+      /* Now check on the bitmap superblock */
-+      if ((super->state & (1<<MD_SB_BITMAP_PRESENT)) == 0)
-+              return 0;
-+      /* Read the bitmap superblock and make sure it looks
-+       * valid.  If it doesn't clear the bit.  An --assemble --force
-+       * should get that written out.
-+       */
-+      if (read(fd, super+1, sizeof(struct bitmap_super_s))
-+          != sizeof(struct bitmap_super_s))
-+              goto no_bitmap;
-+
-+      uuid_from_super0(uuid, super);
-+      bsb = (struct bitmap_super_s *)(super+1);
-+      if (__le32_to_cpu(bsb->magic) != BITMAP_MAGIC ||
-+          memcmp(bsb->uuid, uuid, 16) != 0)
-+              goto no_bitmap;
-+      return 0;
-+
-+ no_bitmap:
-+      super->state &= ~(1<<MD_SB_BITMAP_PRESENT);
-+
-+      return 0;
-+}
-+
-+static struct supertype *match_metadata_desc0(char *arg)
-+{
-+      struct supertype *st = malloc(sizeof(*st));
-+      if (!st) return st;
-+
-+      st->ss = &super0;
-+      st->minor_version = 90;
-+      st->max_devs = MD_SB_DISKS;
-+      if (strcmp(arg, "0") == 0 ||
-+          strcmp(arg, "0.90") == 0 ||
-+          strcmp(arg, "default") == 0
-+              )
-+              return st;
-+
-+      st->minor_version = 9; /* flag for 'byte-swapped' */
-+      if (strcmp(arg, "0.swap")==0)
-+              return st;
-+
-+      free(st);
-+      return NULL;
-+}
-+
-+void locate_bitmap0(struct supertype *st, int fd, void *sbv)
-+{
-+      unsigned long long dsize;
-+      unsigned long long offset;
-+
-+      if (!get_dev_size(fd, NULL, &dsize))
-+              return;
-+
-+      if (dsize < MD_RESERVED_SECTORS*512 * 2)
-+              return;
-+
-+      offset = MD_NEW_SIZE_SECTORS(dsize>>9);
-+
-+      offset *= 512;
-+
-+      offset += MD_SB_BYTES;
-+
-+      lseek64(fd, offset, 0);
-+}
-+
-+struct superswitch super0 = {
-+      .examine_super = NULL,
-+      .brief_examine_super = brief_examine_super0,
-+      .detail_super = NULL,
-+      .brief_detail_super = NULL,
-+      .export_super = NULL,
-+      .match_home = match_home0,
-+      .uuid_from_super = uuid_from_super0,
-+      .getinfo_super = getinfo_super0,
-+      .update_super = update_super0,
-+      .init_super = NULL,
-+      .add_to_super = NULL,
-+      .store_super = store_super0,
-+      .write_init_super = NULL,
-+      .compare_super = compare_super0,
-+      .load_super = load_super0,
-+      .match_metadata_desc = match_metadata_desc0,
-+      .avail_size = NULL,
-+      .add_internal_bitmap = NULL, 
-+      .locate_bitmap = locate_bitmap0,
-+      .write_bitmap = NULL,
-+      .major = 0,
-+      .swapuuid = 0,
-+};
-diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/super1.c busybox-1.7.4+gentoo+mdadm/mdadm/super1.c
---- busybox-1.7.4+gentoo/mdadm/super1.c        1969-12-31 16:00:00.000000000 -0800
-+++ busybox-1.7.4+gentoo+mdadm/mdadm/super1.c  2008-03-11 10:31:00.000000000 -0700
-@@ -0,0 +1,731 @@
-+/*
-+ * mdadm - manage Linux "md" devices aka RAID arrays.
-+ *
-+ * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
-+ *
-+ *
-+ *    This program is free software; you can redistribute it and/or modify
-+ *    it under the terms of the GNU General Public License as published by
-+ *    the Free Software Foundation; either version 2 of the License, or
-+ *    (at your option) any later version.
-+ *
-+ *    This program is distributed in the hope that it will be useful,
-+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *    GNU General Public License for more details.
-+ *
-+ *    You should have received a copy of the GNU General Public License
-+ *    along with this program; if not, write to the Free Software
-+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ *
-+ *    Author: Neil Brown
-+ *    Email: <neilb@cse.unsw.edu.au>
-+ *    Paper: Neil Brown
-+ *           School of Computer Science and Engineering
-+ *           The University of New South Wales
-+ *           Sydney, 2052
-+ *           Australia
-+ */
-+
-+#include "mdadm.h"
-+/*
-+ * The version-1 superblock :
-+ * All numeric fields are little-endian.
-+ *
-+ * total size: 256 bytes plus 2 per device.
-+ *  1K allows 384 devices.
-+ */
-+struct mdp_superblock_1 {
-+      /* constant array information - 128 bytes */
-+      __u32   magic;          /* MD_SB_MAGIC: 0xa92b4efc - little endian */
-+      __u32   major_version;  /* 1 */
-+      __u32   feature_map;    /* 0 for now */
-+      __u32   pad0;           /* always set to 0 when writing */
-+
-+      __u8    set_uuid[16];   /* user-space generated. */
-+      char    set_name[32];   /* set and interpreted by user-space */
-+
-+      __u64   ctime;          /* lo 40 bits are seconds, top 24 are microseconds or 0*/
-+      __u32   level;          /* -4 (multipath), -1 (linear), 0,1,4,5 */
-+      __u32   layout;         /* only for raid5 currently */
-+      __u64   size;           /* used size of component devices, in 512byte sectors */
-+
-+      __u32   chunksize;      /* in 512byte sectors */
-+      __u32   raid_disks;
-+      __u32   bitmap_offset;  /* sectors after start of superblock that bitmap starts
-+                               * NOTE: signed, so bitmap can be before superblock
-+                               * only meaningful of feature_map[0] is set.
-+                               */
-+
-+      /* These are only valid with feature bit '4' */
-+      __u32   new_level;      /* new level we are reshaping to                */
-+      __u64   reshape_position;       /* next address in array-space for reshape */
-+      __u32   delta_disks;    /* change in number of raid_disks               */
-+      __u32   new_layout;     /* new layout                                   */
-+      __u32   new_chunk;      /* new chunk size (bytes)                       */
-+      __u8    pad1[128-124];  /* set to 0 when written */
-+
-+      /* constant this-device information - 64 bytes */
-+      __u64   data_offset;    /* sector start of data, often 0 */
-+      __u64   data_size;      /* sectors in this device that can be used for data */
-+      __u64   super_offset;   /* sector start of this superblock */
-+      __u64   recovery_offset;/* sectors before this offset (from data_offset) have been recovered */
-+      __u32   dev_number;     /* permanent identifier of this  device - not role in raid */
-+      __u32   cnt_corrected_read; /* number of read errors that were corrected by re-writing */
-+      __u8    device_uuid[16]; /* user-space setable, ignored by kernel */
-+        __u8    devflags;        /* per-device flags.  Only one defined...*/
-+#define WriteMostly1    1        /* mask for writemostly flag in above */
-+      __u8    pad2[64-57];    /* set to 0 when writing */
-+
-+      /* array state information - 64 bytes */
-+      __u64   utime;          /* 40 bits second, 24 btes microseconds */
-+      __u64   events;         /* incremented when superblock updated */
-+      __u64   resync_offset;  /* data before this offset (from data_offset) known to be in sync */
-+      __u32   sb_csum;        /* checksum upto devs[max_dev] */
-+      __u32   max_dev;        /* size of devs[] array to consider */
-+      __u8    pad3[64-32];    /* set to 0 when writing */
-+
-+      /* device state information. Indexed by dev_number.
-+       * 2 bytes per device
-+       * Note there are no per-device state flags. State information is rolled
-+       * into the 'roles' value.  If a device is spare or faulty, then it doesn't
-+       * have a meaningful role.
-+       */
-+      __u16   dev_roles[0];   /* role in array, or 0xffff for a spare, or 0xfffe for faulty */
-+};
-+
-+struct misc_dev_info {
-+      __u64 device_size;
-+};
-+
-+/* feature_map bits */
-+#define MD_FEATURE_BITMAP_OFFSET      1
-+#define       MD_FEATURE_RECOVERY_OFFSET      2 /* recovery_offset is present and
-+                                         * must be honoured
-+                                         */
-+#define       MD_FEATURE_RESHAPE_ACTIVE       4
-+
-+#define       MD_FEATURE_ALL                  (1|2|4)
-+
-+#ifndef offsetof
-+#define offsetof(t,f) ((size_t)&(((t*)0)->f))
-+#endif
-+static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb)
-+{
-+      unsigned int disk_csum, csum;
-+      unsigned long long newcsum;
-+      int size = sizeof(*sb) + __le32_to_cpu(sb->max_dev)*2;
-+      unsigned int *isuper = (unsigned int*)sb;
-+      int i;
-+
-+/* make sure I can count... */
-+      if (offsetof(struct mdp_superblock_1,data_offset) != 128 ||
-+          offsetof(struct mdp_superblock_1, utime) != 192 ||
-+          sizeof(struct mdp_superblock_1) != 256) {
-+              fprintf(stderr, "WARNING - superblock isn't sized correctly\n");
-+      }
-+
-+      disk_csum = sb->sb_csum;
-+      sb->sb_csum = 0;
-+      newcsum = 0;
-+      for (i=0; size>=4; size -= 4 ) {
-+              newcsum += __le32_to_cpu(*isuper);
-+              isuper++;
-+      }
-+
-+      if (size == 2)
-+              newcsum += __le16_to_cpu(*(unsigned short*) isuper);
-+
-+      csum = (newcsum & 0xffffffff) + (newcsum >> 32);
-+      sb->sb_csum = disk_csum;
-+      return __cpu_to_le32(csum);
-+}
-+
-+static void brief_examine_super1(void *sbv)
-+{
-+      struct mdp_superblock_1 *sb = sbv;
-+      int i;
-+      unsigned long long sb_offset;
-+      char *nm;
-+      char *c=map_num(pers, __le32_to_cpu(sb->level));
-+
-+      nm = strchr(sb->set_name, ':');
-+      if (nm)
-+              nm++;
-+      else if (sb->set_name[0])
-+              nm = sb->set_name;
-+      else
-+              nm = "??";
-+
-+      printf("ARRAY /dev/md%s level=%s ", nm, c?c:"-unknown-");
-+      sb_offset = __le64_to_cpu(sb->super_offset);
-+      if (sb_offset <= 4)
-+              printf("metadata=1.1 ");
-+      else if (sb_offset <= 8)
-+              printf("metadata=1.2 ");
-+      else
-+              printf("metadata=1.0 ");
-+      printf("num-devices=%d UUID=", __le32_to_cpu(sb->raid_disks));
-+      for (i=0; i<16; i++) {
-+              if ((i&3)==0 && i != 0) printf(":");
-+              printf("%02x", sb->set_uuid[i]);
-+      }
-+      if (sb->set_name[0])
-+              printf(" name=%.32s", sb->set_name);
-+      printf("\n");
-+}
-+
-+static int match_home1(void *sbv, char *homehost)
-+{
-+      struct mdp_superblock_1 *sb = sbv;
-+      int l = homehost ? strlen(homehost) : 0;
-+
-+      return (l > 0 && l < 32 &&
-+              sb->set_name[l] == ':' &&
-+              strncmp(sb->set_name, homehost, l) == 0);
-+}
-+
-+static void uuid_from_super1(int uuid[4], void * sbv)
-+{
-+      struct mdp_superblock_1 *super = sbv;
-+      char *cuuid = (char*)uuid;
-+      int i;
-+      for (i=0; i<16; i++)
-+              cuuid[i] = super->set_uuid[i];
-+}
-+
-+static void getinfo_super1(struct mdinfo *info, void *sbv)
-+{
-+      struct mdp_superblock_1 *sb = sbv;
-+      int working = 0;
-+      int i;
-+      int role;
-+
-+      info->array.major_version = 1;
-+      info->array.minor_version = __le32_to_cpu(sb->feature_map);
-+      info->array.patch_version = 0;
-+      info->array.raid_disks = __le32_to_cpu(sb->raid_disks);
-+      info->array.level = __le32_to_cpu(sb->level);
-+      info->array.layout = __le32_to_cpu(sb->layout);
-+      info->array.md_minor = -1;
-+      info->array.ctime = __le64_to_cpu(sb->ctime);
-+      info->array.utime = __le64_to_cpu(sb->utime);
-+      info->array.chunk_size = __le32_to_cpu(sb->chunksize)*512;
-+      info->array.state =
-+              (__le64_to_cpu(sb->resync_offset) >= __le64_to_cpu(sb->size))
-+              ? 1 : 0;
-+
-+      info->data_offset = __le64_to_cpu(sb->data_offset);
-+      info->component_size = __le64_to_cpu(sb->size);
-+
-+      info->disk.major = 0;
-+      info->disk.minor = 0;
-+      info->disk.number = __le32_to_cpu(sb->dev_number);
-+      if (__le32_to_cpu(sb->dev_number) >= __le32_to_cpu(sb->max_dev) ||
-+          __le32_to_cpu(sb->max_dev) > 512)
-+              role = 0xfffe;
-+      else
-+              role = __le16_to_cpu(sb->dev_roles[__le32_to_cpu(sb->dev_number)]);
-+
-+      info->disk.raid_disk = -1;
-+      switch(role) {
-+      case 0xFFFF:
-+              info->disk.state = 2; /* spare: ACTIVE, not sync, not faulty */
-+              break;
-+      case 0xFFFE:
-+              info->disk.state = 1; /* faulty */
-+              break;
-+      default:
-+              info->disk.state = 6; /* active and in sync */
-+              info->disk.raid_disk = role;
-+      }
-+      info->events = __le64_to_cpu(sb->events);
-+
-+      memcpy(info->uuid, sb->set_uuid, 16);
-+
-+      strncpy(info->name, sb->set_name, 32);
-+      info->name[32] = 0;
-+
-+      if (sb->feature_map & __le32_to_cpu(MD_FEATURE_RESHAPE_ACTIVE)) {
-+              info->reshape_active = 1;
-+              info->reshape_progress = __le64_to_cpu(sb->reshape_position);
-+              info->new_level = __le32_to_cpu(sb->new_level);
-+              info->delta_disks = __le32_to_cpu(sb->delta_disks);
-+              info->new_layout = __le32_to_cpu(sb->new_layout);
-+              info->new_chunk = __le32_to_cpu(sb->new_chunk)<<9;
-+      } else
-+              info->reshape_active = 0;
-+
-+      for (i=0; i< __le32_to_cpu(sb->max_dev); i++) {
-+              role = __le16_to_cpu(sb->dev_roles[i]);
-+              if (/*role == 0xFFFF || */role < info->array.raid_disks)
-+                      working++;
-+      }
-+
-+      info->array.working_disks = working;
-+}
-+
-+static int update_super1(struct mdinfo *info, void *sbv, char *update,
-+                       char *devname, int verbose,
-+                       int uuid_set, char *homehost)
-+{
-+      /* NOTE: for 'assemble' and 'force' we need to return non-zero if any change was made.
-+       * For others, the return value is ignored.
-+       */
-+      int rv = 0;
-+      struct mdp_superblock_1 *sb = sbv;
-+
-+      if (strcmp(update, "force-one")==0) {
-+              /* Not enough devices for a working array,
-+               * so bring this one up-to-date
-+               */
-+              if (sb->events != __cpu_to_le64(info->events))
-+                      rv = 1;
-+              sb->events = __cpu_to_le64(info->events);
-+      }
-+      if (strcmp(update, "force-array")==0) {
-+              /* Degraded array and 'force' requests to
-+               * maybe need to mark it 'clean'.
-+               */
-+              switch(__le32_to_cpu(sb->level)) {
-+              case 5: case 4: case 6:
-+                      /* need to force clean */
-+                      if (sb->resync_offset != ~0ULL)
-+                              rv = 1;
-+                      sb->resync_offset = ~0ULL;
-+              }
-+      }
-+      if (strcmp(update, "assemble")==0) {
-+              int d = info->disk.number;
-+              int want;
-+              if (info->disk.state == 6)
-+                      want = __cpu_to_le32(info->disk.raid_disk);
-+              else
-+                      want = 0xFFFF;
-+              if (sb->dev_roles[d] != want) {
-+                      sb->dev_roles[d] = want;
-+                      rv = 1;
-+              }
-+      }
-+      if (strcmp(update, "linear-grow-new") == 0) {
-+              int i;
-+              int rfd;
-+              int max = __le32_to_cpu(sb->max_dev);
-+
-+              for (i=0 ; i < max ; i++)
-+                      if (__le16_to_cpu(sb->dev_roles[i]) >= 0xfffe)
-+                              break;
-+              sb->dev_number = __cpu_to_le32(i);
-+              info->disk.number = i;
-+              if (max >= __le32_to_cpu(sb->max_dev))
-+                      sb->max_dev = __cpu_to_le32(max+1);
-+
-+              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();
-+              }
-+
-+              sb->dev_roles[i] =
-+                      __cpu_to_le16(info->disk.raid_disk);
-+      }
-+      if (strcmp(update, "linear-grow-update") == 0) {
-+              sb->raid_disks = __cpu_to_le32(info->array.raid_disks);
-+              sb->dev_roles[info->disk.number] =
-+                      __cpu_to_le16(info->disk.raid_disk);
-+      }
-+      if (strcmp(update, "resync") == 0) {
-+              /* make sure resync happens */
-+              sb->resync_offset = 0ULL;
-+      }
-+      if (strcmp(update, "uuid") == 0) {
-+              copy_uuid(sb->set_uuid, info->uuid, super1.swapuuid);
-+
-+              if (__le32_to_cpu(sb->feature_map)&MD_FEATURE_BITMAP_OFFSET) {
-+                      struct bitmap_super_s *bm;
-+                      bm = (struct bitmap_super_s*)(sbv+1024);
-+                      memcpy(bm->uuid, sb->set_uuid, 16);
-+              }
-+      }
-+      if (strcmp(update, "homehost") == 0 &&
-+          homehost) {
-+              char *c;
-+              update = "name";
-+              c = strchr(sb->set_name, ':');
-+              if (c)
-+                      strncpy(info->name, c+1, 31 - (c-sb->set_name));
-+              else
-+                      strncpy(info->name, sb->set_name, 32);
-+              info->name[32] = 0;
-+      }
-+      if (strcmp(update, "name") == 0) {
-+              if (info->name[0] == 0)
-+                      sprintf(info->name, "%d", info->array.md_minor);
-+              memset(sb->set_name, 0, sizeof(sb->set_name));
-+              if (homehost &&
-+                  strchr(info->name, ':') == NULL &&
-+                  strlen(homehost)+1+strlen(info->name) < 32) {
-+                      strcpy(sb->set_name, homehost);
-+                      strcat(sb->set_name, ":");
-+                      strcat(sb->set_name, info->name);
-+              } else
-+                      strcpy(sb->set_name, info->name);
-+      }
-+      if (strcmp(update, "devicesize") == 0 &&
-+          __le64_to_cpu(sb->super_offset) <
-+          __le64_to_cpu(sb->data_offset)) {
-+              /* set data_size to device size less data_offset */
-+              struct misc_dev_info *misc = (struct misc_dev_info*)
-+                      (sbv + 1024 + sizeof(struct bitmap_super_s));
-+              printf("Size was %llu\n", (unsigned long long)
-+                     __le64_to_cpu(sb->data_size));
-+              sb->data_size = __cpu_to_le64(
-+                      misc->device_size - __le64_to_cpu(sb->data_offset));
-+              printf("Size is %llu\n", (unsigned long long)
-+                     __le64_to_cpu(sb->data_size));
-+      }
-+      if (strcmp(update, "_reshape_progress")==0)
-+              sb->reshape_position = __cpu_to_le64(info->reshape_progress);
-+
-+      sb->sb_csum = calc_sb_1_csum(sb);
-+      return rv;
-+}
-+
-+static void locate_bitmap1(struct supertype *st, int fd, void *sbv);
-+
-+static int store_super1(struct supertype *st, int fd, void *sbv)
-+{
-+      struct mdp_superblock_1 *sb = sbv;
-+      unsigned long long sb_offset;
-+      int sbsize;
-+      unsigned long long dsize;
-+
-+      if (!get_dev_size(fd, NULL, &dsize))
-+              return 1;
-+
-+      dsize >>= 9;
-+
-+      if (dsize < 24)
-+              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.
-+       */
-+      switch(st->minor_version) {
-+      case 0:
-+              sb_offset = dsize;
-+              sb_offset -= 8*2;
-+              sb_offset &= ~(4*2-1);
-+              break;
-+      case 1:
-+              sb_offset = 0;
-+              break;
-+      case 2:
-+              sb_offset = 4*2;
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+
-+
-+
-+      if (sb_offset != __le64_to_cpu(sb->super_offset) &&
-+          0 != __le64_to_cpu(sb->super_offset)
-+              ) {
-+              fprintf(stderr, Name ": internal error - sb_offset is wrong\n");
-+              abort();
-+      }
-+
-+      if (lseek64(fd, sb_offset << 9, 0)< 0LL)
-+              return 3;
-+
-+      sbsize = sizeof(*sb) + 2 * __le32_to_cpu(sb->max_dev);
-+
-+      if (write(fd, sb, sbsize) != sbsize)
-+              return 4;
-+
-+      if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) {
-+              struct bitmap_super_s *bm = (struct bitmap_super_s*)
-+                      (((char*)sb)+1024);
-+              if (__le32_to_cpu(bm->magic) == BITMAP_MAGIC) {
-+                      locate_bitmap1(st, fd, sbv);
-+                      if (write(fd, bm, sizeof(*bm)) != sizeof(*bm))
-+                          return 5;
-+              }
-+      }
-+      fsync(fd);
-+      return 0;
-+}
-+
-+static int load_super1(struct supertype *st, int fd, void **sbp, char *devname);
-+
-+static int compare_super1(void **firstp, void *secondv)
-+{
-+      /*
-+       * return:
-+       *  0 same, or first was empty, and second was copied
-+       *  1 second had wrong number
-+       *  2 wrong uuid
-+       *  3 wrong other info
-+       */
-+      struct mdp_superblock_1 *first = *firstp;
-+      struct mdp_superblock_1 *second = secondv;
-+
-+      if (second->magic != __cpu_to_le32(MD_SB_MAGIC))
-+              return 1;
-+      if (second->major_version != __cpu_to_le32(1))
-+              return 1;
-+
-+      if (!first) {
-+              first = malloc(1024+sizeof(bitmap_super_t) +
-+                             sizeof(struct misc_dev_info));
-+              memcpy(first, second, 1024+sizeof(bitmap_super_t) +
-+                     sizeof(struct misc_dev_info));
-+              *firstp = first;
-+              return 0;
-+      }
-+      if (memcmp(first->set_uuid, second->set_uuid, 16)!= 0)
-+              return 2;
-+
-+      if (first->ctime      != second->ctime     ||
-+          first->level      != second->level     ||
-+          first->layout     != second->layout    ||
-+          first->size       != second->size      ||
-+          first->chunksize  != second->chunksize ||
-+          first->raid_disks != second->raid_disks)
-+              return 3;
-+      return 0;
-+}
-+
-+static int load_super1(struct supertype *st, int fd, void **sbp, char *devname)
-+{
-+      unsigned long long dsize;
-+      unsigned long long sb_offset;
-+      struct mdp_superblock_1 *super;
-+      int uuid[4];
-+      struct bitmap_super_s *bsb;
-+      struct misc_dev_info *misc;
-+
-+
-+      if (st->ss == NULL) {
-+              int bestvers = -1;
-+              __u64 bestctime = 0;
-+              /* guess... choose latest ctime */
-+              st->ss = &super1;
-+              for (st->minor_version = 0; st->minor_version <= 2 ; st->minor_version++) {
-+                      switch(load_super1(st, fd, sbp, devname)) {
-+                      case 0: super = *sbp;
-+                              if (bestvers == -1 ||
-+                                  bestctime < __le64_to_cpu(super->ctime)) {
-+                                      bestvers = st->minor_version;
-+                                      bestctime = __le64_to_cpu(super->ctime);
-+                              }
-+                              free(super);
-+                              *sbp = NULL;
-+                              break;
-+                      case 1: st->ss = NULL; return 1; /*bad device */
-+                      case 2: break; /* bad, try next */
-+                      }
-+              }
-+              if (bestvers != -1) {
-+                      int rv;
-+                      st->minor_version = bestvers;
-+                      st->ss = &super1;
-+                      st->max_devs = 384;
-+                      rv = load_super1(st, fd, sbp, devname);
-+                      if (rv) st->ss = NULL;
-+                      return rv;
-+              }
-+              st->ss = NULL;
-+              return 2;
-+      }
-+      if (!get_dev_size(fd, devname, &dsize))
-+              return 1;
-+      dsize >>= 9;
-+
-+      if (dsize < 24) {
-+              if (devname)
-+                      fprintf(stderr, Name ": %s is too small for md: size is %llu sectors.\n",
-+                              devname, dsize);
-+              return 1;
-+      }
-+
-+      /*
-+       * 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.
-+       */
-+      switch(st->minor_version) {
-+      case 0:
-+              sb_offset = dsize;
-+              sb_offset -= 8*2;
-+              sb_offset &= ~(4*2-1);
-+              break;
-+      case 1:
-+              sb_offset = 0;
-+              break;
-+      case 2:
-+              sb_offset = 4*2;
-+              break;
-+      default:
-+              return -EINVAL;
-+      }
-+
-+      ioctl(fd, BLKFLSBUF, 0); /* make sure we read current data */
-+
-+
-+      if (lseek64(fd, sb_offset << 9, 0)< 0LL) {
-+              if (devname)
-+                      fprintf(stderr, Name ": Cannot seek to superblock on %s: %s\n",
-+                              devname, strerror(errno));
-+              return 1;
-+      }
-+
-+      super = malloc(1024 + sizeof(bitmap_super_t) +
-+                     sizeof(struct misc_dev_info));
-+
-+      if (read(fd, super, 1024) != 1024) {
-+              if (devname)
-+                      fprintf(stderr, Name ": Cannot read superblock on %s\n",
-+                              devname);
-+              free(super);
-+              return 1;
-+      }
-+
-+      if (__le32_to_cpu(super->magic) != MD_SB_MAGIC) {
-+              if (devname)
-+                      fprintf(stderr, Name ": No super block found on %s (Expected magic %08x, got %08x)\n",
-+                              devname, MD_SB_MAGIC, __le32_to_cpu(super->magic));
-+              free(super);
-+              return 2;
-+      }
-+
-+      if (__le32_to_cpu(super->major_version) != 1) {
-+              if (devname)
-+                      fprintf(stderr, Name ": Cannot interpret superblock on %s - version is %d\n",
-+                              devname, __le32_to_cpu(super->major_version));
-+              free(super);
-+              return 2;
-+      }
-+      if (__le64_to_cpu(super->super_offset) != sb_offset) {
-+              if (devname)
-+                      fprintf(stderr, Name ": No superblock found on %s (super_offset is wrong)\n",
-+                              devname);
-+              free(super);
-+              return 2;
-+      }
-+      *sbp = super;
-+
-+      bsb = (struct bitmap_super_s *)(((char*)super)+1024);
-+
-+      misc = (struct misc_dev_info*) (bsb+1);
-+      misc->device_size = dsize;
-+
-+      /* Now check on the bitmap superblock */
-+      if ((__le32_to_cpu(super->feature_map)&MD_FEATURE_BITMAP_OFFSET) == 0)
-+              return 0;
-+      /* Read the bitmap superblock and make sure it looks
-+       * valid.  If it doesn't clear the bit.  An --assemble --force
-+       * should get that written out.
-+       */
-+      locate_bitmap1(st, fd, super);
-+      if (read(fd, ((char*)super)+1024, sizeof(struct bitmap_super_s))
-+          != sizeof(struct bitmap_super_s))
-+              goto no_bitmap;
-+
-+      uuid_from_super1(uuid, super);
-+      if (__le32_to_cpu(bsb->magic) != BITMAP_MAGIC ||
-+          memcmp(bsb->uuid, uuid, 16) != 0)
-+              goto no_bitmap;
-+      return 0;
-+
-+ no_bitmap:
-+      super->feature_map = __cpu_to_le32(__le32_to_cpu(super->feature_map) & ~1);
-+      return 0;
-+}
-+
-+
-+static struct supertype *match_metadata_desc1(char *arg)
-+{
-+      struct supertype *st = malloc(sizeof(*st));
-+      if (!st) return st;
-+
-+      st->ss = &super1;
-+      st->max_devs = 384;
-+      if (strcmp(arg, "1") == 0 ||
-+          strcmp(arg, "1.0") == 0 ||
-+          strcmp(arg, "default/large") == 0) {
-+              st->minor_version = 0;
-+              return st;
-+      }
-+      if (strcmp(arg, "1.1") == 0) {
-+              st->minor_version = 1;
-+              return st;
-+      }
-+      if (strcmp(arg, "1.2") == 0) {
-+              st->minor_version = 2;
-+              return st;
-+      }
-+
-+      free(st);
-+      return NULL;
-+}
-+
-+static void locate_bitmap1(struct supertype *st, int fd, void *sbv)
-+{
-+      unsigned long long offset;
-+      struct mdp_superblock_1 *sb;
-+      int mustfree = 0;
-+
-+      if (!sbv) {
-+              if (st->ss->load_super(st, fd, &sbv, NULL))
-+                      return; /* no error I hope... */
-+              mustfree = 1;
-+      }
-+      sb = sbv;
-+
-+      offset = __le64_to_cpu(sb->super_offset);
-+      offset += (int32_t) __le32_to_cpu(sb->bitmap_offset);
-+      if (mustfree)
-+              free(sb);
-+      lseek64(fd, offset<<9, 0);
-+}
-+
-+struct superswitch super1 = {
-+      .examine_super = NULL,
-+      .brief_examine_super = brief_examine_super1,
-+      .detail_super = NULL,
-+      .brief_detail_super = NULL,
-+      .export_super = NULL,
-+      .match_home = match_home1,
-+      .uuid_from_super = uuid_from_super1,
-+      .getinfo_super = getinfo_super1,
-+      .update_super = update_super1,
-+      .init_super = NULL,
-+      .add_to_super = NULL,
-+      .store_super = store_super1,
-+      .write_init_super = NULL,
-+      .compare_super = compare_super1,
-+      .load_super = load_super1,
-+      .match_metadata_desc = match_metadata_desc1,
-+      .avail_size = NULL,
-+      .add_internal_bitmap = NULL,
-+      .locate_bitmap = locate_bitmap1,
-+      .write_bitmap = NULL,
-+      .major = 1,
-+#if __BYTE_ORDER == BIG_ENDIAN
-+      .swapuuid = 0,
-+#else
-+      .swapuuid = 1,
-+#endif
-+};
-diff -Nuar --exclude '*.orig' busybox-1.7.4+gentoo/mdadm/util.c busybox-1.7.4+gentoo+mdadm/mdadm/util.c
---- busybox-1.7.4+gentoo/mdadm/util.c  1969-12-31 16:00:00.000000000 -0800
-+++ busybox-1.7.4+gentoo+mdadm/mdadm/util.c    2008-03-11 10:31:00.000000000 -0700
-@@ -0,0 +1,652 @@
-+/*
-+ * mdadm - manage Linux "md" devices aka RAID arrays.
-+ *
-+ * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
-+ *
-+ *
-+ *    This program is free software; you can redistribute it and/or modify
-+ *    it under the terms of the GNU General Public License as published by
-+ *    the Free Software Foundation; either version 2 of the License, or
-+ *    (at your option) any later version.
-+ *
-+ *    This program is distributed in the hope that it will be useful,
-+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ *    GNU General Public License for more details.
-+ *
-+ *    You should have received a copy of the GNU General Public License
-+ *    along with this program; if not, write to the Free Software
-+ *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-+ *
-+ *    Author: Neil Brown
-+ *    Email: <neilb@cse.unsw.edu.au>
-+ *    Paper: Neil Brown
-+ *           School of Computer Science and Engineering
-+ *           The University of New South Wales
-+ *           Sydney, 2052
-+ *           Australia
-+ */
-+
-+#include      "mdadm.h"
-+#include      "md_p.h"
-+#include      <sys/utsname.h>
-+#include      <ctype.h>
-+
-+/*
-+ * following taken from linux/blkpg.h because they aren't
-+ * anywhere else and it isn't safe to #include linux/ * stuff.
-+ */
-+
-+#define BLKPG      _IO(0x12,105)
-+
-+/* The argument structure */
-+struct blkpg_ioctl_arg {
-+        int op;
-+        int flags;
-+        int datalen;
-+        void *data;
-+};
-+
-+/* The subfunctions (for the op field) */
-+#define BLKPG_ADD_PARTITION   1
-+#define BLKPG_DEL_PARTITION   2
-+
-+/* Sizes of name fields. Unused at present. */
-+#define BLKPG_DEVNAMELTH      64
-+#define BLKPG_VOLNAMELTH      64
-+
-+/* The data structure for ADD_PARTITION and DEL_PARTITION */
-+struct blkpg_partition {
-+      long long start;                /* starting offset in bytes */
-+      long long length;               /* length in bytes */
-+      int pno;                        /* partition number */
-+      char devname[BLKPG_DEVNAMELTH]; /* partition name, like sda5 or c0d1p2,
-+                                         to be used in kernel messages */
-+      char volname[BLKPG_VOLNAMELTH]; /* volume label */
-+};
-+
-+/*
-+ * Parse a 128 bit uuid in 4 integers
-+ * format is 32 hexx nibbles with options :.<space> separator
-+ * If not exactly 32 hex digits are found, return 0
-+ * else return 1
-+ */
-+int parse_uuid(char *str, int uuid[4])
-+{
-+    int hit = 0; /* number of Hex digIT */
-+    int i;
-+    char c;
-+    for (i=0; i<4; i++) uuid[i]=0;
-+
-+    while ((c= *str++)) {
-+      int n;
-+      if (c>='0' && c<='9')
-+          n = c-'0';
-+      else if (c>='a' && c <= 'f')
-+          n = 10 + c - 'a';
-+      else if (c>='A' && c <= 'F')
-+          n = 10 + c - 'A';
-+      else if (strchr(":. -", c))
-+          continue;
-+      else return 0;
-+
-+      if (hit<32) {
-+          uuid[hit/8] <<= 4;
-+          uuid[hit/8] += n;
-+      }
-+      hit++;
-+    }
-+    if (hit == 32)
-+      return 1;
-+    return 0;
-+    
-+}
-+
-+
-+/*
-+ * Get the md version number.
-+ * We use the RAID_VERSION ioctl if it is supported
-+ * If not, but we have a block device with major '9', we assume
-+ * 0.36.0
-+ *
-+ * Return version number as 24 but number - assume version parts
-+ * always < 255
-+ */
-+
-+int md_get_version(int fd)
-+{
-+    struct stat stb;
-+    mdu_version_t vers;
-+
-+    if (fstat(fd, &stb)<0)
-+      return -1;
-+    if ((S_IFMT&stb.st_mode) != S_IFBLK)
-+      return -1;
-+
-+    if (ioctl(fd, RAID_VERSION, &vers) == 0)
-+      return  (vers.major*10000) + (vers.minor*100) + vers.patchlevel;
-+    if (errno == EACCES)
-+          return -1;
-+    if (major(stb.st_rdev) == MD_MAJOR)
-+      return (3600);
-+    return -1;
-+}
-+
-+    
-+int get_linux_version()
-+{
-+      struct utsname name;
-+      char *cp;
-+      int a,b,c;
-+      if (uname(&name) <0)
-+              return -1;
-+
-+      cp = name.release;
-+      a = strtoul(cp, &cp, 10);
-+      if (*cp != '.') return -1;
-+      b = strtoul(cp+1, &cp, 10);
-+      if (*cp != '.') return -1;
-+      c = strtoul(cp+1, NULL, 10);
-+
-+      return (a*1000000)+(b*1000)+c;
-+}
-+
-+void remove_partitions(int fd)
-+{
-+      /* remove partitions from this block devices.
-+       * This is used for components added to an array
-+       */
-+#ifdef BLKPG_DEL_PARTITION
-+      struct blkpg_ioctl_arg a;
-+      struct blkpg_partition p;
-+
-+      a.op = BLKPG_DEL_PARTITION;
-+      a.data = (void*)&p;
-+      a.datalen = sizeof(p);
-+      a.flags = 0;
-+      memset(a.data, 0, a.datalen);
-+      for (p.pno=0; p.pno < 16; p.pno++)
-+              ioctl(fd, BLKPG, &a);
-+#endif
-+}
-+
-+int enough(int level, int raid_disks, int layout, int clean,
-+         char *avail, int avail_disks)
-+{
-+      int copies, first;
-+      switch (level) {
-+      case 10:
-+              /* This is the tricky one - we need to check
-+               * which actual disks are present.
-+               */
-+              copies = (layout&255)* ((layout>>8) & 255);
-+              first=0;
-+              do {
-+                      /* there must be one of the 'copies' form 'first' */
-+                      int n = copies;
-+                      int cnt=0;
-+                      while (n--) {
-+                              if (avail[first])
-+                                      cnt++;
-+                              first = (first+1) % raid_disks;
-+                      }
-+                      if (cnt == 0)
-+                              return 0;
-+
-+              } while (first != 0);
-+              return 1;
-+
-+      case -4:
-+              return avail_disks>= 1;
-+      case -1:
-+      case 0:
-+              return avail_disks == raid_disks;
-+      case 1:
-+              return avail_disks >= 1;
-+      case 4:
-+      case 5:
-+              if (clean)
-+                      return avail_disks >= raid_disks-1;
-+              else
-+                      return avail_disks >= raid_disks;
-+      case 6:
-+              if (clean)
-+                      return avail_disks >= raid_disks-2;
-+              else
-+                      return avail_disks >= raid_disks;
-+      default:
-+              return 0;
-+      }
-+}
-+
-+int same_uuid(int a[4], int b[4], int swapuuid)
-+{
-+      if (swapuuid) {
-+              /* parse uuids are hostendian.
-+               * uuid's from some superblocks are big-ending
-+               * if there is a difference, we need to swap.. 
-+               */
-+              unsigned char *ac = (unsigned char *)a;
-+              unsigned char *bc = (unsigned char *)b;
-+              int i;
-+              for (i=0; i<16; i+= 4) {
-+                      if (ac[i+0] != bc[i+3] ||
-+                          ac[i+1] != bc[i+2] ||
-+                          ac[i+2] != bc[i+1] ||
-+                          ac[i+3] != bc[i+0])
-+                              return 0;
-+              }
-+              return 1;
-+      } else {
-+              if (a[0]==b[0] &&
-+                  a[1]==b[1] &&
-+                  a[2]==b[2] &&
-+                  a[3]==b[3])
-+                      return 1;
-+              return 0;
-+      }
-+}
-+void copy_uuid(void *a, int b[4], int swapuuid)
-+{
-+      if (swapuuid) {
-+              /* parse uuids are hostendian.
-+               * uuid's from some superblocks are big-ending
-+               * if there is a difference, we need to swap..
-+               */
-+              unsigned char *ac = (unsigned char *)a;
-+              unsigned char *bc = (unsigned char *)b;
-+              int i;
-+              for (i=0; i<16; i+= 4) {
-+                      ac[i+0] = bc[i+3];
-+                      ac[i+1] = bc[i+2];
-+                      ac[i+2] = bc[i+1];
-+                      ac[i+3] = bc[i+0];
-+              }
-+      } else
-+              memcpy(a, b, 16);
-+}
-+
-+char *map_num(mapping_t *map, int num)
-+{
-+      while (map->name) {
-+              if (map->num == num)
-+                      return map->name;
-+              map++;
-+      }
-+      return NULL;
-+}
-+
-+int map_name(mapping_t *map, char *name)
-+{
-+      while (map->name) {
-+              if (strcmp(map->name, name)==0)
-+                      return map->num;
-+              map++;
-+      }
-+      return UnSet;
-+}
-+
-+
-+int is_standard(char *dev, int *nump)
-+{
-+      /* tests if dev is a "standard" md dev name.
-+       * i.e if the last component is "/dNN" or "/mdNN",
-+       * where NN is a string of digits 
-+       */
-+      char *d = strrchr(dev, '/');
-+      int type=0;
-+      int num;
-+      if (!d)
-+              return 0;
-+      if (strncmp(d, "/d",2)==0)
-+              d += 2, type=1; /* /dev/md/dN{pM} */
-+      else if (strncmp(d, "/md_d", 5)==0)
-+              d += 5, type=1; /* /dev/md_dNpM */
-+      else if (strncmp(d, "/md", 3)==0)
-+              d += 3, type=-1; /* /dev/mdN */
-+      else if (d-dev > 3 && strncmp(d-2, "md/", 3)==0)
-+              d += 1, type=-1; /* /dev/md/N */
-+      else
-+              return 0;
-+      if (!*d)
-+              return 0;
-+      num = atoi(d);
-+      while (isdigit(*d))
-+              d++;
-+      if (*d)
-+              return 0;
-+      if (nump) *nump = num;
-+
-+      return type;
-+}
-+
-+
-+/*
-+ * convert a major/minor pair for a block device into a name in /dev, if possible.
-+ * On the first call, walk /dev collecting name.
-+ * Put them in a simple linked listfor now.
-+ */
-+struct devmap {
-+    int major, minor;
-+    char *name;
-+    struct devmap *next;
-+} *devlist = NULL;
-+int devlist_ready = 0;
-+
-+int add_dev(const char *name, const struct stat *stb, int flag, struct FTW *s)
-+{
-+      struct stat st;
-+      if (S_ISLNK(stb->st_mode)) {
-+              stat(name, &st);
-+              stb = &st;
-+      }
-+
-+      if ((stb->st_mode&S_IFMT)== S_IFBLK) {
-+              char *n = strdup(name);
-+              struct devmap *dm = malloc(sizeof(*dm));
-+              if (strncmp(n, "/dev/./", 7)==0)
-+                      strcpy(n+4, name+6);
-+              if (dm) {
-+                      dm->major = major(stb->st_rdev);
-+                      dm->minor = minor(stb->st_rdev);
-+                      dm->name = n;
-+                      dm->next = devlist;
-+                      devlist = dm;
-+              }
-+      }
-+      return 0;
-+}
-+
-+#ifndef HAVE_NFTW
-+#ifdef HAVE_FTW
-+int add_dev_1(const char *name, const struct stat *stb, int flag)
-+{
-+      return add_dev(name, stb, flag, NULL);
-+}
-+int nftw(const char *path, int (*han)(const char *name, const struct stat *stb, int flag, struct FTW *s), int nopenfd, int flags)
-+{
-+      return ftw(path, add_dev_1, nopenfd);
-+}
-+#else
-+int nftw(const char *path, int (*han)(const char *name, const struct stat *stb, int flag, struct FTW *s), int nopenfd, int flags)
-+{
-+      return 0;
-+}
-+#endif /* HAVE_FTW */
-+#endif /* HAVE_NFTW */
-+
-+/*
-+ * Find a block device with the right major/minor number.
-+ * If we find multiple names, choose the shortest.
-+ * If we find a non-standard name, it is probably there
-+ * deliberately so prefer it over a standard name.
-+ * This applies only to names for MD devices.
-+ */
-+char *map_dev(int major, int minor, int create)
-+{
-+      struct devmap *p;
-+      char *std = NULL, *nonstd=NULL;
-+      int did_check = 0;
-+
-+      if (major == 0 && minor == 0)
-+                      return NULL;
-+
-+ retry:
-+      if (!devlist_ready) {
-+              char *dev = "/dev";
-+              struct stat stb;
-+              while(devlist) {
-+                      struct devmap *d = devlist;
-+                      devlist = d->next;
-+                      free(d->name);
-+                      free(d);
-+              }
-+              if (lstat(dev, &stb)==0 &&
-+                  S_ISLNK(stb.st_mode))
-+                      dev = "/dev/.";
-+              nftw(dev, add_dev, 10, FTW_PHYS);
-+              devlist_ready=1;
-+              did_check = 1;
-+      }
-+
-+      for (p=devlist; p; p=p->next)
-+              if (p->major == major &&
-+                  p->minor == minor) {
-+                      if (is_standard(p->name, NULL)) {
-+                              if (std == NULL ||
-+                                  strlen(p->name) < strlen(std))
-+                                      std = p->name;
-+                      } else {
-+                              if (nonstd == NULL ||
-+                                  strlen(p->name) < strlen(nonstd))
-+                                      nonstd = p->name;
-+                      }
-+              }
-+      if (!std && !nonstd && !did_check) {
-+              devlist_ready = 0;
-+              goto retry;
-+      }
-+      if (create && !std && !nonstd) {
-+              static char buf[30];
-+              snprintf(buf, sizeof(buf), "%d:%d", major, minor);
-+              nonstd = buf;
-+      }
-+
-+      return nonstd ? nonstd : std;
-+}
-+
-+unsigned long calc_csum(void *super, int bytes)
-+{
-+      unsigned long long newcsum = 0;
-+      int i;
-+      unsigned int csum;
-+      unsigned int *superc = (unsigned int*) super;
-+
-+      for(i=0; i<bytes/4; i++)
-+              newcsum+= superc[i];
-+      csum = (newcsum& 0xffffffff) + (newcsum>>32);
-+#ifdef __alpha__
-+/* The in-kernel checksum calculation is always 16bit on 
-+ * the alpha, though it is 32 bit on i386...
-+ * I wonder what it is elsewhere... (it uses and API in
-+ * a way that it shouldn't).
-+ */
-+      csum = (csum & 0xffff) + (csum >> 16);
-+      csum = (csum & 0xffff) + (csum >> 16);
-+#endif
-+      return csum;
-+}
-+
-+char *human_size(long long bytes)
-+{
-+      static char buf[30];
-+
-+      /* We convert bytes to either centi-M{ega,ibi}bytes or
-+       * centi-G{igi,ibi}bytes, with appropriate rounding,
-+       * and then print 1/100th of those as a decimal.
-+       * We allow upto 2048Megabytes before converting to
-+       * gigabytes, as that shows more precision and isn't
-+       * too large a number.
-+       * Terrabytes are not yet handled.
-+       */
-+
-+      if (bytes < 5000*1024)
-+              buf[0]=0;
-+      else if (bytes < 2*1024LL*1024LL*1024LL) {
-+              long cMiB = (bytes / ( (1LL<<20) / 200LL ) +1) /2;
-+              long cMB  = (bytes / ( 1000000LL / 200LL ) +1) /2;
-+              snprintf(buf, sizeof(buf), " (%ld.%02ld MiB %ld.%02ld MB)",
-+                      cMiB/100 , cMiB % 100,
-+                      cMB/100, cMB % 100);
-+      } else {
-+              long cGiB = (bytes / ( (1LL<<30) / 200LL ) +1) /2;
-+              long cGB  = (bytes / (1000000000LL/200LL ) +1) /2;
-+              snprintf(buf, sizeof(buf), " (%ld.%02ld GiB %ld.%02ld GB)",
-+                      cGiB/100 , cGiB % 100,
-+                      cGB/100, cGB % 100);
-+      }
-+      return buf;
-+}
-+
-+char *human_size_brief(long long bytes)
-+{
-+      static char buf[30];
-+      
-+
-+      if (bytes < 5000*1024)
-+              snprintf(buf, sizeof(buf), "%ld.%02ldKiB",
-+                      (long)(bytes>>10), (long)(((bytes&1023)*100+512)/1024)
-+                      );
-+      else if (bytes < 2*1024LL*1024LL*1024LL)
-+              snprintf(buf, sizeof(buf), "%ld.%02ldMiB",
-+                      (long)(bytes>>20),
-+                      (long)((bytes&0xfffff)+0x100000/200)/(0x100000/100)
-+                      );
-+      else
-+              snprintf(buf, sizeof(buf), "%ld.%02ldGiB",
-+                      (long)(bytes>>30),
-+                      (long)(((bytes>>10)&0xfffff)+0x100000/200)/(0x100000/100)
-+                      );
-+      return buf;
-+}
-+
-+int get_mdp_major(void)
-+{
-+static int mdp_major = -1;
-+      FILE *fl;
-+      char *w;
-+      int have_block = 0;
-+      int have_devices = 0;
-+      int last_num = -1;
-+
-+      if (mdp_major != -1)
-+              return mdp_major;
-+      fl = fopen("/proc/devices", "r");
-+      if (!fl)
-+              return -1;
-+      while ((w = conf_word(fl, 1))) {
-+              if (have_block && strcmp(w, "devices:")==0)
-+                      have_devices = 1;
-+              have_block =  (strcmp(w, "Block")==0);
-+              if (isdigit(w[0]))
-+                      last_num = atoi(w);
-+              if (have_devices && strcmp(w, "mdp")==0)
-+                      mdp_major = last_num;
-+              free(w);
-+      }
-+      fclose(fl);
-+      return mdp_major;
-+}
-+
-+int dev_open(char *dev, int flags)
-+{
-+      /* like 'open', but if 'dev' matches %d:%d, create a temp
-+       * block device and open that
-+       */
-+      char *e;
-+      int fd = -1;
-+      char devname[32];
-+      int major;
-+      int minor;
-+
-+      if (!dev) return -1;
-+
-+      major = strtoul(dev, &e, 0);
-+      if (e > dev && *e == ':' && e[1] &&
-+          (minor = strtoul(e+1, &e, 0)) >= 0 &&
-+          *e == 0) {
-+              snprintf(devname, sizeof(devname), "/dev/.tmp.md.%d:%d", major, minor);
-+              if (mknod(devname, S_IFBLK|0600, makedev(major, minor))==0) {
-+                      fd = open(devname, flags);
-+                      unlink(devname);
-+              }
-+      } else
-+              fd = open(dev, flags);
-+      return fd;
-+}
-+
-+struct superswitch *superlist[] = { &super0, &super1, NULL };
-+
-+struct supertype *super_by_version(int vers, int minor)
-+{
-+      struct supertype *st = malloc(sizeof(*st));
-+      if (!st) return st;
-+      if (vers == 0) {
-+              st->ss = &super0;
-+              st->max_devs = MD_SB_DISKS;
-+      }
-+
-+      if (vers == 1) {
-+              st->ss = &super1;
-+              st->max_devs = 384;
-+      }
-+      st->minor_version = minor;
-+      return st;
-+}
-+
-+struct supertype *guess_super(int fd)
-+{
-+      /* try each load_super to find the best match,
-+       * and return the best superswitch
-+       */
-+      struct superswitch  *ss;
-+      struct supertype *st;
-+      unsigned long besttime = 0;
-+      int bestsuper = -1;
-+      
-+      void *sbp = NULL;
-+      int i;
-+
-+      st = malloc(sizeof(*st));
-+      memset(st, 0, sizeof(*st));
-+      for (i=0 ; superlist[i]; i++) {
-+              int rv;
-+              ss = superlist[i];
-+              st->ss = NULL;
-+              rv = ss->load_super(st, fd, &sbp, NULL);
-+              if (rv == 0) {
-+                      struct mdinfo info;
-+                      ss->getinfo_super(&info, sbp);
-+                      if (bestsuper == -1 ||
-+                          besttime < info.array.ctime) {
-+                              bestsuper = i;
-+                              besttime = info.array.ctime;
-+                      }
-+                      free(sbp);
-+              }
-+      }
-+      if (bestsuper != -1) {
-+              int rv;
-+              st->ss = NULL;
-+              rv = superlist[bestsuper]->load_super(st, fd, &sbp, NULL);
-+              if (rv == 0) {
-+                      free(sbp);
-+                      return st;
-+              }
-+      }
-+      free(st);
-+      return NULL;
-+}
-+
-+/* Return size of device in bytes */
-+int get_dev_size(int fd, char *dname, unsigned long long *sizep)
-+{
-+      unsigned long long ldsize;
-+#ifdef BLKGETSIZE64
-+      if (ioctl(fd, BLKGETSIZE64, &ldsize) != 0)
-+#endif
-+      {
-+              unsigned long dsize;
-+              if (ioctl(fd, BLKGETSIZE, &dsize) == 0) {
-+                      ldsize = dsize;
-+                      ldsize <<= 9;
-+              } else {
-+                      if (dname)
-+                              fprintf(stderr, Name ": Cannot get size of %s: %s\b",
-+                                      dname, strerror(errno));
-+                      return 0;
-+              }
-+      }
-+      *sizep = ldsize;
-+      return 1;
-+}
---- busybox-1.7.4+gentoo/mdadm/Kbuild  2008-03-01 18:44:05.526713152 -0800
-+++ busybox-1.7.4+gentoo+mdadm/mdadm/Kbuild    2008-03-11 12:19:18.000000000 -0700
-@@ -0,0 +1,9 @@
-+# Makefile for busybox
-+#
-+# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
-+#
-+# Licensed under the GPL v2, see the file LICENSE in this tarball.
-+
-+lib-y:=
-+MDADM-y:= config.o util.o dlink.o sha1.o super0.o super1.o mdexamine.o mdassemble.o
-+lib-$(CONFIG_MDADM)   += mdadm.o $(MDADM-y)
index a02e17bcf0092b1d2f4f4869e12f269b498423e0..6061dc75e52c4151fdb80f2535174d3356f75d17 100644 (file)
@@ -2,10 +2,6 @@
 This patch adds support for the -t option to the 'read' command in ash. It's
 used for prompting for the keymap. It originated with 1.1.3+gentoo or earlier.
 
-1.7.4-mdadm.diff:
-This adds a minimal mdadm implementation to busybox for scanning for and
-activating mdraid arrays. You can blame robbat2 for this one :)
-
 1.7.4-mdstart.diff:
 This adds a 'mdstart' command to busybox, which is used for the activation of
 individual mdraid arrays. It originated with 1.1.3+gentoo or earlier.