diff -urN genkernel-3.4.10.906.orig/defaults/initrd.scripts genkernel-3.4.10.906/defaults/initrd.scripts --- genkernel-3.4.10.906.orig/defaults/initrd.scripts 2009-07-20 00:10:44.000000000 +0200 +++ genkernel-3.4.10.906/defaults/initrd.scripts 2009-08-09 15:54:34.877551032 +0200 @@ -571,9 +571,10 @@ then if [ ! -e '/etc/mdadm.conf' ] then - /sbin/mdadm --examine > /etc/mdadm.conf + echo "DEVICE /dev/sd[a-z]* /dev/hd[a-z]*" >/etc/mdadm.conf + /sbin/mdadm --examine --scan >>/etc/mdadm.conf fi - /sbin/mdadm --assemble + /sbin/mdadm -A --scan fi if [ "${USE_DMRAID_NORMAL}" = '1' ] diff -urN genkernel-3.4.10.906.orig/gen_compile.sh genkernel-3.4.10.906/gen_compile.sh --- genkernel-3.4.10.906.orig/gen_compile.sh 2009-08-05 15:19:47.000000000 +0200 +++ genkernel-3.4.10.906/gen_compile.sh 2009-08-09 16:30:35.248300732 +0200 @@ -444,6 +444,39 @@ fi } +compile_mdadm() { + if [ ! -f "${MDADM_BINCACHE}" ] + then + [ -f "${MDADM_SRCTAR}" ] || + gen_die "Could not find MDADM source tarball: ${MDADM_SRCTAR}! Please place it there, or place another version, changing /etc/genkernel.conf as necessary!" + cd "${TEMP}" + rm -rf ${MDADM_DIR} > /dev/null + /bin/tar -jxpf ${MDADM_SRCTAR} || + gen_die 'Could not extract MDADM source tarball!' + [ -d "${MDADM_DIR}" ] || + gen_die 'MDADM directory ${MDADM_DIR} is invalid!' + + cd "${MDADM_DIR}" + print_info 1 'mdadm: >> Compiling...' + LDFLAGS="-static" \ + CFLAGS="-Os" \ + CXFLAGS="${CFLAGS}" \ + compile_generic 'mdadm' utils + + mkdir -p "${TEMP}/mdadm/sbin" + install -m 0755 -s mdadm "${TEMP}/mdadm/sbin/mdadm" + print_info 1 ' >> Copying to bincache...' + cd "${TEMP}/mdadm" + strip "sbin/mdadm" || + gen_die 'Could not strip mdadm!' + /bin/tar -cjf "${MDADM_BINCACHE}" sbin/mdadm || + gen_die 'Could not create binary cache' + + cd "${TEMP}" + rm -rf "${MDADM_DIR}" mdadm + fi +} + compile_dmraid() { compile_device_mapper if [ ! -f "${DMRAID_BINCACHE}" ] diff -urN genkernel-3.4.10.906.orig/gen_determineargs.sh genkernel-3.4.10.906/gen_determineargs.sh --- genkernel-3.4.10.906.orig/gen_determineargs.sh 2009-08-05 15:19:47.000000000 +0200 +++ genkernel-3.4.10.906/gen_determineargs.sh 2009-08-09 16:30:25.606550699 +0200 @@ -127,6 +127,7 @@ BUSYBOX_BINCACHE=`cache_replace "${BUSYBOX_BINCACHE}"` DEVICE_MAPPER_BINCACHE=`cache_replace "${DEVICE_MAPPER_BINCACHE}"` LVM_BINCACHE=`cache_replace "${LVM_BINCACHE}"` + MDADM_BINCACHE=`cache_replace "${MDADM_BINCACHE}"` DMRAID_BINCACHE=`cache_replace "${DMRAID_BINCACHE}"` BLKID_BINCACHE=`cache_replace "${BLKID_BINCACHE}"` FUSE_BINCACHE=`cache_replace "${FUSE_BINCACHE}"` @@ -137,6 +138,7 @@ BUSYBOX_BINCACHE=`arch_replace "${BUSYBOX_BINCACHE}"` DEVICE_MAPPER_BINCACHE=`arch_replace "${DEVICE_MAPPER_BINCACHE}"` LVM_BINCACHE=`arch_replace "${LVM_BINCACHE}"` + MDADM_BINCACHE=`arch_replace "${MDADM_BINCACHE}"` DMRAID_BINCACHE=`arch_replace "${DMRAID_BINCACHE}"` BLKID_BINCACHE=`arch_replace "${BLKID_BINCACHE}"` FUSE_BINCACHE=`arch_replace "${FUSE_BINCACHE}"` diff -urN genkernel-3.4.10.906.orig/gen_initramfs.sh genkernel-3.4.10.906/gen_initramfs.sh --- genkernel-3.4.10.906.orig/gen_initramfs.sh 2009-08-05 15:19:47.000000000 +0200 +++ genkernel-3.4.10.906/gen_initramfs.sh 2009-08-09 15:39:31.744300661 +0200 @@ -294,10 +294,22 @@ fi cd ${TEMP} mkdir -p "${TEMP}/initramfs-mdadm-temp/etc/" + mkdir -p "${TEMP}/initramfs-mdadm-temp/sbin/" if [ "${MDADM}" -eq '1' ] then cp -a /etc/mdadm.conf "${TEMP}/initramfs-mdadm-temp/etc" \ || gen_die "Could not copy mdadm.conf!" + if [ -e '/sbin/mdadm' ] && LC_ALL="C" ldd /sbin/mdadm|grep -q 'not a dynamic executable' + then + print_info 1 ' MDADM: Adding support (using local static binaries)...' + cp /sbin/mdadm "${TEMP}/initramfs-mdadm-temp/sbin/mdadm" || + gen_die 'Could not copy over mdadm!' + else + print_info 1 ' MDADM: Adding support (compiling binaries)...' + compile_mdadm + /bin/tar -jxpf "${MDADM_BINCACHE}" -C "${TEMP}/initramfs-mdadm-temp" || + gen_die "Could not extract mdadm binary cache!"; + fi fi cd "${TEMP}/initramfs-mdadm-temp/" find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}" diff -urN genkernel-3.4.10.906.orig/genkernel.conf genkernel-3.4.10.906/genkernel.conf --- genkernel-3.4.10.906.orig/genkernel.conf 2009-08-05 15:19:47.000000000 +0200 +++ genkernel-3.4.10.906/genkernel.conf 2009-08-09 16:05:29.540355375 +0200 @@ -159,6 +159,11 @@ LVM_SRCTAR="${DISTDIR}/LVM2.${LVM_VER}.tgz" LVM_BINCACHE="%%CACHE%%/LVM2.${LVM_VER}-%%ARCH%%.tar.bz2" +MDADM_VER="VERSION_MDADM" +MDADM_DIR="mdadm-${MDADM_VER}" +MDADM_SRCTAR="${DISTDIR}/mdadm-${MDADM_VER}.tar.bz2" +MDADM_BINCACHE="%%CACHE%%/mdadm-${MDADM_VER}-%%ARCH%%.tar.bz2" + DMRAID_VER="VERSION_DMRAID" DMRAID_DIR="dmraid/${DMRAID_VER}" DMRAID_SRCTAR="${DISTDIR}/dmraid-${DMRAID_VER}.tar.bz2" diff -urN genkernel-3.4.10.906.orig/patches/busybox/1.7.4/1.7.4-mdadm.diff genkernel-3.4.10.906/patches/busybox/1.7.4/1.7.4-mdadm.diff --- genkernel-3.4.10.906.orig/patches/busybox/1.7.4/1.7.4-mdadm.diff 2008-07-29 03:17:11.000000000 +0200 +++ genkernel-3.4.10.906/patches/busybox/1.7.4/1.7.4-mdadm.diff 1970-01-01 01:00:00.000000000 +0100 @@ -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 - -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 -+ * -+ * -+ * 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: -+ * 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 -+#include -+#include -+#include -+#include -+#include -+ -+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; idevname = 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 -+#include -+#include -+#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 -+ -+# include -+#if HAVE_STDINT_H || _LIBC -+# include -+#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 -+ */ -+#include -+ -+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 -+ * -+ * -+ * 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: -+ * Paper: Neil Brown -+ * School of Computer Science and Engineering -+ * The University of New South Wales -+ * Sydney, 2052 -+ * Australia -+ */ -+ -+#include -+#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 -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#ifdef __dietlibc__ -+#include -+/* dietlibc has deprecated random and srandom!! */ -+#define random rand -+#define srandom srand -+#endif -+ -+ -+#include -+/*#include */ -+#include -+#include -+#include -+#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 -+/* Redhat don't like to #include , and -+ * some time include isn't enough, -+ * and there is no standard conversion function so... */ -+/* And dietlibc doesn't think byteswap is ok, so.. */ -+/* #include */ -+#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 -+# 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 -+#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 -+ * -+ * -+ * 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: -+ * Paper: Neil Brown -+ * School of Computer Science and Engineering -+ * The University of New South Wales -+ * Sydney, 2052 -+ * Australia -+ */ -+ -+#include "mdadm.h" -+#include -+ -+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<= -+ 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=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= 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 && iss->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; iss->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 -+ * -+ * -+ * 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: -+ * 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 -- Expansion function fix -+*/ -+ -+#ifdef HAVE_CONFIG_H -+# include -+#endif -+ -+#include "sha1.h" -+ -+#include -+#include -+ -+#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 -+# 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 -+ * -+ * -+ * 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: -+ * 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<disks[i].raid_disk < info->array.raid_disks) && -+ (sb->disks[i].state & (1<disks[i].state & (1<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<nr_disks++; -+ if (state & (1<active_disks++; -+ if (state & (1<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<disks[d].state & ~(1<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<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<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<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<magic) != BITMAP_MAGIC || -+ memcmp(bsb->uuid, uuid, 16) != 0) -+ goto no_bitmap; -+ return 0; -+ -+ no_bitmap: -+ super->state &= ~(1<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 -+ * -+ * -+ * 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: -+ * 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 -+ * -+ * -+ * 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: -+ * 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 -+#include -+ -+/* -+ * 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 :. 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>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 -+# -+# 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)