aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Robbins <drobbins@funtoo.org>2011-01-20 10:40:42 -0700
committerDaniel Robbins <drobbins@funtoo.org>2011-01-20 10:40:42 -0700
commitd67d8c30bd73671ff2269cf1857a91cff8f99131 (patch)
treea580fa68b8af8a8eab8e8be694fa0e3a6f9be691
parentuse a default kernel make, undoing previous tweak (diff)
parentBump version to 3.4.11.1 (diff)
downloadgenkernel-3.4.11.1-funtoo.tar.gz
genkernel-3.4.11.1-funtoo.tar.bz2
genkernel-3.4.11.1-funtoo.zip
gentoo upstream mergev3.4.11.1-funtoo
-rw-r--r--.gitignore2
-rw-r--r--ChangeLog145
-rw-r--r--HACKING9
-rw-r--r--Makefile27
-rw-r--r--arch/alpha/kernel-config10
-rw-r--r--arch/alpha/modules_load2
-rw-r--r--arch/arm/modules_load2
-rw-r--r--arch/ia64/kernel-config42
-rw-r--r--arch/ia64/modules_load2
-rw-r--r--arch/mips/modules_load2
-rw-r--r--arch/parisc/modules_load2
-rw-r--r--arch/parisc64/modules_load2
-rw-r--r--arch/ppc/kernel-config42
-rw-r--r--arch/ppc/modules_load2
-rw-r--r--arch/ppc64/modules_load2
-rw-r--r--arch/sparc/modules_load2
-rw-r--r--arch/sparc64/kernel-config43
-rw-r--r--arch/sparc64/modules_load2
-rw-r--r--arch/um/modules_load2
-rw-r--r--arch/x86/kernel-config43
-rw-r--r--arch/x86/modules_load2
-rw-r--r--arch/x86_64/kernel-config45
-rw-r--r--arch/x86_64/modules_load2
-rwxr-xr-xdefaults/initrd.defaults2
-rwxr-xr-xdefaults/initrd.scripts149
-rw-r--r--defaults/kernel-config43
-rwxr-xr-xdefaults/linuxrc62
-rwxr-xr-xdefaults/modprobe2
-rw-r--r--defaults/modules_load2
-rw-r--r--doc/asciidoc.conf3
-rw-r--r--doc/genkernel.8.txt478
-rwxr-xr-xgen_bootloader.sh2
-rwxr-xr-xgen_cmdline.sh11
-rwxr-xr-xgen_compile.sh77
-rwxr-xr-xgen_configkernel.sh34
-rwxr-xr-xgen_determineargs.sh9
-rwxr-xr-xgen_funcs.sh46
-rwxr-xr-xgen_initramfs.sh97
-rwxr-xr-xgen_package.sh2
-rwxr-xr-xgenkernel49
-rw-r--r--genkernel.8329
-rw-r--r--genkernel.conf14
-rw-r--r--maintenance/docmatcher.py281
-rw-r--r--patches/busybox/1.18.1/1.18.1-mdadm.diff5874
-rw-r--r--patches/busybox/1.18.1/1.18.1-mdstart.diff122
-rw-r--r--patches/busybox/1.18.1/1.18.1-openvt.diff19
-rw-r--r--patches/busybox/1.18.1/README16
-rw-r--r--patches/busybox/1.18.1/busybox-1.7.4-signal-hack.patch28
-rw-r--r--patches/busybox/1.7.4/1.7.4-make-3.82.diff42
-rw-r--r--patches/lvm/2.02.28/filter-sysfs-inc-sys-stat.patch11
-rw-r--r--patches/lvm/2.02.28/no-export-dynamic.patch22
-rw-r--r--patches/lvm/2.02.74/lvm2-2.02.72-no-export-dynamic.patch37
52 files changed, 7771 insertions, 526 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..643cdcc
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+/genkernel.8
+
diff --git a/ChangeLog b/ChangeLog
index 756be77..d27bb0b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,8 +1,150 @@
# ChangeLog for genkernel
-# Copyright 1999-2009 Gentoo Foundation; 2008-2009 Various authors (see AUTHORS)
+# Copyright:
+# - 2003-2008 Gentoo Foundation
+# - 2008-2011 Various authors (see AUTHORS)
# Distributed under the GPL v2
# $Id$
+ 20 Jan 2011; Sebastian Pipping <sping@gentoo.org> genkernel:
+ Bump version to 3.4.11.1
+
+ 20 Jan 2011; Sebastian Pipping <sping@gentoo.org> gen_configkernel.sh:
+ Move application of kernel config after "make mrproper" as that deletes
+ .config (whereas "make clean" does not) (bug #351906)
+
+ Special thanks:
+ - Xake
+
+ 20 Jan 2011; Sebastian Pipping <sping@gentoo.org>
+ patches/busybox/1.18.1/1.18.1-mdstart.diff:
+ busybox 1.18.1: Return of mdstart as an applet (regression) (bug #351909)
+
+ 16 Jan 2011; Sebastian Pipping <sping@gentoo.org> genkernel:
+ Bump version to 3.4.11
+
+ 16 Jan 2011; Sebastian Pipping <sping@gentoo.org> defaults/initrd.scripts:
+ Do not sleep after vgscan (bug #351047)
+
+ 16 Jan 2011; Sebastian Pipping <sping@gentoo.org> ChangeLog:
+ Changes:
+ - Fix compilation of LVM 2.02.74 (and 2.02.28) (bug #255196, bug #267383)
+ - Add minimal btrfs support (bug #303529)
+ - Add support for UUID to crypt_root (bug #315467)
+ - Run "make firmware_install" if CONFIG_FIRMWARE_IN_KERNEL != y (bug #244651)
+ - Port busybox patches from 1.7.4 to 1.18.1 (bug #331971)
+ - Handle missing kernel .config better (bug #271528)
+ - Improve slowusb handling (bug #323317)
+ - Add GnuPG 1.x support (bug #217959)
+ - Check return codes of cpio (bug #246370)
+ - Update e2fsprogs/blkid to 1.41.14 (bug #291822)
+ - Create /bin/vg* symlinks when called as /linuxrc, too (bug #307855)
+ - Pick first device when several devices are matching real_root (bug #303531)
+ - Fix warning "cannot remove `/var/cache/genkernel/src'" (bug #347213)
+ - Allow configuring the list of busybox applets (bug #326593)
+ - Fix arithmetic bug in defaults/initrd.scripts (bug #339789)
+
+ Special thanks:
+ - Amadeusz Zolnowski (LVM update)
+ - Christian Giessner (UUID crypt_root)
+ - dacook (GnuPG 1.x support)
+ - Denis Kaganovich (Busybox patch porting)
+ - devsk (Multi-device patch)
+ - Fabio Erculiani (Slowusb fixes)
+ - Kai Dietrich (Symlink analysis)
+ - Kolbjørn Barmen (Arithmetic fix)
+
+ 13 Dec 2010; Sebastian Pipping <sping@gentoo.org> genkernel:
+ Bump version to 3.4.10.908
+
+ 13 Dec 2010; <sping@gentoo.org> doc/genkernel.8.txt, gen_cmdline.sh:
+ docs: Document --genzimage
+
+ 13 Dec 2010; <sping@gentoo.org> gen_cmdline.sh:
+ Fix a reference to --nomenuconfig into --no-menuconfig
+
+ 13 Dec 2010; <sping@gentoo.org> doc/genkernel.8.txt:
+ docs: Update man page from output of --help
+
+ 13 Dec 2010; <sping@gentoo.org> doc/genkernel.8.txt:
+ docs: Document keymap= and dokeymap (bug #346017)
+
+ 6 Dec 2010; <sping@gentoo.org> genkernel.conf:
+ .conf: Document LUKS variable (bug #346015)
+
+ 6 Dec 2010; <sping@gentoo.org> doc/genkernel.8.txt:
+ docs: Mention both "initramfs" and "ramdisk" as available actions
+ (bug #251702)
+
+ 6 Dec 2010; <sping@gentoo.org> genkernel.8:
+ man page: Propagate rename of --no-initrdmodules to --no-ramdisk-modules
+
+ 29 Nov 2010; <sping@gentoo.org> ChangeLog:
+ Add patch allowing compilation of busybox 1.7.4 with make 3.82 (bug #341943)
+
+ 20 Feb 2010; Andrew Gaffney <agaffney@gentoo.org> defaults/initrd.scripts:
+ Apply patches from Gentoo bug #268468
+
+ 19 Jan 2010; Andrew Gaffney <agaffney@gentoo.org> genkernel:
+ Only call set_bootloader is CMD_NOINSTALL is not set for Gentoo bug
+ #301454
+
+ 27 Dec 2009; Andrew Gaffney <agaffney@gentoo.org> arch/alpha/modules_load,
+ arch/arm/modules_load, arch/ia64/kernel-config, arch/ia64/modules_load,
+ arch/mips/modules_load, arch/parisc/modules_load,
+ arch/parisc64/modules_load, arch/ppc/kernel-config, arch/ppc/modules_load,
+ arch/ppc64/modules_load, arch/sparc/modules_load,
+ arch/sparc64/kernel-config, arch/sparc64/modules_load,
+ arch/um/modules_load, arch/x86/kernel-config, arch/x86/modules_load,
+ arch/x86_64/kernel-config, arch/x86_64/modules_load,
+ defaults/kernel-config:
+ Add USB HID modules to modules_load and default kernel-config (for Gentoo
+ bug #270983)
+
+ 27 Dec 2009; Andrew Gaffney <agaffney@gentoo.org>
+ arch/alpha/kernel-config, arch/alpha/modules_load, arch/arm/modules_load,
+ arch/ia64/kernel-config, arch/ia64/modules_load, arch/mips/modules_load,
+ arch/parisc/modules_load, arch/parisc64/modules_load,
+ arch/ppc/kernel-config, arch/ppc/modules_load, arch/ppc64/modules_load,
+ arch/sparc/modules_load, arch/sparc64/kernel-config,
+ arch/sparc64/modules_load, arch/um/modules_load, arch/x86/kernel-config,
+ arch/x86/modules_load, arch/x86_64/kernel-config,
+ arch/x86_64/modules_load, defaults/kernel-config, defaults/modules_load:
+ Enable ext4 by default everywhere (for Gentoo bug #268818)
+
+ 27 Dec 2009; Andrew Gaffney <agaffney@gentoo.org> defaults/initrd.scripts,
+ defaults/linuxrc:
+ Add support for isoboot= option (for Gentoo bug #294268)
+
+ 26 Dec 2009; Andrew Gaffney <agaffney@gentoo.org>
+ defaults/initrd.defaults, defaults/initrd.scripts:
+ Properly apply NFS mount options for Gentoo bug #262915
+
+ 26 Dec 2009; Andrew Gaffney <agaffney@gentoo.org>
+ arch/alpha/kernel-config, arch/ia64/kernel-config, arch/ppc/kernel-config,
+ arch/x86_64/kernel-config:
+ Enable CONFIG_SCSI_MULTI_LUN option for Gentoo bug #261122
+
+ 26 Dec 2009; Andrew Gaffney <agaffney@gentoo.org> defaults/initrd.scripts:
+ Apply patch to make sure loop cache directory exists for Gentoo bug
+ #297814
+
+ 17 Dec 2009; Robin H. Johnson <robbat2@gentoo.org> HACKING:
+ Document how to roll a release for the next time.
+
+ 17 Dec 2009; Robin H. Johnson <robbat2@gentoo.org> genkernel:
+ Tag 3.4.10.907 release.
+
+ 06 Dec 2009; Andrew Gaffney <agaffney@gentoo.org> gen_initramfs.sh:
+ use a symlink instead of a hardlink for busybox utils (for Gentoo bug
+ #246370)
+
+ 23 Nov 2009; Andrew Gaffney <agaffney@gentoo.org> defaults/linuxrc:
+ Fix typo for Gentoo bug #294138
+
+ 16 Nov 2009; Andrew Gaffney <agaffney@gentoo.org> gen_initramfs.sh:
+ Make sure to change back to existant directory before removing the current
+ directory for Gentoo bug #291794
+
15 Oct 2009; <craig@haquarter.de> Changelog:
added iSCSI support
@@ -178,6 +320,7 @@
23 Dec 2008; Andrew Gaffney <agaffney@gentoo.org> gen_cmdline.sh:
Allow old 'initramfs' option instead of 'ramdisk' for compatability
+ (bug #251702)
17 Dec 2008; Andrew Gaffney <agaffney@gentoo.org> defaults/linuxrc:
Remove the use of 'env -i' when calling switch_root due to Gentoo bug
diff --git a/HACKING b/HACKING
index 02081d3..b379bf4 100644
--- a/HACKING
+++ b/HACKING
@@ -11,3 +11,12 @@ Phases:
- source global scripts
-
+Rolling a release:
+- Bump the version in the main genkernel file.
+- echangelog commit the bump
+- git tag -a -m "Tag release v${PV}" v${PV}
+- git push ${REMOTE} master --tags
+- make dist
+- upload genkernel-${PV}.tar.bz2 to the hosting:
+ scp genkernel-${PV}.tar.bz2 ${USER}@dev.gentoo.org:/space/distfiles-local/
+- check open bugs with keyword "InSVN" for closability
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..74c5bb9
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,27 @@
+PACKAGE_VERSION = `/bin/fgrep GK_V= genkernel | sed "s/.*GK_V='\([^']\+\)'/\1/"`
+distdir = genkernel-$(PACKAGE_VERSION)
+
+# Add off-Git/generated files here that need to be shipped with releases
+EXTRA_DIST = genkernel.8
+
+genkernel.8: doc/genkernel.8.txt doc/asciidoc.conf Makefile
+ a2x --conf-file=doc/asciidoc.conf --attribute="genkernelversion=$(PACKAGE_VERSION)" \
+ --format=manpage -D . "$<"
+
+clean:
+ rm -f genkernel.8
+
+check-git-repository:
+ git diff --quiet || { echo 'STOP, you have uncommitted changes in the working directory' ; false ; }
+ git diff --cached --quiet || { echo 'STOP, you have uncommitted changes in the index' ; false ; }
+
+dist: check-git-repository genkernel.8
+ rm -Rf "$(distdir)" "$(distdir)".tar "$(distdir)".tar.bz2
+ mkdir "$(distdir)"
+ git ls-files -z | xargs -0 cp --no-dereference --parents --target-directory="$(distdir)" \
+ $(EXTRA_DIST)
+ tar cf "$(distdir)".tar "$(distdir)"
+ bzip2 -9v "$(distdir)".tar
+ rm -Rf "$(distdir)"
+
+.PHONY: clean check-git-repository dist
diff --git a/arch/alpha/kernel-config b/arch/alpha/kernel-config
index b4eb04c..812fe8f 100644
--- a/arch/alpha/kernel-config
+++ b/arch/alpha/kernel-config
@@ -400,7 +400,7 @@ CONFIG_CHR_DEV_SG=y
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
-# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_MULTI_LUN=y
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
# CONFIG_SCSI_SCAN_ASYNC is not set
@@ -976,10 +976,10 @@ CONFIG_EXT3_FS=m
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
-CONFIG_EXT4DEV_FS=m
-CONFIG_EXT4DEV_FS_XATTR=y
-CONFIG_EXT4DEV_FS_POSIX_ACL=y
-CONFIG_EXT4DEV_FS_SECURITY=y
+CONFIG_EXT4_FS=m
+CONFIG_EXT4_FS_XATTR=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
CONFIG_JBD=m
CONFIG_JBD2=m
CONFIG_FS_MBCACHE=y
diff --git a/arch/alpha/modules_load b/arch/alpha/modules_load
index 85bf3d0..63ef20f 100644
--- a/arch/alpha/modules_load
+++ b/arch/alpha/modules_load
@@ -22,7 +22,7 @@ MODULES_ISCSI="scsi_transport_iscsi libiscsi iscsi_tcp"
# Hardware (Pluggable)
MODULES_FIREWIRE="ieee1394 ohci1394 sbp2"
MODULES_PCMCIA="pcmcia pcmcia_core yenta_socket pd6729 i82092 i82365 tcic ds ide-cs firmware_class"
-MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd"
+MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd hid-a4tech hid-apple hid-belkin hid-cherry hid-chicony hid-cypress hid-dummy hid-ezkey hid-gyration hid-logitech hid-microsoft hid-monterey hid-petalynx hid-pl hid-samsung hid-sony hid-sunplus"
# Filesystems
MODULES_FS="ext2 ext3 ext4 reiserfs jfs nfs xfs fuse"
diff --git a/arch/arm/modules_load b/arch/arm/modules_load
index 9a44618..b2cf1d1 100644
--- a/arch/arm/modules_load
+++ b/arch/arm/modules_load
@@ -19,7 +19,7 @@ MODULES_NET="e1000 tg3"
# Hardware (Pluggable)
MODULES_FIREWIRE="ieee1394 ohci1394 sbp2"
MODULES_PCMCIA="pcmcia pcmcia_core yenta_socket pd6729 i82092 i82365 tcic ds ide-cs firmware_class"
-MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd"
+MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd hid-a4tech hid-apple hid-belkin hid-cherry hid-chicony hid-cypress hid-dummy hid-ezkey hid-gyration hid-logitech hid-microsoft hid-monterey hid-petalynx hid-pl hid-samsung hid-sony hid-sunplus"
# Filesystems
MODULES_FS="ext2 ext3 ext4 reiserfs jfs nfs xfs fuse"
diff --git a/arch/ia64/kernel-config b/arch/ia64/kernel-config
index 202eb72..8fbc90c 100644
--- a/arch/ia64/kernel-config
+++ b/arch/ia64/kernel-config
@@ -476,7 +476,7 @@ CONFIG_CHR_DEV_SG=y
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
-# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_MULTI_LUN=y
CONFIG_SCSI_CONSTANTS=y
CONFIG_SCSI_LOGGING=y
# CONFIG_SCSI_SCAN_ASYNC is not set
@@ -867,6 +867,41 @@ CONFIG_USB_HID=y
CONFIG_USB_HIDDEV=y
#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=m
+CONFIG_HID_APPLE=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_BRIGHT=m
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+CONFIG_HID_CYPRESS=m
+CONFIG_HID_DELL=m
+CONFIG_HID_EZKEY=m
+CONFIG_HID_GYRATION=m
+CONFIG_HID_LOGITECH=m
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+CONFIG_HID_PANTHERLORD=m
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SONY=m
+CONFIG_HID_SUNPLUS=m
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
# USB support
#
CONFIG_USB_ARCH_HAS_HCD=y
@@ -1032,7 +1067,10 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
# CONFIG_EXT3_FS_SECURITY is not set
-# CONFIG_EXT4DEV_FS is not set
+CONFIG_EXT4_FS=m
+CONFIG_EXT4_FS_XATTR=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
CONFIG_JBD=y
CONFIG_JBD_DEBUG=y
CONFIG_FS_MBCACHE=y
diff --git a/arch/ia64/modules_load b/arch/ia64/modules_load
index 33dbd12..2612197 100644
--- a/arch/ia64/modules_load
+++ b/arch/ia64/modules_load
@@ -22,7 +22,7 @@ MODULES_ISCSI="scsi_transport_iscsi libiscsi iscsi_tcp"
# Hardware (Pluggable)
MODULES_FIREWIRE="ieee1394 ohci1394 sbp2"
MODULES_PCMCIA="pcmcia pcmcia_core yenta_socket pd6729 i82092 i82365 tcic ds ide-cs firmware_class"
-MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd"
+MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd hid-a4tech hid-apple hid-belkin hid-cherry hid-chicony hid-cypress hid-dummy hid-ezkey hid-gyration hid-logitech hid-microsoft hid-monterey hid-petalynx hid-pl hid-samsung hid-sony hid-sunplus"
# Filesystems
MODULES_FS="ext2 ext3 ext4 reiserfs jfs nfs xfs fuse"
diff --git a/arch/mips/modules_load b/arch/mips/modules_load
index 85bf3d0..63ef20f 100644
--- a/arch/mips/modules_load
+++ b/arch/mips/modules_load
@@ -22,7 +22,7 @@ MODULES_ISCSI="scsi_transport_iscsi libiscsi iscsi_tcp"
# Hardware (Pluggable)
MODULES_FIREWIRE="ieee1394 ohci1394 sbp2"
MODULES_PCMCIA="pcmcia pcmcia_core yenta_socket pd6729 i82092 i82365 tcic ds ide-cs firmware_class"
-MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd"
+MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd hid-a4tech hid-apple hid-belkin hid-cherry hid-chicony hid-cypress hid-dummy hid-ezkey hid-gyration hid-logitech hid-microsoft hid-monterey hid-petalynx hid-pl hid-samsung hid-sony hid-sunplus"
# Filesystems
MODULES_FS="ext2 ext3 ext4 reiserfs jfs nfs xfs fuse"
diff --git a/arch/parisc/modules_load b/arch/parisc/modules_load
index 85bf3d0..63ef20f 100644
--- a/arch/parisc/modules_load
+++ b/arch/parisc/modules_load
@@ -22,7 +22,7 @@ MODULES_ISCSI="scsi_transport_iscsi libiscsi iscsi_tcp"
# Hardware (Pluggable)
MODULES_FIREWIRE="ieee1394 ohci1394 sbp2"
MODULES_PCMCIA="pcmcia pcmcia_core yenta_socket pd6729 i82092 i82365 tcic ds ide-cs firmware_class"
-MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd"
+MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd hid-a4tech hid-apple hid-belkin hid-cherry hid-chicony hid-cypress hid-dummy hid-ezkey hid-gyration hid-logitech hid-microsoft hid-monterey hid-petalynx hid-pl hid-samsung hid-sony hid-sunplus"
# Filesystems
MODULES_FS="ext2 ext3 ext4 reiserfs jfs nfs xfs fuse"
diff --git a/arch/parisc64/modules_load b/arch/parisc64/modules_load
index 33dbd12..2612197 100644
--- a/arch/parisc64/modules_load
+++ b/arch/parisc64/modules_load
@@ -22,7 +22,7 @@ MODULES_ISCSI="scsi_transport_iscsi libiscsi iscsi_tcp"
# Hardware (Pluggable)
MODULES_FIREWIRE="ieee1394 ohci1394 sbp2"
MODULES_PCMCIA="pcmcia pcmcia_core yenta_socket pd6729 i82092 i82365 tcic ds ide-cs firmware_class"
-MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd"
+MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd hid-a4tech hid-apple hid-belkin hid-cherry hid-chicony hid-cypress hid-dummy hid-ezkey hid-gyration hid-logitech hid-microsoft hid-monterey hid-petalynx hid-pl hid-samsung hid-sony hid-sunplus"
# Filesystems
MODULES_FS="ext2 ext3 ext4 reiserfs jfs nfs xfs fuse"
diff --git a/arch/ppc/kernel-config b/arch/ppc/kernel-config
index 9cf960d..c62386d 100644
--- a/arch/ppc/kernel-config
+++ b/arch/ppc/kernel-config
@@ -651,7 +651,7 @@ CONFIG_CHR_DEV_SCH=m
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
-# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_MULTI_LUN=y
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
# CONFIG_SCSI_SCAN_ASYNC is not set
@@ -1837,6 +1837,41 @@ CONFIG_USB=y
# CONFIG_USB_DEBUG is not set
#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=m
+CONFIG_HID_APPLE=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_BRIGHT=m
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+CONFIG_HID_CYPRESS=m
+CONFIG_HID_DELL=m
+CONFIG_HID_EZKEY=m
+CONFIG_HID_GYRATION=m
+CONFIG_HID_LOGITECH=m
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+CONFIG_HID_PANTHERLORD=m
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SONY=m
+CONFIG_HID_SUNPLUS=m
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
# Miscellaneous USB options
#
CONFIG_USB_DEVICEFS=y
@@ -2058,7 +2093,10 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
-# CONFIG_EXT4DEV_FS is not set
+CONFIG_EXT4_FS=m
+CONFIG_EXT4_FS_XATTR=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_FS_MBCACHE=y
diff --git a/arch/ppc/modules_load b/arch/ppc/modules_load
index 85bf3d0..63ef20f 100644
--- a/arch/ppc/modules_load
+++ b/arch/ppc/modules_load
@@ -22,7 +22,7 @@ MODULES_ISCSI="scsi_transport_iscsi libiscsi iscsi_tcp"
# Hardware (Pluggable)
MODULES_FIREWIRE="ieee1394 ohci1394 sbp2"
MODULES_PCMCIA="pcmcia pcmcia_core yenta_socket pd6729 i82092 i82365 tcic ds ide-cs firmware_class"
-MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd"
+MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd hid-a4tech hid-apple hid-belkin hid-cherry hid-chicony hid-cypress hid-dummy hid-ezkey hid-gyration hid-logitech hid-microsoft hid-monterey hid-petalynx hid-pl hid-samsung hid-sony hid-sunplus"
# Filesystems
MODULES_FS="ext2 ext3 ext4 reiserfs jfs nfs xfs fuse"
diff --git a/arch/ppc64/modules_load b/arch/ppc64/modules_load
index 33dbd12..2612197 100644
--- a/arch/ppc64/modules_load
+++ b/arch/ppc64/modules_load
@@ -22,7 +22,7 @@ MODULES_ISCSI="scsi_transport_iscsi libiscsi iscsi_tcp"
# Hardware (Pluggable)
MODULES_FIREWIRE="ieee1394 ohci1394 sbp2"
MODULES_PCMCIA="pcmcia pcmcia_core yenta_socket pd6729 i82092 i82365 tcic ds ide-cs firmware_class"
-MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd"
+MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd hid-a4tech hid-apple hid-belkin hid-cherry hid-chicony hid-cypress hid-dummy hid-ezkey hid-gyration hid-logitech hid-microsoft hid-monterey hid-petalynx hid-pl hid-samsung hid-sony hid-sunplus"
# Filesystems
MODULES_FS="ext2 ext3 ext4 reiserfs jfs nfs xfs fuse"
diff --git a/arch/sparc/modules_load b/arch/sparc/modules_load
index 85bf3d0..63ef20f 100644
--- a/arch/sparc/modules_load
+++ b/arch/sparc/modules_load
@@ -22,7 +22,7 @@ MODULES_ISCSI="scsi_transport_iscsi libiscsi iscsi_tcp"
# Hardware (Pluggable)
MODULES_FIREWIRE="ieee1394 ohci1394 sbp2"
MODULES_PCMCIA="pcmcia pcmcia_core yenta_socket pd6729 i82092 i82365 tcic ds ide-cs firmware_class"
-MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd"
+MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd hid-a4tech hid-apple hid-belkin hid-cherry hid-chicony hid-cypress hid-dummy hid-ezkey hid-gyration hid-logitech hid-microsoft hid-monterey hid-petalynx hid-pl hid-samsung hid-sony hid-sunplus"
# Filesystems
MODULES_FS="ext2 ext3 ext4 reiserfs jfs nfs xfs fuse"
diff --git a/arch/sparc64/kernel-config b/arch/sparc64/kernel-config
index 68d20c1..c4b2359 100644
--- a/arch/sparc64/kernel-config
+++ b/arch/sparc64/kernel-config
@@ -1478,6 +1478,41 @@ CONFIG_USB_HID=m
CONFIG_USB_HIDDEV=y
#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=m
+CONFIG_HID_APPLE=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_BRIGHT=m
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+CONFIG_HID_CYPRESS=m
+CONFIG_HID_DELL=m
+CONFIG_HID_EZKEY=m
+CONFIG_HID_GYRATION=m
+CONFIG_HID_LOGITECH=m
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+CONFIG_HID_PANTHERLORD=m
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SONY=m
+CONFIG_HID_SUNPLUS=m
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
# USB HID Boot Protocol drivers
#
CONFIG_USB_KBD=m
@@ -1740,10 +1775,10 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
-CONFIG_EXT4DEV_FS=m
-CONFIG_EXT4DEV_FS_XATTR=y
-CONFIG_EXT4DEV_FS_POSIX_ACL=y
-CONFIG_EXT4DEV_FS_SECURITY=y
+CONFIG_EXT4_FS=m
+CONFIG_EXT4_FS_XATTR=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_JBD2=m
diff --git a/arch/sparc64/modules_load b/arch/sparc64/modules_load
index 33dbd12..2612197 100644
--- a/arch/sparc64/modules_load
+++ b/arch/sparc64/modules_load
@@ -22,7 +22,7 @@ MODULES_ISCSI="scsi_transport_iscsi libiscsi iscsi_tcp"
# Hardware (Pluggable)
MODULES_FIREWIRE="ieee1394 ohci1394 sbp2"
MODULES_PCMCIA="pcmcia pcmcia_core yenta_socket pd6729 i82092 i82365 tcic ds ide-cs firmware_class"
-MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd"
+MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd hid-a4tech hid-apple hid-belkin hid-cherry hid-chicony hid-cypress hid-dummy hid-ezkey hid-gyration hid-logitech hid-microsoft hid-monterey hid-petalynx hid-pl hid-samsung hid-sony hid-sunplus"
# Filesystems
MODULES_FS="ext2 ext3 ext4 reiserfs jfs nfs xfs fuse"
diff --git a/arch/um/modules_load b/arch/um/modules_load
index 67b280d..55dcc23 100644
--- a/arch/um/modules_load
+++ b/arch/um/modules_load
@@ -22,7 +22,7 @@ MODULES_ISCSI="scsi_transport_iscsi libiscsi iscsi_tcp"
# Hardware (Pluggable)
MODULES_FIREWIRE="ieee1394 ohci1394 sbp2"
MODULES_PCMCIA="pcmcia pcmcia_core yenta_socket pd6729 i82092 i82365 tcic ds ide-cs firmware_class"
-MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd"
+MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd hid-a4tech hid-apple hid-belkin hid-cherry hid-chicony hid-cypress hid-dummy hid-ezkey hid-gyration hid-logitech hid-microsoft hid-monterey hid-petalynx hid-pl hid-samsung hid-sony hid-sunplus"
# Filesystems
MODULES_FS="ext2 ext3 ext4 reiserfs jfs nfs xfs fuse"
diff --git a/arch/x86/kernel-config b/arch/x86/kernel-config
index 12ca2c6..1dbc07e 100644
--- a/arch/x86/kernel-config
+++ b/arch/x86/kernel-config
@@ -2888,6 +2888,41 @@ CONFIG_ZEROPLUS_FF=y
CONFIG_USB_HIDDEV=y
#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=m
+CONFIG_HID_APPLE=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_BRIGHT=m
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+CONFIG_HID_CYPRESS=m
+CONFIG_HID_DELL=m
+CONFIG_HID_EZKEY=m
+CONFIG_HID_GYRATION=m
+CONFIG_HID_LOGITECH=m
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+CONFIG_HID_PANTHERLORD=m
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SONY=m
+CONFIG_HID_SUNPLUS=m
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
# USB HID Boot Protocol drivers
#
# CONFIG_USB_KBD is not set
@@ -3233,10 +3268,10 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
-CONFIG_EXT4DEV_FS=m
-CONFIG_EXT4DEV_FS_XATTR=y
-CONFIG_EXT4DEV_FS_POSIX_ACL=y
-CONFIG_EXT4DEV_FS_SECURITY=y
+CONFIG_EXT4_FS=m
+CONFIG_EXT4_FS_XATTR=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_JBD2=m
diff --git a/arch/x86/modules_load b/arch/x86/modules_load
index b1be781..2d159fb 100644
--- a/arch/x86/modules_load
+++ b/arch/x86/modules_load
@@ -23,7 +23,7 @@ MODULES_ISCSI="scsi_transport_iscsi libiscsi iscsi_tcp"
# Hardware (Pluggable)
MODULES_FIREWIRE="ieee1394 ohci1394 sbp2"
MODULES_PCMCIA="pcmcia pcmcia_core yenta_socket pd6729 i82092 i82365 tcic ds ide-cs firmware_class"
-MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd"
+MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd hid-a4tech hid-apple hid-belkin hid-cherry hid-chicony hid-cypress hid-dummy hid-ezkey hid-gyration hid-logitech hid-microsoft hid-monterey hid-petalynx hid-pl hid-samsung hid-sony hid-sunplus"
# Filesystems
MODULES_FS="ext2 ext3 ext4 reiserfs jfs nfs xfs fuse"
diff --git a/arch/x86_64/kernel-config b/arch/x86_64/kernel-config
index 7656dc9..1260e39 100644
--- a/arch/x86_64/kernel-config
+++ b/arch/x86_64/kernel-config
@@ -976,7 +976,7 @@ CONFIG_CHR_DEV_SCH=m
#
# Some SCSI devices (e.g. CD jukebox) support multiple LUNs
#
-# CONFIG_SCSI_MULTI_LUN is not set
+CONFIG_SCSI_MULTI_LUN=y
# CONFIG_SCSI_CONSTANTS is not set
# CONFIG_SCSI_LOGGING is not set
CONFIG_SCSI_SCAN_ASYNC=y
@@ -2388,6 +2388,41 @@ CONFIG_USB_HIDINPUT_POWERBOOK=y
CONFIG_USB_HIDDEV=y
#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=m
+CONFIG_HID_APPLE=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_BRIGHT=m
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+CONFIG_HID_CYPRESS=m
+CONFIG_HID_DELL=m
+CONFIG_HID_EZKEY=m
+CONFIG_HID_GYRATION=m
+CONFIG_HID_LOGITECH=m
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+CONFIG_HID_PANTHERLORD=m
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SONY=m
+CONFIG_HID_SUNPLUS=m
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
# USB HID Boot Protocol drivers
#
# CONFIG_USB_KBD is not set
@@ -2698,10 +2733,10 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
-CONFIG_EXT4DEV_FS=y
-CONFIG_EXT4DEV_FS_XATTR=y
-CONFIG_EXT4DEV_FS_POSIX_ACL=y
-CONFIG_EXT4DEV_FS_SECURITY=y
+CONFIG_EXT4_FS=y
+CONFIG_EXT4_FS_XATTR=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
CONFIG_JBD=y
CONFIG_JBD2=y
CONFIG_FS_MBCACHE=y
diff --git a/arch/x86_64/modules_load b/arch/x86_64/modules_load
index 73bf530..fe26891 100644
--- a/arch/x86_64/modules_load
+++ b/arch/x86_64/modules_load
@@ -22,7 +22,7 @@ MODULES_ISCSI="scsi_transport_iscsi libiscsi iscsi_tcp"
# Hardware (Pluggable)
MODULES_FIREWIRE="ieee1394 ohci1394 sbp2"
MODULES_PCMCIA="pcmcia pcmcia_core yenta_socket pd6729 i82092 i82365 tcic ds ide-cs firmware_class"
-MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd"
+MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd hid-a4tech hid-apple hid-belkin hid-cherry hid-chicony hid-cypress hid-dummy hid-ezkey hid-gyration hid-logitech hid-microsoft hid-monterey hid-petalynx hid-pl hid-samsung hid-sony hid-sunplus"
# Filesystems
MODULES_FS="ext2 ext3 ext4 reiserfs jfs nfs xfs fuse"
diff --git a/defaults/initrd.defaults b/defaults/initrd.defaults
index db5cb25..14a403f 100755
--- a/defaults/initrd.defaults
+++ b/defaults/initrd.defaults
@@ -75,6 +75,8 @@ CONSOLE='/dev/console'
LOOPS='/livecd.loop /zisofs /livecd.squashfs /image.squashfs /livecd.gcloop'
+DEFAULT_NFSOPTIONS="ro,nolock,rsize=1024,wsize=1024"
+
# Only sections that are in by default or those that
# are not module groups need to be defined here...
HWOPTS='keymap cache modules pata sata scsi usb firewire waitscan slowusb evms lvm dmraid mdadm fs net'
diff --git a/defaults/initrd.scripts b/defaults/initrd.scripts
index 7b63838..b7493aa 100755
--- a/defaults/initrd.scripts
+++ b/defaults/initrd.scripts
@@ -72,8 +72,17 @@ findmediamount() {
if [ "$#" -gt "0" ]
then
-
[ ! -d "${mntdir}" ] && mkdir -p ${mntdir} 2>/dev/null >/dev/null
+ if [ -n "${ISOBOOT}" ]
+ then
+ mntcddir="${mntdir%${media}}iso"
+ if [ ! -f ${mntcddir} ]
+ then
+ mkdir ${mntcddir}
+ fi
+ else
+ mntcddir=${mntdir}
+ fi
for x in $*
do
@@ -104,9 +113,18 @@ findmediamount() {
# else
# mount -r -t auto ${x} ${mntdir} &>/dev/null
# fi
- mount -r -t ${CDROOT_TYPE} ${x} ${mntdir} >/dev/null 2>&1
+ mount -r -t ${CDROOT_TYPE} ${x} ${mntcddir} >/dev/null 2>&1
if [ "$?" = '0' ]
then
+ if [ -n "${ISOBOOT}" ]; then
+ if [ -f ${mntcddir}/${ISOBOOT} ]; then
+ mount -o loop ${mntcddir}/${ISOBOOT} ${mntdir}
+ if [ "$?" = "0" ]; then
+ good_msg "iso mounted on ${mntdir}"
+ fi
+ fi
+ fi
+
# Check for the media
if [ -f "${mntdir}/${recon}" ]
then
@@ -115,7 +133,7 @@ findmediamount() {
good_msg "Media found on ${x}" ${CRYPT_SILENT}
break
else
- umount ${mntdir}
+ umount ${mntcddir}
fi
fi
fi
@@ -175,6 +193,8 @@ cache_cd_contents() {
# z=$(($z + $i)) ; done
# echo $z
good_msg "Copying loop file for caching..."
+ # Verify that the needed directory exists
+ mkdir -p "$(dirname ${NEW_ROOT}/mnt/${LOOP})"
cp -a ${NEW_ROOT}/mnt/cdrom/${LOOP} ${NEW_ROOT}/mnt/${LOOP}
if [ $? -ne 0 ]
then
@@ -192,7 +212,7 @@ cache_cd_contents() {
mount_sysfs() {
mount -t sysfs /sys /sys >/dev/null 2>&1
ret=$?
- [ "$ret" -eq '0' ] || bad_msg "Failed to mount /sys!"
+ [ ${ret} -eq 0 ] || bad_msg "Failed to mount /sys!"
}
aufs_setup_dir() {
@@ -241,10 +261,19 @@ findnfsmount() {
if [ "${NFSROOT}" != '' ]
then
+ NFSOPTIONS=${NFSROOT#*,}
+ NFSROOT=${NFSROOT%%,*}
+ if [ "${NFSOPTIONS}" = "${NFSROOT}" ]
+ then
+ NFSOPTIONS=$DEFAULT_NFSOPTIONS
+ else
+ NFSOPTIONS="${DEFAULT_NFSOPTIONS},${NFSOPTIONS}"
+ fi
+
if [ "${CDROOT}" != '0' ]
then
- good_msg "Attempting to mount NFS CD image on ${NFSROOT}"
- mount -t nfs -o ro,nolock,rsize=1024,wsize=1024 ${NFSROOT} ${NEW_ROOT}/mnt/cdrom
+ good_msg "Attempting to mount NFS CD image on ${NFSROOT} with options ${NFSOPTIONS}"
+ mount -t nfs -o ${NFSOPTIONS} ${NFSROOT} ${NEW_ROOT}/mnt/cdrom
if [ "$?" = '0' ]
then
REAL_ROOT="/dev/nfs"
@@ -252,8 +281,8 @@ findnfsmount() {
bad_msg "NFS Mounting failed. Is the path corrent ?"
fi
else
- good_msg "Attempting to mount NFS root on ${NFSROOT}"
- mount -t nfs -o ro,nolock,rsize=1024,wsize=1024 ${NFSROOT} ${NEW_ROOT}
+ good_msg "Attempting to mount NFS root on ${NFSROOT} with options ${NFSOPTIONS}"
+ mount -t nfs -o ${NFSOPTIONS} ${NFSROOT} ${NEW_ROOT}
if [ "$?" = '0' ]
then
REAL_ROOT="/dev/nfs"
@@ -329,11 +358,16 @@ warn_msg() {
}
crypt_filter() {
- if [ ${CRYPT_SILENT} -eq 1 ]
+ if [ "${CRYPT_SILENT}" = '1' ]
then
eval $1 >/dev/null 2>/dev/null
else
+ splash 'verbose' > /dev/null &
eval $1
+ if [ $? -eq 0 ]
+ then
+ splash set_msg 'Disk unlocked.'
+ fi
fi
}
@@ -383,12 +417,23 @@ setup_hotplug() {
fi
}
-check_slowusb() {
- [ "${DO_slowusb}" ] || \
- for x in /sys/bus/usb/drivers/usb-storage/*
+setup_slowusb() {
+ # slowusb already set?
+ if [ "${DO_slowusb}" = "1" ]
+ then
+ return
+ fi
+
+ local usb_storage_dir="/sys/bus/usb/drivers/usb-storage"
+ if [ ! -d "${usb_storage_dir}" ]
+ then
+ # no automated slowusb required. no usb-storage devices attached.
+ return
+ fi
+ for x in "${usb_storage_dir}"/*
do
- [ -d "${x}" ] && [ "${x}" != "/sys/bus/usb/drivers/usb-storage/module" ] \
- && FORCE_slowusb="1"
+ [ -d "${x}" ] && [ "${x}" != "${usb_storage_dir}/module" ] \
+ && { DO_slowusb="1" ; break ; }
done
}
@@ -396,11 +441,8 @@ start_dev_mgr() {
if [ "${KV_2_6_OR_GREATER}" ]
then
cd /sys
- check_slowusb
good_msg 'Activating mdev'
runmdev
- [ "${DO_slowusb}" ] || \
- [ "${FORCE_slowusb}" ] && sdelay
cd /
fi
}
@@ -479,7 +521,7 @@ setup_keymap() {
[ "${DEVBIND}" = '1' ] && umount /dev
- if [ -e /etc/sysconfig/keyboard -a "${CDROOT}" -eq '1' ]
+ if [ -e /etc/sysconfig/keyboard -a "${CDROOT}" = '1' ]
then
mkdir -p ${NEW_ROOT}/etc/sysconfig/
cp /etc/sysconfig/keyboard ${NEW_ROOT}/etc/sysconfig/keyboard
@@ -491,6 +533,7 @@ chooseKeymap() {
good_msg "Loading keymaps"
if [ -z "${keymap}" ]
then
+ splash 'verbose' > /dev/null &
cat /lib/keymaps/keymapList
read -t 10 -p '<< Load keymap (Enter for default): ' keymap
case ${keymap} in
@@ -544,17 +587,19 @@ chooseKeymap() {
loadkmap < /lib/keymaps/${keymap}.map
# xkeymap=${keymap}
# echo ${keymap} | egrep -e "[0-9]+" >/dev/null 2>&1
-# if [ "$?" -eq '0' ]
+# if [ $? -eq 0 ]
# then
# xkeymap=`tail -n 7 /lib/keymaps/keymapList | grep ${keymap} | sed -r "s/.*\s+${keymap}\s+([a-z-]+).*/\1/g" | egrep -v 1`
# fi
mkdir -p /etc/sysconfig
# echo "XKEYBOARD=${xkeymap}" > /etc/sysconfig/keyboard
echo "XKEYBOARD=${keymap}" > /etc/sysconfig/keyboard
+ splash set_msg "Set keymap to ${keymap}"
elif [ -z "${keymap}" ]
then
echo
good_msg "Keeping default keymap"
+ splash set_msg "Keeping default keymap"
else
bad_msg "Sorry, but keymap ''${keymap}'' is invalid!"
unset keymap
@@ -573,7 +618,7 @@ startVolumes() {
ln -sf /dev/device-mapper /dev/mapper/control
fi
- if [ "${USE_MDADM}" -eq '1' ]
+ if [ "${USE_MDADM}" = '1' ]
then
if [ ! -e '/etc/mdadm.conf' ]
then
@@ -607,7 +652,6 @@ startVolumes() {
good_msg "Scanning for Volume Groups"
/bin/vgscan --ignorelockingfailure --mknodes 2>/dev/null
- sleep 2
good_msg "Activating Volume Groups"
/bin/vgchange -ay --ignorelockingfailure 2>/dev/null
@@ -678,6 +722,9 @@ startiscsi() {
fi
iscsistart -i "${ISCSI_INITIATORNAME}" -t "${ISCSI_TARGET}" -a "${ISCSI_ADDRESS}" ${ADDITIONAL}
+
+ # let iscsid settle - otherwise mounting the iSCSI-disk will fail (very rarely, though)
+ sleep 1
fi
}
@@ -705,6 +752,7 @@ openLUKS() {
[ ! -e /sbin/cryptsetup ] && bad_msg "The ramdisk does not support LUKS" && exit 1
while [ 1 ]
do
+ local gpg_cmd=""
# if crypt_silent=1 and some error occurs, enter shell quietly
if [ \( ${CRYPT_SILENT} -eq 1 \) -a \( \( \( ${DEV_ERROR} -eq 1 \) -o \( ${KEY_ERROR} -eq 1 \) \) -o \( ${KEYDEV_ERROR} -eq 1 \) \) ]
then
@@ -722,9 +770,36 @@ openLUKS() {
whereis "LUKS_KEYDEV" "${LUKS_NAME} key device"
KEYDEV_ERROR=0
else
+ case "${LUKS_DEVICE}" in
+ UUID\=*|LABEL\=*)
+ local REAL_LUKS=""
+ local retval=1
+
+ if [ "${retval}" -ne 0 ]; then
+ REAL_LUKS=`findfs "${LUKS_DEVICE}" 2>/dev/null`
+ retval=$?
+ fi
+
+ if [ "$retval" -ne 0 ]; then
+ REAL_LUKS=`busybox findfs "${LUKS_DEVICE}" 2>/dev/null`
+ retval=$?
+ fi
+
+ if [ "${retval}" -ne 0 ]; then
+ REAL_LUKS=`blkid -l -t "${LUKS_DEVICE}" | cut -d ":" -f 1 2>/dev/null`
+ retval=$?
+ fi
+
+ if [ "${retval}" -eq 0 ] && [ -n "${REAL_LUKS}" ]; then
+ good_msg "Detected device ${REAL_LUKS}"
+ LUKS_DEVICE="${REAL_LUKS}"
+ fi
+ ;;
+ esac
+
setup_md_device ${LUKS_DEVICE}
cryptsetup isLuks ${LUKS_DEVICE}
- if [ ! "$?" -eq '0' ]
+ if [ $? -ne 0 ]
then
bad_msg "The LUKS device ${LUKS_DEVICE} does not contain a LUKS header" ${CRYPT_SILENT}
DEV_ERROR=1
@@ -789,10 +864,17 @@ openLUKS() {
fi
# At this point a candidate key exists (either mounted before or not)
good_msg "${LUKS_KEY} on device ${LUKS_KEYDEV} found" ${CRYPT_SILENT}
- cryptsetup_options="-d ${mntkey}${LUKS_KEY}"
+ if [ $(echo ${LUKS_KEY} | grep -o '.gpg$') = ".gpg" ] && [ -e /sbin/gpg ] ; then
+ [ -e /dev/tty ] && mv /dev/tty /dev/tty.org
+ mknod /dev/tty c 5 1
+ cryptsetup_options="-d -"
+ gpg_cmd="/sbin/gpg --logger-file /dev/null --quiet --decrypt ${mntkey}${LUKS_KEY} |"
+ else
+ cryptsetup_options="-d ${mntkey}${LUKS_KEY}"
+ fi
fi
# At this point, keyfile or not, we're ready!
- crypt_filter "cryptsetup ${cryptsetup_options} luksOpen ${LUKS_DEVICE} ${LUKS_NAME}"
+ crypt_filter "${gpg_cmd}cryptsetup ${cryptsetup_options} luksOpen ${LUKS_DEVICE} ${LUKS_NAME}"
if [ $? -eq 0 ]
then
good_msg "LUKS device ${LUKS_DEVICE} opened" ${CRYPT_SILENT}
@@ -843,15 +925,15 @@ startLUKS() {
}
sdelay() {
- # Sleep a specific number of seconds if SDELAY is set otherwise only sleep
- # 1 second
- if [ -n "${SDELAY}" ]
+ # Sleep a specific number of seconds if SDELAY is set
+ if [ "${SDELAY}" ]
then
+ good_msg 'Waiting ${SDELAY} seconds...'
sleep ${SDELAY}
elif grep cdroot /proc/cmdline > /dev/null 2>&1; then
sleep 3
else
- sleep 1
+ good_msg 'Hint: Use parameter scandelay[=seconds] if you need waiting here'
fi
}
@@ -884,6 +966,11 @@ cdupdate() {
fi
}
+setup_btrfsctl() {
+ # start BTRFS volume detection, if available
+ [ -x /sbin/btrfsctl ] && /sbin/btrfsctl -a
+}
+
setup_md_device() {
local device
@@ -897,7 +984,7 @@ setup_md_device() {
if [ ! -e /dev/md${MD_NUMBER} ]
then
mknod /dev/md${MD_NUMBER} b 9 ${MD_NUMBER} >/dev/null 2>&1
- [ "$?" -ne 0 ] && bad_msg "Creation of /dev/md${MD_NUMBER} failed..."
+ [ $? -ne 0 ] && bad_msg "Creation of /dev/md${MD_NUMBER} failed..."
fi
mdstart ${MDPART} /dev/md${MD_NUMBER}
fi
@@ -1058,7 +1145,7 @@ setup_unionfs() {
# # mount tmpfs only in the case when changes= boot parameter was
# # empty or we were not able to mount the storage device
# ret=$?
-# if [ "${ret}" -ne 0 ]
+# if [ ${ret} -ne 0 ]
# then
# bad_msg "mount of $CHANGESDEV failed falling back to ramdisk based unionfs"
# mount -t tmpfs tmpfs $MEMORY
@@ -1083,7 +1170,7 @@ setup_unionfs() {
good_msg "Creating union mount"
unionfs -o allow_other,cow,noinitgroups,suid,dev,default_permissions,use_ino ${rw_dir}=RW:${ro_dir}=RO ${UNION} 2>/dev/null
ret=$?
- if [ "${ret}" -ne 0 ]
+ if [ ${ret} -ne 0 ]
then
bad_msg "Can't setup union mount!"
USE_UNIONFS_NORMAL=0
diff --git a/defaults/kernel-config b/defaults/kernel-config
index 5f8c2ad..62de5e7 100644
--- a/defaults/kernel-config
+++ b/defaults/kernel-config
@@ -2888,6 +2888,41 @@ CONFIG_ZEROPLUS_FF=y
CONFIG_USB_HIDDEV=y
#
+# Special HID drivers
+#
+CONFIG_HID_COMPAT=y
+CONFIG_HID_A4TECH=m
+CONFIG_HID_APPLE=m
+CONFIG_HID_BELKIN=m
+CONFIG_HID_BRIGHT=m
+CONFIG_HID_CHERRY=m
+CONFIG_HID_CHICONY=m
+CONFIG_HID_CYPRESS=m
+CONFIG_HID_DELL=m
+CONFIG_HID_EZKEY=m
+CONFIG_HID_GYRATION=m
+CONFIG_HID_LOGITECH=m
+# CONFIG_LOGITECH_FF is not set
+# CONFIG_LOGIRUMBLEPAD2_FF is not set
+CONFIG_HID_MICROSOFT=m
+CONFIG_HID_MONTEREY=m
+CONFIG_HID_PANTHERLORD=m
+# CONFIG_PANTHERLORD_FF is not set
+CONFIG_HID_PETALYNX=m
+CONFIG_HID_SAMSUNG=m
+CONFIG_HID_SONY=m
+CONFIG_HID_SUNPLUS=m
+# CONFIG_THRUSTMASTER_FF is not set
+# CONFIG_ZEROPLUS_FF is not set
+CONFIG_USB_SUPPORT=y
+CONFIG_USB_ARCH_HAS_HCD=y
+CONFIG_USB_ARCH_HAS_OHCI=y
+CONFIG_USB_ARCH_HAS_EHCI=y
+CONFIG_USB=m
+# CONFIG_USB_DEBUG is not set
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+
+#
# USB HID Boot Protocol drivers
#
# CONFIG_USB_KBD is not set
@@ -3233,10 +3268,10 @@ CONFIG_EXT3_FS=y
CONFIG_EXT3_FS_XATTR=y
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
-CONFIG_EXT4DEV_FS=m
-CONFIG_EXT4DEV_FS_XATTR=y
-CONFIG_EXT4DEV_FS_POSIX_ACL=y
-CONFIG_EXT4DEV_FS_SECURITY=y
+CONFIG_EXT4_FS=m
+CONFIG_EXT4_FS_XATTR=y
+CONFIG_EXT4_FS_POSIX_ACL=y
+CONFIG_EXT4_FS_SECURITY=y
CONFIG_JBD=y
# CONFIG_JBD_DEBUG is not set
CONFIG_JBD2=m
diff --git a/defaults/linuxrc b/defaults/linuxrc
index 4a2ab72..7379633 100755
--- a/defaults/linuxrc
+++ b/defaults/linuxrc
@@ -29,12 +29,12 @@ mount -o remount,rw / >/dev/null 2>&1
if [ "$0" = '/init' ]
then
[ -e /linuxrc ] && rm /linuxrc
-
- if [ -e /bin/lvm ]
- then
- ln -s /bin/lvm /bin/vgscan
- ln -s /bin/lvm /bin/vgchange
- fi
+fi
+
+if [ -e /bin/lvm ]
+then
+ [ -e /bin/vgscan ] || ln -s /bin/lvm /bin/vgscan
+ [ -e /bin/vgchange ] || ln -s /bin/lvm /bin/vgchange
fi
quiet_kmsg
@@ -80,6 +80,9 @@ do
looptype\=*)
LOOPTYPE=`parse_opt "${x}"`
;;
+ isoboot\=*)
+ ISOBOOT=`parse_opt "${x}"`
+ ;;
# Start Volume manager options
dolvm)
USE_LVM_NORMAL=1
@@ -114,7 +117,7 @@ do
SDELAY=`parse_opt "${x}"`
;;
scandelay)
- SDELAY=10
+ SDELAY=3
;;
# Module no-loads
doload\=*)
@@ -239,7 +242,7 @@ do
# USE_UNIONFS_NORMAL=1
# CMD_UNIONFS=`parse_opt "${x}"`
# echo ${CMD_UNIONFS}|grep , >/dev/null 2>&1
-# if [ "$?" -eq '0' ]
+# if [ $? -eq 0 ]
# then
# UID=`echo ${CMD_UNIONFS#*,}`
# UNIONFS=`echo ${CMD_UNIONFS%,*}`
@@ -251,7 +254,7 @@ do
esac
done
-if [ -z "${REAL_ROOT}" -a \( "${CDROOT}" -eq 0 \) -a \( "${FAKE_ROOT}" != "/dev/ram0" \) ]
+if [ -z "${REAL_ROOT}" -a \( "${CDROOT}" = '0' \) -a \( "${FAKE_ROOT}" != "/dev/ram0" \) ]
then
REAL_ROOT="${FAKE_ROOT}"
fi
@@ -287,17 +290,23 @@ else
good_msg 'Skipping module load; no modules in the ramdisk!'
fi
-# Delay if needed for USB hardware
+# Apply scan delay if specified
sdelay
+# Setup slow USB bits
+setup_slowusb
+
# Start device manager
start_dev_mgr
+# if doslowusb is passed, pause other 10 seconds here, after mdev load
+[ "${DO_slowusb}" ] && sleep 10
+
# Start iSCSI
startiscsi
-# let iscsid settle - otherwise mounting the iSCSI-disk will fail (very rarely, though)
-sleep 1
+# Setup btrfs, see bug 303529
+setup_btrfsctl
# start BTRFS volume detection
[ -x /sbin/btrfsctl ] && /sbin/btrfsctl -a
@@ -322,22 +331,22 @@ then
RESUME_DEV=""
retval=1
- if [ "${retval}" -ne '0' ]; then
+ if [ ${retval} -ne 0 ]; then
RESUME_DEV=`findfs "${REAL_RESUME}" 2>/dev/null`
retval=$?
fi
- if [ "$retval" -ne '0' ]; then
+ if [ ${retval} -ne 0 ]; then
RESUME_DEV=`busybox findfs "${REAL_RESUME}" 2>/dev/null`
retval=$?
fi
- if [ "${retval}" -ne '0' ]; then
- RESUME_DEV=`blkid -t "${REAL_RESUME}" | cut -d ":" -f 1 2>/dev/null`
+ if [ ${retval} -ne 0 ]; then
+ RESUME_DEV=`blkid -l -t "${REAL_RESUME}" | cut -d ":" -f 1 2>/dev/null`
retval=$?
fi
- if [ "${retval}" -eq '0' ] && [ -n "${RESUME_DEV}" ]; then
+ if [ ${retval} -eq 0 ] && [ -n "${RESUME_DEV}" ]; then
good_msg "Detected real_resume=${RESUME_DEV}"
REAL_RESUME="${RESUME_DEV}"
fi
@@ -429,22 +438,22 @@ do
ROOT_DEV=""
retval=1
- if [ "${retval}" -ne '0' ]; then
+ if [ ${retval} -ne 0 ]; then
ROOT_DEV=`findfs "${REAL_ROOT}" 2>/dev/null`
retval=$?
fi
- if [ "$retval" -ne '0' ]; then
+ if [ ${retval} -ne 0 ]; then
ROOT_DEV=`busybox findfs "${REAL_ROOT}" 2>/dev/null`
retval=$?
fi
- if [ "${retval}" -ne '0' ]; then
- ROOT_DEV=`blkid -t "${REAL_ROOT}" | cut -d ":" -f 1 2>/dev/null`
+ if [ ${retval} -ne 0 ]; then
+ ROOT_DEV=`blkid -l -t "${REAL_ROOT}" | cut -d ":" -f 1 2>/dev/null`
retval=$?
fi
- if [ "${retval}" -eq '0' ] && [ -n "${ROOT_DEV}" ]; then
+ if [ ${retval} -eq 0 ] && [ -n "${ROOT_DEV}" ]; then
good_msg "Detected real_root=${ROOT_DEV}"
REAL_ROOT="${ROOT_DEV}"
else
@@ -660,8 +669,8 @@ then
directory="${directory#${NEW_ROOT}/${FS_LOCATION}/}"
# Skip this directory if we already linked a parent directory
- if [ "${curent_parrent}" != '' ]; then
- var=`echo "${directory}" | grep "^${curent_parrent}"`
+ if [ "${current_parent}" != '' ]; then
+ var=`echo "${directory}" | grep "^${current_parent}"`
if [ "${var}" != '' ]; then
continue
fi
@@ -700,11 +709,6 @@ then
# Let Init scripts know that we booted from CD
export CDBOOT
CDBOOT=1
- check_slowusb
- if [ "${DO_slowusb}" ] || [ "${FORCE_slowusb}" ]
- then
- sleep 10
- fi
else
if [ "${USE_UNIONFS_NORMAL}" = '1' ]
then
diff --git a/defaults/modprobe b/defaults/modprobe
index 8790122..ba2d890 100755
--- a/defaults/modprobe
+++ b/defaults/modprobe
@@ -112,7 +112,7 @@ modprobe2() {
done
${INSMOD} ${real_path} > /dev/null 2>&1
ret=$?
- if [ "$ret" -eq '0' ]
+ if [ ${ret} -eq 0 ]
then
echoAppend=' loaded.'
[ "${2}" = '-n' ] && echoFlags='-n' && echoAppend=', '
diff --git a/defaults/modules_load b/defaults/modules_load
index 15ad3e5..47643a1 100644
--- a/defaults/modules_load
+++ b/defaults/modules_load
@@ -25,5 +25,5 @@ MODULES_PCMCIA="pcmcia pcmcia_core yenta_socket pd6729 i82092 i82365 tcic ds ide
MODULES_USB="ehci-hcd uhci usb-ohci hid usb-storage uhci-hcd ohci-hcd usbhid sl811-hcd"
# Filesystems
-MODULES_FS="ext2 ext3 reiserfs jfs nfs xfs fuse"
+MODULES_FS="ext2 ext3 ext4 reiserfs jfs nfs xfs fuse"
diff --git a/doc/asciidoc.conf b/doc/asciidoc.conf
new file mode 100644
index 0000000..5835345
--- /dev/null
+++ b/doc/asciidoc.conf
@@ -0,0 +1,3 @@
+#
+# asciidoc.conf for genkernel's man page
+#
diff --git a/doc/genkernel.8.txt b/doc/genkernel.8.txt
new file mode 100644
index 0000000..b36137a
--- /dev/null
+++ b/doc/genkernel.8.txt
@@ -0,0 +1,478 @@
+GENKERNEL(8)
+============
+:man source: genkernel {genkernelversion}
+:man manual: genkernel {genkernelversion}
+
+
+NAME
+----
+genkernel - the Gentoo Linux automatic kernel compiler.
+
+
+SYNOPSIS
+--------
+*genkernel* [options...] action
+
+
+INTRODUCTION
+------------
+Genkernel is designed to allow users who are not previously used to
+compiling a kernel to use a similar setup to that one that is used on
+the Gentoo LiveCDs which auto-detects your hardware.
+
+Some users may also be interested in using genkernel for hardware which
+requires initialization and a working kernel before it can be booted
+because genkernel also automatically compiles your kernel modules,
+allowing hardware which needs to be loaded with module parameters to be
+used.
+
+
+USAGE
+-----
+All that is needed to run genkernel is just `genkernel` with an
+action and any flags you might need:
+
+------------------------------------------
+# genkernel --menuconfig --no-clean --no-install all
+------------------------------------------
+
+This would produce a kernel, asking you what how to configure it to
+your desire, leaving alone any existing compiled object files, but not
+installing anything.
+
+
+ACTIONS
+-------
+An action tells genkernel what you want it to do - the following
+actions are supported:
+
+*all*::
+ Build all steps - the kernel, modules, and the ramdisk.
+*bzImage*::
+ Build only the kernel.
+*initramfs*::
+ Build only the ramdisk/initramfs.
+*kernel*::
+ Build only the kernel and the modules.
+*ramdisk*::
+ Build only the ramdisk/initramfs.
+
+
+OPTIONS
+-------
+Genkernel supports the following options which alter its behaviour.
+Certain options have *--no-* variants which do the opposite thing.
+You can specify your options in any order.
+
+
+CONFIGURATION OPTIONS
+~~~~~~~~~~~~~~~~~~~~~
+*--config*=<file>::
+ Genkernel configuration file to use
+
+
+DEBUGGING OPTIONS
+~~~~~~~~~~~~~~~~~
+*--loglevel*=<0-5>::
+ This controls the out verbosity level of genkernel output - if
+ this is set to 0, minimal debugging is done; if this is set to 5
+ as much output as possible is given.
+
+*--logfile*=<outfile>::
+ This outputs debugging data to the file <outfile>. By default
+ this is '/var/log/genkernel.log'.
+
+*--*[*no-*]*color*::
+ Turns on, or off, output in color using escape sequences.
+
+
+KERNEL CONFIGURATION
+~~~~~~~~~~~~~~~~~~~~
+*--*[*no-*]*menuconfig*::
+ Runs, or does not run "make menuconfig" after running "make oldconfig".
+
+*--*[*no-*]*save-config*::
+ Saves, or does not save the kernel configuration to '/etc/kernels'
+ if the kernel is successfully compiled.
+
+*--gconfig*::
+ Run "make gconfig" after "make oldconfig".
+
+*--xconfig*::
+ Run "make xconfig" after "make oldconfig".
+
+
+KERNEL COMPILATION
+~~~~~~~~~~~~~~~~~~
+*--*[*no-*]*clean*::
+ Runs, or does not run, "make clean" before compilation - this
+ erases any compiled object files in the kernel source tree but
+ does not have an impact on the kernel configuration. Specifying
+ *--no-clean* implies *--no-mrproper*.
+
+*--*[*no-*]*mrproper*::
+ Runs, or does not run, "make mrproper" before compilation - this
+ erases both any compiled object files in the kernel source tree
+ as well as the kernel configuration.
+
+*--*[*no-*]*install*::
+ Installs, or does not install the kernel to '/boot' after building.
+ The default is *--install*. If MOUNTBOOT is set in
+ '/etc/genkernel.conf' then '/boot' will be automatically mounted if
+ it is not already mounted before the ramdisk and kernel images
+ are copied over.
+
+*--*[*no-*]*symlink*::
+ Manages, or does not manage, symlinks in '/boot' like the manual
+ kernel "make install" process does. A kernel (or, depending on
+ options, kernelz) symlink will link to the most recently built
+ kernel image and a kernel.old (or kernelz.old) symlink will link
+ to the second most recently built image, if one exists. Similar
+ symlinks (both * and *.old) are managed for initramfs and System.map.
+ The corresponding work products (i.e., the actual kernel
+ and initamfs images, and System.map) are also managed accordingly.
+ NOTE: Specifying *--symlink* does nothing unless
+ *--install* is also specified.
+
+*--oldconfig*::
+ Implies *--no-clean*, and thus *--no-mrproper*, running a "make oldconfig".
+
+*--gensplash*::
+ Install framebuffer splash support into initramfs.
+
+*--*[*no-*]*splash*::
+ Installs, or not, framebuffer splash support into initramfs.
+
+*--no-ramdisk-modules*::
+ Don't copy any modules to the ramdisk.
+
+*--all-ramdisk-modules*::
+ Copy all kernel modules to the initrd.
+
+*--callback*=<...>::
+ Run the specified arguments in the current environment after the
+ kernel and modules have been compiled.
+
+*--static*::
+ This builds a monolithic kernel without any modules on any
+ initial ramdisks.
+
+
+KERNEL LOCATIONS
+~~~~~~~~~~~~~~~~
+*--kerneldir*=<dir>::
+ This specifies the location of the kernel sources; the default
+ is '/usr/src/linux'.
+
+*--kernel-config*=<file>::
+ This specifies a kernel configuration file to use for compilation;
+ by default genkernel uses the config from the previous
+ build of the same kernel version or a default kernel config if
+ there isn't a previous config.
+
+*--module-prefix*=<dir>::
+ Prefix to kernel module destination, modules will be installed in
+ '<prefix>/lib/modules'.
+
+
+LOW-LEVEL COMPILATION OPTIONS
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+*--kernel-cc*=<compiler>::
+ Compiler to use for the kernel compilation (e.g. distcc).
+
+*--kernel-as*=<assembler>::
+ Assembler to use for the kernel compilation.
+
+*--kernel-ld*=<linker>::
+ Linker to use for the kernel compilation.
+
+*--kernel-cross-compile*=<cross var>::
+ CROSS_COMPILE kernel variable.
+
+*--kernel-make*=<makeprg>::
+ GNU Make to use for the kernel compilation.
+
+*--utils-cc*=<compiler>::
+ Compiler to use for utilities.
+
+*--utils-as*=<assembler>::
+ Assembler to use for utilities.
+
+*--utils-ld*=<linker>::
+ Linker to use for utilities.
+
+*--utils-make*=<makeprog>::
+ GNU Make to use for utilities.
+
+*--utils-cross-compile*=<cross var>::
+ CROSS_COMPILE utils variable.
+
+*--utils-arch*=<arch>::
+ Force to arch for utils only instead of autodetect.
+
+*--*[*no-*]*mountboot*::
+ Mount, or not, BOOTDIR automatically if mountable.
+
+*--bootdir*=<dir>::
+ Set the location of the boot-directory, default is '/boot'.
+
+*--makeopts*=<makeopts>::
+ GNU Make options such as -j2, etc.
+
+
+INITIALIZATION
+~~~~~~~~~~~~~~
+*--gensplash*=<theme>::
+ Enable framebuffer splash using <theme>.
+
+*--gensplash-res*=<resolutions>::
+ Select gensplash resolutions to include.
+
+*--*[*no-*]*splash*=<theme>::
+ If the extra argument is specified, splash is forced using
+ <theme> rather than the default theme specified in your splash
+ configuration. If *--no-splash* is specified, then splash is disabled.
+
+*--splash-res*=<resolutions>::
+ Optionally select splash resolutions to include.
+
+*--do-keymap-auto*::
+ Force keymap selection at boot.
+
+*--no-keymap*::
+ Disables keymap selection at boot.
+
+*--evms*::
+*--evms2*::
+ Add in EVMS support from static binaries if they exist on the system:
+ you should run "emerge evms" first (in the host system).
+
+*--lvm*::
+*--lvm2*::
+ Add in LVM support from static binaries if they exist on the
+ system, or compile static LVM binaries if static ones do not
+ exist.
+
+*--mdadm*::
+ Copy '/etc/mdadm.conf' to initramfs.
+
+*--dmraid*::
+ Add DMRAID support.
+
+*--multipath*::
+ Include Multipath support
+
+*--iscsi*::
+ Include iSCSI support
+
+*--slowusb*::
+ Enables extra pauses for slow USB CD boots.
+
+*--bootloader*=*grub*::
+ Add new kernel to GRUB configuration.
+
+*--linuxrc*=<file>::
+ Use <file> for the linuxrc instead of the genkernel linuxrc.
+
+*--busybox-config*=<file>::
+ Specifies a user created busybox config.
+
+*--genzimage*::
+ Make and install kernelz image from 'arch/powerpc/boot/zImage.initrd'.
+
+*--disklabel*::
+ Include disk label and uuid support in your initrd.
+
+*--luks*::
+ Add in Luks support from static binaries if they exist on the
+ system.
+
+*--gpg*::
+ Add support for GnuPG 1.x, the portable standalone branch of GnuPG.
+ A key can be made from
+ `gpg --encrypt --symmetric /path/to/LUKS-key > /path/to/LUKS-key.gpg` .
+ After that, re-point the *root_key* argument to the new .gpg file.
+
+*--no-busybox*::
+ Do not include busybox in the initrd or initramfs.
+
+*--unionfs*::
+ Include support for unionfs
+
+*--netboot*::
+ Create a self-contained env in the initramfs
+
+*--real-root*=<foo>::
+ Specify a default for *real_root*= kernel option.
+
+
+INTERNALS
+~~~~~~~~~
+*--arch-override*=<arch>::
+ Force the architecture settings described by the <arch> profile
+ instead of autodetecting the running architecture.
+
+*--cachedir*=<dir>::
+ Override the default cache location.
+
+*--tempdir*=<dir>::
+ Sets genkernel's temporary working directory to <dir>.
+
+*--postclear*::
+ Clear all tmp files and caches after genkernel has run.
+
+
+OUTPUT SETTINGS
+~~~~~~~~~~~~~~~
+*--kernname*=<...>::
+ Tag the kernel and initrd with a name, if not defined this
+ option defaults to genkernel
+
+*--minkernpackage*=<tbz2>::
+ File to output a .tar.bz2'd kernel and initrd: no modules outside
+ of the initrd will be included...
+
+*--modulespackage*=<tbz2>::
+ File to output a .tar.bz2'd modules after the callbacks have run
+
+*--kerncache*=<tbz2>::
+ File to output a .tar.bz2'd kernel, contents of '/lib/modules/'
+ and the kernel config. NOTE: This is created before the callbacks
+ are run.
+
+*--no-kernel-sources*=<tbz2>::
+ This option is only valid if kerncache is defined If there is a
+ valid kerncache no checks will be made against a kernel source
+ tree.
+
+*--initramfs-overlay*=<dir>::
+ Directory structure to include in the initramfs, only available
+ on 2.6 kernels
+
+*--firmware*::
+ Enable copying of firmware into initramfs.
+
+*--firmware-dir*=<dir>::
+ Specify directory to copy firmware from (defaults to '/lib/firmware').
+
+*--firmware-files*=<files>::
+ Specifies specific firmware files to copy. This overrides *--firmware-dir*.
+ For multiple files, separate the filenames with a comma.
+
+*--integrated-initramfs*::
+ Build the generated initramfs into the kernel instead of keeping it as a separate file.
+
+
+RAMDISK OPTIONS
+---------------
+The following options can be passed as kernel parameters from the bootloader,
+which the ramdisk scripts would recognize.
+
+*real_root*=<...>::
+ Specifies the device node of the root filesystem to mount.
+
+*crypt_root*=<...>::
+ This specifies the device encrypted by Luks, which contains the
+ root filesystem to mount.
+
+*crypt_swap*=<...>::
+ This specifies the swap device encrypted by Luks.
+
+*root_key*=<...>::
+ In case your root is encrypted with a key, you can use a device
+ like a usb pen to store the key. This value should be the key
+ path relative to the mount point.
+
+*root_keydev*=<...>::
+ If necessary provide the name of the device that carries the
+ root_key. If unset while using root_key, it will automatically
+ look for the device in every boot.
+
+*swap_key*=<...>::
+ Same as root_key for swap.
+
+*swap_keydev*=<...>::
+ Same as root_keydev for swap.
+
+*crypt_silent*::
+ Set this to silent all the output related to the cryptographic
+ software, and in case your encrypted device isn't open with the
+ key, it opens a shell in the initrd quietly.
+
+*dodmraid*=<...>::
+ Passes arguments to dmraid on bootup.
+
+*real_init*=<...>::
+ Passes arguments to init on bootup.
+
+*scandelay*=<...>::
+ Pauses for 10 seconds before running devfsd if no argument is
+ specified; otherwise pauses for the number of specified seconds.
+
+*ip*=<...>::
+ Normally used to tell the kernel that it should start a network
+ interface. If present, the initrd will try to mount a livecd
+ over NFS.
+
+*nfsroot*=<...>::
+ If present, the initrd will try to mount a livecd from that
+ location. Otherwise the location will be deduced from the DCHP
+ request (option root-path)
+
+*doevms*::
+ Activate EVMS volumes on bootup
+
+*dolvm*::
+ Activate LVM volumes on bootup
+
+*doscsi*::
+ Activate SCSI devices on bootup, necessary when SCSI support is
+ compiled as modules and you're using SCSI or SATA devices.
+
+*keymap*='MAP'::
+ Set keymap to 'MAP', e.g. *keymap*=de.
+ For valid values of 'MAP' please see
+ '/usr/share/genkernel/defaults/keymaps.tar.gz'.
+
+*dokeymap*::
+ Use keymap. Usage of *keymap*= implies this option, already.
+
+
+NETBOOTING
+----------
+The initrd scripts have limited support for network booting. This is
+activated if the *ip*=<...> kernel parameter was given. Please refer to
+the genkernel guide at 'http://www.gentoo.org/doc/en/genkernel.xml' for
+more information.
+
+The initrd scripts will extract any *.tar.gz files found in the '/add'
+directory of the livecd into the root filesystem during boot. This way
+it is easy to extend a netbooted LiveCD i.e. add custom tools, or other
+kernel modules.
+
+
+REPORTING BUGS
+--------------
+If you believe you have found a bug in the genkernel scripts, then
+please file a bug on the Gentoo Linux Bugzilla: 'http://bugs.gentoo.org',
+assigning your bug to genkernel@gentoo.org. We cannot assist you with
+kernel compilation failures unless they are caused by a genkernel bug.
+
+Kernel issues for Gentoo-supported kernels, including compilation failures
+should go to 'http://bugs.gentoo.org' and should be assigned to kernel@gentoo.org.
+Please check if an existing bug documents the same
+issue before opening a new bug. Issues for kernel sources not supported
+by Gentoo should go to their relevant authors.
+
+
+AUTHORS
+-------
+- Tim Yamin <plasmaroo@gentoo.org>
+- Eric Edgar <rocket@gentoo.org>
+- NFS Support by Thomas Seiler <thseiler@gmail.com>
+- GnuPG 1.x integration by dacook <schism@subverted.org>
+
+
+SEE ALSO
+--------
+/etc/genkernel.conf - genkernel configuration file
diff --git a/gen_bootloader.sh b/gen_bootloader.sh
index 9b1deef..3e6f98b 100755
--- a/gen_bootloader.sh
+++ b/gen_bootloader.sh
@@ -63,7 +63,7 @@ set_bootloader_grub() {
# Add grub configuration to grub.conf
echo "# Genkernel generated entry, see GRUB documentation for details" >> ${GRUB_CONF}
echo "title=Gentoo Linux ($KV)" >> ${GRUB_CONF}
- if [ "${BUILD_INITRD}" -eq '0' ]
+ if [ "${BUILD_INITRD}" = '0' ]
then
echo -e "\tkernel /kernel-${KNAME}-${ARCH}-${KV} root=${GRUB_ROOTFS}" >> ${GRUB_CONF}
else
diff --git a/gen_cmdline.sh b/gen_cmdline.sh
index bb0d8fd..1bf5de3 100755
--- a/gen_cmdline.sh
+++ b/gen_cmdline.sh
@@ -3,12 +3,14 @@
longusage() {
echo "Gentoo Linux Genkernel ${GK_V}"
+ echo
echo "Usage: "
echo " genkernel [options] action"
echo
echo "Available Actions: "
echo " all Build all steps"
echo " bzImage Build only the kernel"
+ echo " initramfs Build only the ramdisk/initramfs"
echo " kernel Build only the kernel and modules"
echo " ramdisk Build only the ramdisk/initramfs"
echo
@@ -90,10 +92,12 @@ longusage() {
echo " --bootloader=grub Add new kernel to GRUB configuration"
echo " --linuxrc=<file> Specifies a user created linuxrc"
echo " --busybox-config=<file> Specifies a user created busybox config"
+ echo " --genzimage Make and install kernelz image (PowerPC)"
echo " --disklabel Include disk label and uuid support in your"
echo " ramdisk"
echo " --luks Include LUKS support"
echo " --> 'emerge cryptsetup-luks' with USE=-dynamic"
+ echo " --gpg Include GPG-armored LUKS key support"
echo " --no-busybox Do not include busybox in the initramfs."
echo " --unionfs Include support for unionfs"
echo " --netboot Create a self-contained env in the initramfs"
@@ -138,6 +142,7 @@ longusage() {
usage() {
echo "Gentoo Linux Genkernel ${GK_V}"
+ echo
echo "Usage: "
echo " genkernel [options] all"
echo
@@ -307,7 +312,7 @@ parse_cmdline() {
if [[ TERM_LINES -lt 19 || TERM_COLUMNS -lt 80 ]]
then
echo "Error: You need a terminal with at least 80 columns"
- echo " and 19 lines for --menuconfig; try --nomenuconfig..."
+ echo " and 19 lines for --menuconfig; try --no-menuconfig..."
exit 1
fi
CMD_MENUCONFIG=1
@@ -520,6 +525,10 @@ parse_cmdline() {
CMD_LUKS=1
print_info 2 "CMD_LUKS: ${CMD_LUKS}"
;;
+ --gpg)
+ CMD_GPG=1
+ print_info 2 "CMD_GPG: ${CMD_GPG}"
+ ;;
--firmware)
CMD_FIRMWARE=1
print_info 2 "CMD_FIRMWARE: ${CMD_FIRMWARE}"
diff --git a/gen_compile.sh b/gen_compile.sh
index 7bab9e1..7438f34 100755
--- a/gen_compile.sh
+++ b/gen_compile.sh
@@ -203,6 +203,7 @@ apply_patches() {
print_info 1 "${util}: >> Applying patches..."
for i in ${GK_SHARE}/patches/${util}/${version}/*{diff,patch}
do
+ [ -f "${i}" ] || continue
patch_success=0
for j in `seq 0 5`
do
@@ -213,8 +214,10 @@ apply_patches() {
break
fi
done
- if [ ${patch_success} != 1 ]
+ if [ ${patch_success} -eq 1 ]
then
+ print_info 1 " - `basename ${i}`"
+ else
gen_die "could not apply patch ${i} for ${util}-${version}"
fi
done
@@ -264,7 +267,7 @@ compile_generic() {
eval ${MAKE} ${MAKEOPTS} ${ARGS} ${target} $* >> ${LOGFILE} 2>&1
RET=$?
fi
- [ "${RET}" -ne '0' ] &&
+ [ ${RET} -ne 0 ] &&
gen_die "Failed to compile the \"${target}\" target..."
unset MAKE
@@ -300,6 +303,15 @@ compile_kernel() {
compile_generic "${KERNEL_MAKE_DIRECTIVE_2}" kernel
fi
+ local firmware_in_kernel_line=`fgrep CONFIG_FIRMWARE_IN_KERNEL "${KERNEL_DIR}"/.config`
+ if [ -n "${firmware_in_kernel_line}" -a "${firmware_in_kernel_line}" != CONFIG_FIRMWARE_IN_KERNEL=y ]
+ then
+ print_info 1 " >> Installing firmware ('make firmware_install') due to CONFIG_FIRMWARE_IN_KERNEL != y..."
+ compile_generic "firmware_install" kernel
+ else
+ print_info 1 " >> Not installing firmware as it's included in the kernel already (CONFIG_FIRMWARE_IN_KERNEL=y)..."
+ fi
+
local tmp_kernel_binary=$(find_kernel_binary ${KERNEL_BINARY})
local tmp_kernel_binary2=$(find_kernel_binary ${KERNEL_BINARY_2})
if [ -z "${tmp_kernel_binary}" ]
@@ -405,7 +417,6 @@ compile_busybox() {
}
compile_lvm() {
- compile_device_mapper
if [ ! -f "${LVM_BINCACHE}" ]
then
[ -f "${LVM_SRCTAR}" ] ||
@@ -421,11 +432,13 @@ compile_lvm() {
gen_die "Could not extract device-mapper binary cache!";
cd "${LVM_DIR}"
+ apply_patches lvm ${LVM_VER}
print_info 1 'lvm: >> Configuring...'
- LDFLAGS="-L${TEMP}/device-mapper/lib" \
- CFLAGS="-I${TEMP}/device-mapper/include" \
- CPPFLAGS="-I${TEMP}/device-mapper/include" \
- ./configure --enable-static_link --prefix=${TEMP}/lvm >> ${LOGFILE} 2>&1 ||
+ CFLAGS="-fPIC" \
+ ./configure --enable-static_link --prefix=${TEMP}/lvm \
+ --with-lvm1=internal --with-clvmd=none --with-cluster=none \
+ --disable-readline --disable-selinux --with-mirrors=internal \
+ --with-snapshots=internal --with-pool=internal >> ${LOGFILE} 2>&1 || \
gen_die 'Configure of lvm failed!'
print_info 1 'lvm: >> Compiling...'
compile_generic '' utils
@@ -502,6 +515,7 @@ compile_device_mapper() {
[ ! -d "${DEVICE_MAPPER_DIR}" ] &&
gen_die "device-mapper directory ${DEVICE_MAPPER_DIR} invalid"
cd "${DEVICE_MAPPER_DIR}"
+ CFLAGS="-fPIC" \
./configure --prefix=${TEMP}/device-mapper --enable-static_link \
--disable-selinux >> ${LOGFILE} 2>&1 ||
gen_die 'Configuring device-mapper failed!'
@@ -525,8 +539,10 @@ compile_device_mapper() {
}
compile_e2fsprogs() {
- if [ ! -f "${BLKID_BINCACHE}" ]
+ if [ -f "${BLKID_BINCACHE}" ]
then
+ print_info 1 "blkid: >> Using cache"
+ else
[ ! -f "${E2FSPROGS_SRCTAR}" ] &&
gen_die "Could not find e2fsprogs source tarball: ${E2FSPROGS_SRCTAR}. Please place it there, or place another version, changing /etc/genkernel.conf as necessary!"
cd "${TEMP}"
@@ -536,7 +552,7 @@ compile_e2fsprogs() {
gen_die "e2fsprogs directory ${E2FSPROGS_DIR} invalid"
cd "${E2FSPROGS_DIR}"
print_info 1 'e2fsprogs: >> Configuring...'
- ./configure --with-ldopts=-static >> ${LOGFILE} 2>&1 ||
+ LDFLAGS=-static ./configure >> ${LOGFILE} 2>&1 ||
gen_die 'Configuring e2fsprogs failed!'
print_info 1 'e2fsprogs: >> Compiling...'
MAKE=${UTILS_MAKE} compile_generic "" ""
@@ -663,3 +679,46 @@ compile_iscsi() {
fi
}
+compile_gpg() {
+ if [ -f "${GPG_BINCACHE}" ]
+ then
+ print_info 1 "gnupg: >> Using cache"
+ else
+ [ ! -f "${GPG_SRCTAR}" ] &&
+ gen_die "Could not find gnupg source tarball: ${GPG_SRCTAR}. Please place it there, or place another version, changing /etc/genkernel.conf as necessary!"
+ cd "${TEMP}"
+ rm -rf "${GPG_DIR}"
+ tar -jxf "${GPG_SRCTAR}"
+ [ ! -d "${GPG_DIR}" ] &&
+ gen_die "gnupg directory ${GPG_DIR} invalid"
+ cd "${GPG_DIR}"
+ print_info 1 'gnupg: >> Configuring...'
+ # --enable-minimal works, but it doesn't reduce the command length much.
+ # Given its history and the precision this needs, explicit is cleaner.
+ LDFLAGS='-static' CFLAGS='-Os' ./configure --prefix=/ \
+ --enable-static-rnd=linux --disable-dev-random --disable-asm \
+ --disable-selinux-support --disable-gnupg-iconv --disable-card-support \
+ --disable-agent-support --disable-bzip2 --disable-exec \
+ --disable-photo-viewers --disable-keyserver-helpers --disable-ldap \
+ --disable-hkp --disable-finger --disable-generic --disable-mailto \
+ --disable-keyserver-path --disable-dns-srv --disable-dns-pka \
+ --disable-dns-cert --disable-nls --disable-threads --disable-regex \
+ --disable-optimization --with-included-zlib --without-capabilities \
+ --without-tar --without-ldap --without-libcurl --without-mailprog \
+ --without-libpth-prefix --without-libiconv-prefix --without-libintl-prefix\
+ --without-zlib --without-bzip2 --without-libusb --without-readline \
+ >> ${LOGFILE} 2>&1 || gen_die 'Configuring gnupg failed!'
+ print_info 1 'gnupg: >> Compiling...'
+ compile_generic "" "utils"
+ print_info 1 'gnupg: >> Copying to cache...'
+ [ -f "${TEMP}/${GPG_DIR}/g10/gpg" ] ||
+ gen_die 'gnupg executable does not exist!'
+ strip "${TEMP}/${GPG_DIR}/g10/gpg" ||
+ gen_die 'Could not strip gpg binary!'
+ bzip2 -z -c "${TEMP}/${GPG_DIR}/g10/gpg" > "${GPG_BINCACHE}" ||
+ gen_die 'Could not copy the gpg binary to the package directory, does the directory exist?'
+
+ cd "${TEMP}"
+ rm -rf "${GPG_DIR}" > /dev/null
+ fi
+}
diff --git a/gen_configkernel.sh b/gen_configkernel.sh
index 8c00f8d..2f14b4d 100755
--- a/gen_configkernel.sh
+++ b/gen_configkernel.sh
@@ -29,43 +29,57 @@ config_kernel() {
determine_config_file
cd "${KERNEL_DIR}" || gen_die 'Could not switch to the kernel directory!'
- isTrue "${CLEAN}" && cp "${KERNEL_DIR}/.config" "${KERNEL_DIR}/.config.bak" > /dev/null 2>&1
+ # Backup current kernel .config
+ if isTrue "${MRPROPER}" || [ ! -f "${KERNEL_DIR}/.config" ]
+ then
+ print_info 1 "kernel: Using config from ${KERNEL_CONFIG}"
+ if [ -f "${KERNEL_DIR}/.config" ]
+ then
+ NOW=`date +--%Y-%m-%d--%H-%M-%S`
+ cp "${KERNEL_DIR}/.config" "${KERNEL_DIR}/.config${NOW}.bak" \
+ || gen_die "Could not backup kernel config (${KERNEL_DIR}/.config)"
+ print_info 1 " Previous config backed up to .config${NOW}.bak"
+ fi
+ fi
+
if isTrue ${MRPROPER}
then
print_info 1 'kernel: >> Running mrproper...'
compile_generic mrproper kernel
+ else
+ print_info 1 "kernel: --mrproper is disabled; not running 'make mrproper'."
fi
- # If we're not cleaning, then we don't want to try to overwrite the configs
+ # If we're not cleaning a la mrproper, then we don't want to try to overwrite the configs
# or we might remove configurations someone is trying to test.
-
- if isTrue "${CLEAN}"
+ if isTrue "${MRPROPER}" || [ ! -f "${KERNEL_DIR}/.config" ]
then
- print_info 1 "config: Using config from ${KERNEL_CONFIG}"
- print_info 1 ' Previous config backed up to .config.bak'
cp "${KERNEL_CONFIG}" "${KERNEL_DIR}/.config" || gen_die 'Could not copy configuration file!'
fi
+
if isTrue "${OLDCONFIG}"
then
print_info 1 ' >> Running oldconfig...'
yes '' 2>/dev/null | compile_generic oldconfig kernel 2>/dev/null
+ else
+ print_info 1 "kernel: --oldconfig is disabled; not running 'make oldconfig'."
fi
if isTrue "${CLEAN}"
then
print_info 1 'kernel: >> Cleaning...'
compile_generic clean kernel
else
- print_info 1 "config: --no-clean is enabled; leaving the .config alone."
+ print_info 1 "kernel: --clean is disabled; not running 'make clean'."
fi
if isTrue ${MENUCONFIG}
then
- print_info 1 'config: >> Invoking menuconfig...'
+ print_info 1 'kernel: >> Invoking menuconfig...'
compile_generic menuconfig runtask
[ "$?" ] || gen_die 'Error: menuconfig failed!'
elif isTrue ${CMD_GCONFIG}
then
- print_info 1 'config: >> Invoking gconfig...'
+ print_info 1 'kernel: >> Invoking gconfig...'
compile_generic gconfig kernel
[ "$?" ] || gen_die 'Error: gconfig failed!'
@@ -74,7 +88,7 @@ config_kernel() {
if isTrue ${CMD_XCONFIG}
then
- print_info 1 'config: >> Invoking xconfig...'
+ print_info 1 'kernel: >> Invoking xconfig...'
compile_generic xconfig kernel
[ "$?" ] || gen_die 'Error: xconfig failed!'
fi
diff --git a/gen_determineargs.sh b/gen_determineargs.sh
index abf3f08..3e39e86 100755
--- a/gen_determineargs.sh
+++ b/gen_determineargs.sh
@@ -20,6 +20,11 @@ get_KV() {
# Configure the kernel
# If BUILD_KERNEL=0 then assume --no-clean, menuconfig is cleared
+ if [ ! -f "${KERNEL_DIR}"/Makefile ]
+ then
+ gen_die "Kernel Makefile (${KERNEL_DIR}/Makefile) missing. Maybe re-install the kernel sources."
+ fi
+
VER=`grep ^VERSION\ \= ${KERNEL_DIR}/Makefile | awk '{ print $3 };'`
PAT=`grep ^PATCHLEVEL\ \= ${KERNEL_DIR}/Makefile | awk '{ print $3 };'`
SUB=`grep ^SUBLEVEL\ \= ${KERNEL_DIR}/Makefile | awk '{ print $3 };'`
@@ -29,6 +34,7 @@ get_KV() {
then
# Handle O= build directories
KERNEL_SOURCE_DIR=`grep ^MAKEARGS\ \:\= ${KERNEL_DIR}/Makefile | awk '{ print $4 };'`
+ [ -z "${KERNEL_SOURCE_DIR}" ] && gen_die "Deriving \${KERNEL_SOURCE_DIR} failed"
SUB=`grep ^SUBLEVEL\ \= ${KERNEL_SOURCE_DIR}/Makefile | awk '{ print $3 };'`
EXV=`grep ^EXTRAVERSION\ \= ${KERNEL_SOURCE_DIR}/Makefile | sed -e "s/EXTRAVERSION =//" -e "s/ //g" -e 's/\$([a-z]*)//gi'`
fi
@@ -110,6 +116,7 @@ determine_real_args() {
set_config_with_override 2 REAL_ROOT CMD_REAL_ROOT
set_config_with_override 1 DISKLABEL CMD_DISKLABEL
set_config_with_override 1 LUKS CMD_LUKS
+ set_config_with_override 1 GPG CMD_GPG
set_config_with_override 1 MDADM CMD_MDADM
set_config_with_override 1 MULTIPATH CMD_MULTIPATH
set_config_with_override 1 FIRMWARE CMD_FIRMWARE
@@ -133,6 +140,7 @@ determine_real_args() {
BLKID_BINCACHE=`cache_replace "${BLKID_BINCACHE}"`
FUSE_BINCACHE=`cache_replace "${FUSE_BINCACHE}"`
UNIONFS_FUSE_BINCACHE=`cache_replace "${UNIONFS_FUSE_BINCACHE}"`
+ GPG_BINCACHE=`cache_replace "${GPG_BINCACHE}"`
DEFAULT_KERNEL_CONFIG=`arch_replace "${DEFAULT_KERNEL_CONFIG}"`
BUSYBOX_CONFIG=`arch_replace "${BUSYBOX_CONFIG}"`
@@ -144,6 +152,7 @@ determine_real_args() {
BLKID_BINCACHE=`arch_replace "${BLKID_BINCACHE}"`
FUSE_BINCACHE=`arch_replace "${FUSE_BINCACHE}"`
UNIONFS_FUSE_BINCACHE=`arch_replace "${UNIONFS_FUSE_BINCACHE}"`
+ GPG_BINCACHE=`arch_replace "${GPG_BINCACHE}"`
if [ -n "${CMD_BOOTLOADER}" ]
then
diff --git a/gen_funcs.sh b/gen_funcs.sh
index e4a1c4a..6af595e 100755
--- a/gen_funcs.sh
+++ b/gen_funcs.sh
@@ -94,7 +94,7 @@ print_info() {
# PRINT TO SCREEN ONLY IF PASSED LOGLEVEL IS HIGHER THAN
# OR EQUAL TO SET DEBUG LEVEL
- if [ "$1" -lt "${LOGLEVEL}" -o "$1" -eq "${LOGLEVEL}" ]
+ if [ "$1" -lt "${LOGLEVEL}" -o "$1" = "${LOGLEVEL}" ]
then
SCRPRINT='1'
fi
@@ -106,7 +106,7 @@ print_info() {
fi
# STRUCTURE DATA TO BE OUTPUT TO SCREEN, AND OUTPUT IT
- if [ "${SCRPRINT}" -eq '1' ]
+ if [ "${SCRPRINT}" = '1' ]
then
if [ "${PREFIXLINE}" = '1' ]
then
@@ -124,7 +124,7 @@ print_info() {
fi
# STRUCTURE DATA TO BE OUTPUT TO FILE, AND OUTPUT IT
- if [ "${SCRPRINT}" -eq '1' -o "${FORCEFILE}" -eq '1' ]
+ if [ "${SCRPRINT}" = '1' -o "${FORCEFILE}" = '1' ]
then
STRR=${2//${WARN}/}
STRR=${STRR//${BAD}/}
@@ -140,13 +140,13 @@ print_info() {
if [ "${NEWLINE}" = '0' ]
then
- if [ "${TODEBUGCACHE}" -eq '1' ]; then
+ if [ "${TODEBUGCACHE}" = '1' ]; then
DEBUGCACHE="${DEBUGCACHE}${STR}"
else
echo -ne "${STR}" >> ${LOGFILE}
fi
else
- if [ "${TODEBUGCACHE}" -eq '1' ]; then
+ if [ "${TODEBUGCACHE}" = '1' ]; then
DEBUGCACHE="${DEBUGCACHE}${STR}"$'\n'
else
echo "${STR}" >> ${LOGFILE}
@@ -250,13 +250,11 @@ setup_cache_dir()
if [ "${CLEAR_CACHE_DIR}" == 'yes' ]
then
print_info 1 "Clearing cache dir contents from ${CACHE_DIR}"
- CACHE_DIR_CONTENTS=`ls ${CACHE_DIR}|grep -v CVS|grep -v cpio|grep -v README`
-
- for i in ${CACHE_DIR_CONTENTS}
+ while read i
do
print_info 1 " >> removing ${i}"
- rm ${CACHE_DIR}/${i}
- done
+ rm "${i}"
+ done < <(find "${CACHE_DIR}" -maxdepth 1 -type f -name '*.tar.*' -o -name '*.bz2')
fi
}
@@ -265,13 +263,13 @@ clear_tmpdir()
{
if ! isTrue ${CMD_NOINSTALL}
then
- TMPDIR_CONTENTS=`ls ${TMPDIR}`
- print_info 1 "Removing tmp dir contents"
- for i in ${TMPDIR_CONTENTS}
- do
- print_info 1 " >> removing ${i}"
- rm ${TMPDIR}/${i}
- done
+ TMPDIR_CONTENTS=`ls ${TMPDIR}`
+ print_info 1 "Removing tmp dir contents"
+ for i in ${TMPDIR_CONTENTS}
+ do
+ print_info 1 " >> removing ${i}"
+ rm ${TMPDIR}/${i}
+ done
fi
}
@@ -303,7 +301,7 @@ copy_image_with_preserve() {
# Old product might be a different version. If so, we need to read
# the symlink to see what it's name is, if there are symlinks.
- if [ "${SYMLINK}" -eq '1' ]
+ if [ "${SYMLINK}" = '1' ]
then
print_info 4 "automatically managing symlinks and old images." 1 0
if [ -e "${BOOTDIR}/${symlinkName}" ]
@@ -349,7 +347,7 @@ copy_image_with_preserve() {
# When symlinks are not being managed by genkernel, old symlinks might
# still be useful. Leave 'em alone unless managed.
- if [ "${SYMLINK}" -eq '1' ]
+ if [ "${SYMLINK}" = '1' ]
then
print_info 5 " Deleting old symlinks, if any."
rm -f "${BOOTDIR}/${symlinkName}"
@@ -367,7 +365,7 @@ copy_image_with_preserve() {
#
print_info 5 " Same base version. May have to delete old image to make room."
- if [ "${currDestImageExists}" -eq '1' ]
+ if [ "${currDestImageExists}" = '1' ]
then
if [ -e "${BOOTDIR}/${currDestImage}.old" ]
then
@@ -395,14 +393,14 @@ copy_image_with_preserve() {
cp "${newSrceImage}" "${BOOTDIR}/${currDestImage}" ||
gen_die "Could not copy the ${symlinkName} image to ${BOOTDIR}!"
- if [ "${SYMLINK}" -eq '1' ]
+ if [ "${SYMLINK}" = '1' ]
then
print_info 5 " Make new symlink(s) (from ${BOOTDIR}):"
print_info 5 " ${symlinkName} -> ${currDestImage}"
pushd ${BOOTDIR} >/dev/null
ln -s "${currDestImage}" "${symlinkName}" ||
gen_die "Could not create the ${symlinkName} symlink!"
- if [ "${prevDestImageExists}" -eq '1' ]
+ if [ "${prevDestImageExists}" = '1' ]
then
print_info 5 " ${symlinkName}.old -> ${prevDestImage}"
ln -s "${prevDestImage}" "${symlinkName}.old" ||
@@ -486,7 +484,7 @@ set_config_with_override() {
fi
fi
- if [ "$VarType" -eq "1" ]
+ if [ "${VarType}" = "1" ]
then
if isTrue "${Result}"
then
@@ -500,7 +498,7 @@ set_config_with_override() {
}
check_distfiles() {
- for i in $BUSYBOX_SRCTAR $DEVICE_MAPPER_SRCTAR $MULTIPATH_SRCTAR $LVM_SRCTAR $DMRAID_SRCTAR $E2FSPROGS_SRCTAR $ISCSI_SRCTAR
+ for i in $BUSYBOX_SRCTAR $DEVICE_MAPPER_SRCTAR $MULTIPATH_SRCTAR $LVM_SRCTAR $DMRAID_SRCTAR $E2FSPROGS_SRCTAR $ISCSI_SRCTAR $GPG_SRCTAR
do
if [ ! -f "${i}" ]
then
diff --git a/gen_initramfs.sh b/gen_initramfs.sh
index 820dc04..ac32516 100755
--- a/gen_initramfs.sh
+++ b/gen_initramfs.sh
@@ -34,7 +34,9 @@ append_base_layout() {
date '+%Y%m%d' > ${TEMP}/initramfs-base-temp/etc/build_date
cd "${TEMP}/initramfs-base-temp/"
- find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}"
+ find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}" \
+ || gen_die "compressing baselayout cpio"
+ cd "${TEMP}"
rm -rf "${TEMP}/initramfs-base-temp" > /dev/null
}
@@ -54,14 +56,16 @@ append_busybox() {
chmod +x "${TEMP}/initramfs-busybox-temp/usr/share/udhcpc/default.script"
# Set up a few default symlinks
- for i in '[' ash sh mount uname echo cut cat; do
+ for i in ${BUSYBOX_APPLETS:-[ ash sh mount uname echo cut cat}; do
rm -f ${TEMP}/initramfs-busybox-temp/bin/$i > /dev/null
- ln ${TEMP}/initramfs-busybox-temp/bin/busybox ${TEMP}/initramfs-busybox-temp/bin/$i ||
+ ln -s busybox ${TEMP}/initramfs-busybox-temp/bin/$i ||
gen_die "Busybox error: could not link ${i}!"
done
cd "${TEMP}/initramfs-busybox-temp/"
- find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}"
+ find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}" \
+ || gen_die "compressing busybox cpio"
+ cd "${TEMP}"
rm -rf "${TEMP}/initramfs-busybox-temp" > /dev/null
}
@@ -72,11 +76,13 @@ append_blkid(){
fi
cd ${TEMP}
mkdir -p "${TEMP}/initramfs-blkid-temp/bin/"
- [ "${DISKLABEL}" -eq '1' ] && { /bin/bzip2 -dc "${BLKID_BINCACHE}" > "${TEMP}/initramfs-blkid-temp/bin/blkid" ||
+ [ "${DISKLABEL}" = '1' ] && { /bin/bzip2 -dc "${BLKID_BINCACHE}" > "${TEMP}/initramfs-blkid-temp/bin/blkid" ||
gen_die "Could not extract blkid binary cache!"; }
chmod a+x "${TEMP}/initramfs-blkid-temp/bin/blkid"
cd "${TEMP}/initramfs-blkid-temp/"
- find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}"
+ find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}" \
+ || gen_die "compressing blkid cpio"
+ cd "${TEMP}"
rm -rf "${TEMP}/initramfs-blkid-temp" > /dev/null
}
@@ -89,7 +95,8 @@ append_blkid(){
# mkdir -p "${TEMP}/initramfs-fuse-temp/lib/"
# tar -C "${TEMP}/initramfs-fuse-temp/lib/" -xjf "${FUSE_BINCACHE}"
# cd "${TEMP}/initramfs-fuse-temp/"
-# find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}"
+# find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}" \
+# || gen_die "compressing fuse cpio"
# rm -rf "${TEMP}/initramfs-fuse-temp" > /dev/null
#}
@@ -104,7 +111,9 @@ append_unionfs_fuse() {
gen_die 'Could not extract unionfs-fuse binary cache!'
chmod a+x "${TEMP}/initramfs-unionfs-fuse-temp/sbin/unionfs"
cd "${TEMP}/initramfs-unionfs-fuse-temp/"
- find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}"
+ find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}" \
+ || gen_die "compressing unionfs fuse cpio"
+ cd "${TEMP}"
rm -rf "${TEMP}/initramfs-unionfs-fuse-temp" > /dev/null
}
@@ -122,7 +131,8 @@ append_unionfs_fuse() {
# cp -f /etc/suspend.conf "${TEMP}/initramfs-suspend-temp/etc" ||
# gen_die 'Could not copy /etc/suspend.conf'
# cd "${TEMP}/initramfs-suspend-temp/"
-# find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}"
+# find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}" \
+# || gen_die "compressing suspend cpio"
# rm -r "${TEMP}/initramfs-suspend-temp/"
#}
@@ -175,7 +185,9 @@ append_multipath(){
cp /etc/scsi_id.config "${TEMP}/initramfs-multipath-temp/etc/" || gen_die 'could not copy scsi_id.config'
fi
cd "${TEMP}/initramfs-multipath-temp"
- find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}"
+ find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}" \
+ || gen_die "compressing multipath cpio"
+ cd "${TEMP}"
rm -r "${TEMP}/initramfs-multipath-temp/"
}
@@ -197,7 +209,9 @@ append_dmraid(){
ln -sf raid456.kp raid45.ko
cd "${TEMP}/initramfs-dmraid-temp/"
fi
- find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}"
+ find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}" \
+ || gen_die "compressing dmraid cpio"
+ cd "${TEMP}"
rm -r "${TEMP}/initramfs-dmraid-temp/"
}
@@ -214,7 +228,9 @@ append_iscsi(){
gen_die "Could not extract iscsi binary cache!"
chmod a+x "${TEMP}/initramfs-iscsi-temp/bin/iscsistart"
cd "${TEMP}/initramfs-iscsi-temp/"
- find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}"
+ find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}" \
+ || gen_die "compressing iscsi cpio"
+ cd "${TEMP}"
rm -rf "${TEMP}/initramfs-iscsi-temp" > /dev/null
}
@@ -228,16 +244,16 @@ append_lvm(){
mkdir -p "${TEMP}/initramfs-lvm-temp/etc/lvm/"
if [ -e '/sbin/lvm.static' ]
then
- print_info 1 ' LVM: Adding support (using local static binaries)...'
+ print_info 1 ' LVM: Adding support (using local static binary /sbin/lvm.static)...'
cp /sbin/lvm.static "${TEMP}/initramfs-lvm-temp/bin/lvm" ||
gen_die 'Could not copy over lvm!'
elif [ -e '/sbin/lvm' ] && LC_ALL="C" ldd /sbin/lvm|grep -q 'not a dynamic executable'
then
- print_info 1 ' LVM: Adding support (using local static binaries)...'
+ print_info 1 ' LVM: Adding support (using local static binary /sbin/lvm)...'
cp /sbin/lvm "${TEMP}/initramfs-lvm-temp/bin/lvm" ||
gen_die 'Could not copy over lvm!'
else
- print_info 1 ' LVM: Adding support (compiling binaries)...'
+ print_info 1 ' LVM: Adding support (compiling binaries)...'
compile_lvm
/bin/tar -jxpf "${LVM_BINCACHE}" -C "${TEMP}/initramfs-lvm-temp" ||
gen_die "Could not extract lvm binary cache!";
@@ -257,7 +273,9 @@ append_lvm(){
# fi
fi
cd "${TEMP}/initramfs-lvm-temp/"
- find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}"
+ find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}" \
+ || gen_die "compressing lvm cpio"
+ cd "${TEMP}"
rm -r "${TEMP}/initramfs-lvm-temp/"
}
@@ -270,7 +288,7 @@ append_evms(){
mkdir -p "${TEMP}/initramfs-evms-temp/etc/"
mkdir -p "${TEMP}/initramfs-evms-temp/bin/"
mkdir -p "${TEMP}/initramfs-evms-temp/sbin/"
- if [ "${EVMS}" -eq '1' ]
+ if [ "${EVMS}" = '1' ]
then
print_info 1 ' EVMS: Adding support...'
mkdir -p ${TEMP}/initramfs-evms-temp/lib
@@ -308,7 +326,9 @@ append_evms(){
done
fi
cd "${TEMP}/initramfs-evms-temp/"
- find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}"
+ find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}" \
+ || gen_die "compressing evms cpio"
+ cd "${TEMP}"
rm -r "${TEMP}/initramfs-evms-temp/"
}
@@ -319,13 +339,15 @@ append_mdadm(){
fi
cd ${TEMP}
mkdir -p "${TEMP}/initramfs-mdadm-temp/etc/"
- if [ "${MDADM}" -eq '1' ]
+ if [ "${MDADM}" = '1' ]
then
cp -a /etc/mdadm.conf "${TEMP}/initramfs-mdadm-temp/etc" \
|| gen_die "Could not copy mdadm.conf!"
fi
cd "${TEMP}/initramfs-mdadm-temp/"
- find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}"
+ find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}" \
+ || gen_die "compressing mdadm cpio"
+ cd "${TEMP}"
rm -rf "${TEMP}/initramfs-mdadm-temp" > /dev/null
}
@@ -352,6 +374,7 @@ append_splash(){
cd "${TEMP}/initramfs-splash-temp/"
find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}" \
|| gen_die "compressing splash cpio"
+ cd "${TEMP}"
rm -r "${TEMP}/initramfs-splash-temp/"
else
print_warning 1 ' >> No splash detected; skipping!'
@@ -360,7 +383,8 @@ append_splash(){
append_overlay(){
cd ${INITRAMFS_OVERLAY}
- find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}"
+ find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}" \
+ || gen_die "compressing overlay cpio"
}
append_luks() {
@@ -423,9 +447,29 @@ append_firmware() {
fi
find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}" \
|| gen_die "appending firmware to cpio"
+ cd "${TEMP}"
rm -r "${TEMP}/initramfs-firmware-temp/"
}
+append_gpg() {
+ if [ -d "${TEMP}/initramfs-gpg-temp" ]
+ then
+ rm -r "${TEMP}/initramfs-gpg-temp"
+ fi
+ cd ${TEMP}
+ mkdir -p "${TEMP}/initramfs-gpg-temp/sbin/"
+ if [ ! -e ${GPG_BINCACHE} ] ; then
+ print_info 1 ' GPG: Adding support (compiling binaries)...'
+ compile_gpg
+ fi
+ bzip2 -dc "${GPG_BINCACHE}" > "${TEMP}/initramfs-gpg-temp/sbin/gpg" ||
+ gen_die 'Could not extract gpg binary cache!'
+ chmod a+x "${TEMP}/initramfs-gpg-temp/sbin/gpg"
+ cd "${TEMP}/initramfs-gpg-temp/"
+ find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}"
+ rm -rf "${TEMP}/initramfs-gpg-temp" > /dev/null
+}
+
print_list()
{
local x
@@ -474,7 +518,8 @@ append_modules() {
print_list ${!group_modules} > "${TEMP}/initramfs-modules-${KV}-temp/etc/modules/${group}"
done
cd "${TEMP}/initramfs-modules-${KV}-temp/"
- find . | cpio ${CPIO_ARGS} --append -F "${CPIO}"
+ find . | cpio ${CPIO_ARGS} --append -F "${CPIO}" \
+ || gen_die "compressing modules cpio"
cd "${TEMP}"
rm -r "${TEMP}/initramfs-modules-${KV}-temp/"
}
@@ -579,7 +624,8 @@ append_auxilary() {
fi
cd "${TEMP}/initramfs-aux-temp/"
- find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}"
+ find . -print | cpio ${CPIO_ARGS} --append -F "${CPIO}" \
+ || gen_die "compressing auxilary cpio"
cd "${TEMP}"
rm -r "${TEMP}/initramfs-aux-temp/"
}
@@ -592,7 +638,7 @@ append_data() {
if [ $# -eq 1 ] || isTrue ${var}
then
print_info 1 " >> Appending ${name} cpio data..."
- ${func}
+ ${func} || gen_die "${func}() failed"
fi
}
@@ -614,8 +660,9 @@ create_initramfs() {
append_data 'mdadm' "${MDADM}"
append_data 'luks' "${LUKS}"
append_data 'multipath' "${MULTIPATH}"
+ append_data 'gpg' "${GPG}"
- if [ "${NORAMDISKMODULES}" -eq '0' ]
+ if [ "${NORAMDISKMODULES}" = '0' ]
then
append_data 'modules'
else
diff --git a/gen_package.sh b/gen_package.sh
index 60cbce0..a0a6bd0 100755
--- a/gen_package.sh
+++ b/gen_package.sh
@@ -31,7 +31,7 @@ gen_minkernpackage() {
if ! isTrue "${INTEGRATED_INITRAMFS}"
then
- [ "${BUILD_RAMDISK}" -ne 0 ] && { cp "${TMPDIR}/initramfs-${KV}" "${TEMP}/minkernpackage/initramfs-${ARCH}-${KV}" || gen_die 'Could not copy the initramfs for the kernel package!'; }
+ [ "${BUILD_RAMDISK}" != '0' ] && { cp "${TMPDIR}/initramfs-${KV}" "${TEMP}/minkernpackage/initramfs-${ARCH}-${KV}" || gen_die 'Could not copy the initramfs for the kernel package!'; }
fi
if [ "${KERNCACHE}" != "" ]
diff --git a/genkernel b/genkernel
index 1b0b8d6..6a3351f 100755
--- a/genkernel
+++ b/genkernel
@@ -2,7 +2,7 @@
# $Id$
PATH="${PATH}:/sbin:/usr/sbin"
-GK_V='3.4.10.908'
+GK_V='3.4.11.1'
# Set the default for TMPDIR. May be modified by genkernel.conf or the
# --tempdir command line option.
@@ -86,7 +86,7 @@ do
done
# Check if no action is specified...
-if [ "${BUILD_KERNEL}" -eq '0' -a "${BUILD_RAMDISK}" -eq '0' ]
+if [ "${BUILD_KERNEL}" = '0' -a "${BUILD_RAMDISK}" = '0' ]
then
usage
exit 1
@@ -200,7 +200,7 @@ then
gen_kerncache_is_valid
fi
-if [ ${BUILD_KERNEL} -eq '1' -a "${KERNCACHE_IS_VALID}" == "0" ]
+if [ ${BUILD_KERNEL} = '1' -a "${KERNCACHE_IS_VALID}" = '0' ]
then
# Configure kernel
config_kernel
@@ -217,12 +217,12 @@ then
compile_kernel
# Compile modules
- if [ ${BUILD_MODULES} -eq '1' -a ${BUILD_STATIC} -eq '0' ]
+ if [ "${BUILD_MODULES}" = '1' -a "${BUILD_STATIC}" = '0' ]
then
compile_modules
fi
- if [ ${SAVE_CONFIG} -eq '1' ]
+ if [ "${SAVE_CONFIG}" = '1' ]
then
print_info 1 "Copying config for successful build to /etc/kernels/kernel-config-${ARCH}-${KV}"
[ ! -e '/etc/kernels' ] && mkdir -p /etc/kernels
@@ -240,7 +240,7 @@ fi
if [ "${KERNCACHE}" != "" -a "${KERNCACHE_IS_VALID}" != "0" ]
then
- [ ${BUILD_STATIC} -eq '0' ] && gen_kerncache_extract_modules
+ [ "${BUILD_STATIC}" = '0' ] && gen_kerncache_extract_modules
gen_kerncache_extract_config
fi
@@ -254,13 +254,13 @@ then
CALLBACK_COUNT=0
trap "CALLBACK_ESCAPE=1" TERM KILL INT QUIT ABRT
- while [[ ${CALLBACK_ESCAPE} -eq '0' && ${CALLBACK_COUNT} -lt 5 ]]
+ while [[ "${CALLBACK_ESCAPE}" = '0' && ${CALLBACK_COUNT} -lt 5 ]]
do
sleep 1; echo -n '.';
let CALLBACK_COUNT=${CALLBACK_COUNT}+1
done
- if [ "${CALLBACK_ESCAPE}" -eq '0' ]
+ if [ "${CALLBACK_ESCAPE}" = '0' ]
then
echo
echo
@@ -268,7 +268,7 @@ then
CMD_STATUS="${PIPESTATUS[0]}"
echo
print_info 1 "<<< Callback exit status: ${CMD_STATUS}"
- [ "${CMD_STATUS}" -ne 0 ] && gen_die '--callback failed!'
+ [ "${CMD_STATUS}" != '0' ] && gen_die '--callback failed!'
else
echo
print_info 1 ">>> Callback cancelled..."
@@ -277,11 +277,11 @@ then
print_info 1 "" 1 0
fi
-if [ "${BUILD_RAMDISK}" -eq '1' ]
+if [ "${BUILD_RAMDISK}" = '1' ]
then
- [ "${DISKLABEL}" -eq '1' ] && compile_e2fsprogs
+ [ "${DISKLABEL}" = '1' ] && compile_e2fsprogs
- if [ "${BUSYBOX}" -eq '1' ]
+ if [ "${BUSYBOX}" = '1' ]
then
# Compile Busybox
compile_busybox
@@ -298,7 +298,7 @@ else
print_info 1 'initrd: Not building since only the kernel was requested...'
fi
-if isTrue "${INTEGRATED_INITRAMFS}" #|| [ ${BUILD_KERNEL} -eq '1' -a "${KERNCACHE_IS_VALID}" == "0" ]
+if isTrue "${INTEGRATED_INITRAMFS}" #|| [ "${BUILD_KERNEL}" = '1' -a "${KERNCACHE_IS_VALID}" == "0" ]
then
# We build the kernel a second time to include the initramfs
compile_kernel
@@ -311,14 +311,17 @@ fi
# Clean up...
[ -n "${CTEMP}" ] && rm -rf "${TEMP}"
-if [ "${BUILD_KERNEL}" -eq '1' ]
+if [ "${BUILD_KERNEL}" = '1' ]
then
- set_bootloader
+ if ! isTrue "${CMD_NOINSTALL}"
+ then
+ set_bootloader
+ fi
print_info 1 ''
print_info 1 "Kernel compiled successfully!"
print_info 1 ''
print_info 1 'Required Kernel Parameters:'
- if [ "${BUILD_RAMDISK}" -eq '0' ]
+ if [ "${BUILD_RAMDISK}" = '0' ]
then
print_info 1 ' root=/dev/$ROOT'
print_info 1 ' [ And "vga=0x317 splash=verbose" if you use a framebuffer ]'
@@ -338,17 +341,17 @@ then
fi
fi
-if [ "${BUILD_RAMDISK}" -eq '1' ]
+if [ "${BUILD_RAMDISK}" = '1' ]
then
echo
print_info 1 'WARNING... WARNING... WARNING...'
print_info 1 'Additional kernel cmdline arguments that *may* be required to boot properly...'
- [ "${SPLASH}" -eq '1' ] && print_info 1 "add \"vga=791 splash=silent,theme:${SPLASH_THEME} console=tty1 quiet\" if you use a splash framebuffer ]"
- [ "${LVM}" -eq '1' ] && print_info 1 'add "dolvm" for lvm support'
- [ "${EVMS}" -eq '1' ] && print_info 1 'add "doevms" for evms support'
- [ "${DMRAID}" -eq '1' ] && print_info 1 'add "dodmraid" for dmraid support'
- [ "${DMRAID}" -eq '1' ] && print_info 1 ' or "dodmraid=<additional options>"'
- [ "${ISCSI}" -eq '1' ] && print_info 1 'add at least "iscsi_initiatorname=<initiator name> iscsi_target=<target name> and iscsi_address=<target ip>" for iscsi support'
+ [ "${SPLASH}" = '1' ] && print_info 1 "add \"vga=791 splash=silent,theme:${SPLASH_THEME} console=tty1 quiet\" if you use a splash framebuffer ]"
+ [ "${LVM}" = '1' ] && print_info 1 'add "dolvm" for lvm support'
+ [ "${EVMS}" = '1' ] && print_info 1 'add "doevms" for evms support'
+ [ "${DMRAID}" = '1' ] && print_info 1 'add "dodmraid" for dmraid support'
+ [ "${DMRAID}" = '1' ] && print_info 1 ' or "dodmraid=<additional options>"'
+ [ "${ISCSI}" = '1' ] && print_info 1 'add at least "iscsi_initiatorname=<initiator name> iscsi_target=<target name> and iscsi_address=<target ip>" for iscsi support'
fi
[ "${BOOTRW}" != '' ] && mount -o remount,ro ${BOOTDIR}
diff --git a/genkernel.8 b/genkernel.8
deleted file mode 100644
index 4dba331..0000000
--- a/genkernel.8
+++ /dev/null
@@ -1,329 +0,0 @@
-.TH GENKERNEL "8" "June 2006" "genkernel 3.3" "Gentoo Linux"
-.SH NAME
-genkernel \- the Gentoo Linux automatic kernel compiler.
-.SH SYNOPSIS
-\fBgenkernel\fR \fI[options...] action\fR
-.SH INTRODUCTION
-Genkernel is designed to allow users who are not previously used to
-compiling a kernel to use a similar setup to that one that is used on
-the Gentoo LiveCDs which auto-detects your hardware.
-.PP
-Some users may also be interested in using genkernel for hardware
-which requires initialization and a working kernel before it can be
-booted because genkernel also automatically compiles your kernel
-modules, allowing hardware which needs to be loaded with module
-parameters to be used.
-.SH USAGE
-All that is needed to run genkernel is just ``genkernel'' with an action
-and any flags you might need:
-.PP
-# genkernel --menuconfig --no-clean --no-install all
-.PP
-This would produce a kernel, asking you what how to configure it
-to your desire, leaving alone any existing compiled object files, but not
-installing anything.
-.SH ACTIONS
-An action tells genkernel what you want it to do - the following
-actions are supported:
-.PP
-.I \fBall\fR
-.RS
-Build all steps - the kernel, modules, and the ramdisk.
-.RE
-.I \fBbzImage\fR
-.RS
-Build only the kernel.
-.RE
-.I \fBkernel\fR
-.RS
-Build only the kernel and the modules.
-.RE
-.I \fBinitramfs\fR
-.RS
-Build only the ramdisk.
-.RE
-.SH OPTIONS
-Genkernel supports the following options which alter its
-behaviour. Certain options have ``\fB--no-\fR'' variants which
-do the opposite thing. You can specify your options in any order.
-.PP
-.BR Debugging \ Options
-.TP
-\fB\-\-loglevel=\fR<0-5>
-This controls the out verbosity level of genkernel output - if this is set
-to 0, minimal debugging is done; if this is set to 5 as much output as
-possible is given.
-.TP
-\fB\-\-logfile=\fR<outfile>
-This outputs debugging data to the file <outfile>. By default this is
-.I /var/log/genkernel.log\fR.
-.TP
-\fB\-\-\fR[no\-]\fBcolor\fR
-Turns on, or off, output in color using escape sequences.
-.PP
-.BR Kernel \ Configuration
-.TP
-\fB\-\-\fR[no\-]\fBmenuconfig\fR
-Runs, or does not run "make menuconfig" after running "make oldconfig".
-.TP
-\fB\-\-\fR[no\-]\fBsave\-config\fR
-Saves, or does not save the kernel configuration to
-.I /etc/kernels
-if the kernel is successfully compiled.
-.TP
-\fB\-\-gconfig\fR
-Run "make gconfig" after "make oldconfig".
-.TP
-\fB\-\-xconfig\fR
-Run "make xconfig" after "make oldconfig".
-.PP
-.BR Kernel \ Compilation
-.TP
-\fB\-\-\fR[no\-]\fBclean\fR
-Runs, or does not run, "make clean" before compilation - this erases any
-compiled object files in the kernel source tree but does not have an impact
-on the kernel configuration. Specifying \fB\-\-no\-clean\fR implies
-\fB\-\-no\-mrproper\fR.
-.TP
-\fB\-\-\fR[no\-]\fBmrproper\fR
-Runs, or does not run, "make mrproper" before compilation - this erases both
-any compiled object files in the kernel source tree as well as the kernel
-configuration.
-.TP
-\fB\-\-\fR[no\-]\fBinstall\fR
-Installs, or does not install the kernel to
-.I /boot
-after building. The default is --install. If MOUNTBOOT is set in
-.I /etc/genkernel.conf
-then
-.I /boot
-will be automatically mounted if it is
-not already mounted before the ramdisk and kernel images are copied over.
-.TP
-\fB\-\-\fR[no\-]\fBsymlink\fR
-Manages, or does not manage, symlinks in
-.I /boot
-like the manual kernel "make install" process does. A
-.I kernel
-(or, depending on options,
-.I kernelz\fR)
-symlink will link to the most recently built kernel image and a
-.I kernel.old
-(or
-.I kernelz.old\fR)
-symlink will link to the second most recently built image, if one exists.
-Similar symlinks (both * and *.old) are managed for
-.I initramfs\fR
-and
-.I System.map\f.
-The corresponding work products (i.e., the actual kernel and initamfs images,
-and System.map) are also managed accordingly. NOTE: Specifying --symlink
-does nothing unless --install is also specified.
-.TP
-\fB\-\-no\-initrdmodules\fR
-Don't copy any modules to the ramdisk.
-.TP
-\fB\-\-oldconfig\fR
-Implies \fB\-\-no\-clean\fR, and thus \fB\-\-no\-mrproper\fR, running a
-"make oldconfig".
-.TP
-\fB\-\-callback=\fR<...>
-Run the specified arguments in the current environment after the kernel and
-modules have been compiled.
-.PP
-.BR Kernel \ Locations
-.TP
-\fB\-\-kerneldir=\fR<dir>
-This specifies the location of the kernel sources; the default is
-/usr/src/linux.
-.TP
-\fB\-\-kernel\-config=\fR<file>
-This specifies a kernel configuration file to use for compilation; by
-default genkernel uses the config from the previous build of the same kernel
-version or a default kernel config if there isn't a previous config.
-.PP
-.BR Low-Level \ Compilation \ Options
-.TP
-\fB\-\-kernel\-cc=\fR<compiler>
-Compiler to use for the kernel compilation (e.g. distcc).
-.TP
-\fB\-\-kernel\-as=\fR<assembler>
-Assembler to use for the kernel compilation.
-.TP
-\fB\-\-kernel\-ld=\fR<linker>
-Linker to use for the kernel compilation.
-.TP
-\fB\-\-kernel\-make=\fR<makeprg>
-GNU Make to use for the kernel compilation.
-.TP
-\fB\-\-utils\-cc=\fR<compiler>
-Compiler to use for utilities.
-.TP
-\fB\-\-utils\-as=\fR<assembler>
-Assembler to use for utilities.
-.TP
-\fB\-\-utils\-ld=\fR<linker>
-Linker to use for utilities.
-.TP
-\fB\-\-utils\-make=\fR<makeprog>
-GNU Make to use for utilities.
-.TP
-\fB\-\-makeopts=\fR<makeopts>
-GNU Make options such as \fB\-j2\fR, etc.
-.PP
-.BR Initialization
-.TP
-\fB\-\-\fR[no\-]\fBsplash=\fR<theme>
-If the extra argument is specified, splash is forced using <theme>
-rather than the default theme specified in your splash
-configuration. If \fB\-\-no-splash\fR is specified, then
-splash is disabled.
-.TP
-\fB\-\-splash-res=\fR<resolutions>
-Optionally select splash resolutions to include.
-.TP
-\fB\-\-do\-keymap\-auto\fR
-Force keymap selection at boot.
-.TP
-\fB\-\-dmraid\fR
-Add DMRAID support.
-.TP
-\fB\-\-evms\fR
-Add in EVMS support from static binaries if they exist on the system:
-you should run "emerge evms" first.
-.TP
-\fB\-\-lvm\fR
-.RS
-Add in LVM support from static binaries if they exist on the system,
-or compile static LVM binaries if static ones do not exist.
-.RE
-.TP
-\fB\-\-luks\fR
-.RS
-Add in Luks support from static binaries if they exist on the
-system.
-.RE
-.TP
-\fB\-\-static\fR
-This builds a monolithic kernel without any modules on any initial ramdisks.
-.TP
-\fB\-\-linuxrc=\fR<file>
-Use <file> for the linuxrc instead of the genkernel linuxrc.
-.PP
-.BR Internals
-.TP
-\fB\-\-arch\-override=\fR<arch>
-Force the architecture settings described by the <arch> profile
-instead of autodetecting the running architecture.
-.TP
-\fB\-\-tempdir=\fR<dir>
-Sets genkernel's temporary working directory to <dir>.
-.PP
-.BR Output \ Settings
-.TP
-\fB\-\-kernname=\fR<...>
-Tag the kernel and initrd with a name, if not defined this option defaults to genkernel
-.TP
-\fB\-\-minkernpackage=\fR<tbz2>
-File to output a .tar.bz2'd kernel and initrd: no modules outside of the
-initrd will be included...
-.TP
-\fB\-\-modulespackage=\fR<tbz2>
-File to output a .tar.bz2'd modules after the callbacks have run
-.TP
-\fB\-\-kerncache=\fR<tbz2>
-File to output a .tar.bz2'd kernel, contents of /lib/modules/ and the kernel config.
-\fBNOTE\fR: This is created before the callbacks are run.
-.TP
-\fB\-\-no\-kernel\-sources=\fR<tbz2>
-This option is only valid if kerncache is defined
-If there is a valid kerncache no checks will be made
-against a kernel source tree.
-.TP
-\fB\-\-initramfs\-overlay=\fR<dir>
-Directory structure to include in the initramfs,
-only available on 2.6 kernels
-.SH RAMDISK OPTIONS
-The following options can be passed as kernel parameters from the
-bootloader, which the ramdisk scripts would recognize.
-.TP
-\fBreal_root=\fR<...>
-Specifies the device node of the root filesystem to mount.
-.TP
-\fBcrypt_root=\fR<...>
-This specifies the device encrypted by Luks, which contains the root
-filesystem to mount.
-.TP
-\fBcrypt_swap=\fR<...>
-This specifies the swap device encrypted by Luks.
-.TP
-\fBroot_key=\fR<...>
-In case your root is encrypted with a key, you can use a device like a usb pen to store the key.
-This value should be the key path relative to the mount point.
-.TP
-\fBroot_keydev=\fR<...>
-If necessary provide the name of the device that carries the root_key.
-If unset while using root_key, it will automatically look for the device in every boot.
-.TP
-\fBswap_key=\fR<...>
-Same as root_key for swap.
-.TP
-\fBswap_keydev=\fR<...>
-Same as root_keydev for swap.
-.TP
-\fBcrypt_silent\fR
-Set this to silent all the output related to the cryptographic software, and in case your encrypted device isn't open with the key, it opens a shell in the initrd quietly.
-.TP
-\fBdodmraid=\fR<...>
-Passes arguments to dmraid on bootup.
-.TP
-\fBreal_init=\fR<...>
-Passes arguments to init on bootup.
-.TP
-\fBscandelay=\fR<...>
-Pauses for 10 seconds before running devfsd if no argument is specified;
-otherwise pauses for the number of specified seconds.
-.TP
-\fBip=\fR<...>
-Normally used to tell the kernel that it should start a network interface. If present, the initrd will try to mount a livecd over NFS.
-.TP
-\fBnfsroot=\fR<...>
-If present, the initrd will try to mount a livecd from that location. Otherwise the location will be deduced from the DCHP request (option root\-path)
-.TP
-\fBdoevms\fR
-Activate EVMS volumes on bootup
-.TP
-\fBdolvm\fR
-Activate LVM volumes on bootup
-.TP
-\fBdoscsi\fR
-Activate SCSI devices on bootup, necessary when SCSI support is compiled as modules and you're using SCSI or SATA devices.
-
-.SH NETBOOTING
-The initrd scripts have limited support for network booting.
-This is activated if the ip=<...> kernel parameter was given. Please refer to the genkernel guide at http://www.gentoo.org/doc/en/genkernel.xml for more information.
-
-The initrd scripts will extract any *.tar.gz files found in the \fB/add\fR directory of the livecd into the root filesystem during boot. This way it is easy to extend a netbooted LiveCD i.e. add custom tools, or other kernel modules.
-.SH REPORTING BUGS
-If you believe you have found a bug in the genkernel scripts, then please
-file a bug on the Gentoo Linux Bugzilla:
-.I http://bugs.gentoo.org\fR,
-assigning your bug to genkernel@gentoo.org. We cannot assist you
-with kernel compilation failures unless they are caused by a genkernel
-bug.
-.PP
-Kernel issues for Gentoo-supported kernels, including compilation
-failures should go to
-.I http://bugs.gentoo.org
-and should be assigned to kernel@gentoo.org. Please check if an
-existing bug documents the same issue before opening a new bug. Issues
-for kernel sources not supported by Gentoo should go to their relevant
-authors.
-.SH AUTHORS
-.nf
-Tim Yamin <plasmaroo@gentoo.org>
-Eric Edgar <rocket@gentoo.org>
-NFS Support by Thomas Seiler <thseiler@gmail.com>
-.fi
-.SH SEE ALSO
-\fB/etc/genkernel.conf\fR \- genkernel configuration file
diff --git a/genkernel.conf b/genkernel.conf
index a71ce69..2bc8183 100644
--- a/genkernel.conf
+++ b/genkernel.conf
@@ -53,6 +53,12 @@ USECOLOR="yes"
# compile static LVM binaries if static ones do not exist.
# LVM="no"
+# Add in Luks support. Needs sys-fs/cryptsetup with -dynamic installed.
+# LUKS="no"
+
+# Add in GnuPG support
+# GPG="no"
+
# Add in EVMS support from static binaries if they exist on the system: you
# should run "emerge evms" first.
# EVMS="no"
@@ -130,7 +136,7 @@ DISKLABEL="yes"
#BOOTDIR="/boot"
# Default share directory location
-GK_SHARE="/usr/share/genkernel"
+GK_SHARE="${GK_SHARE:-/usr/share/genkernel}"
# Location of the default cache
CACHE_DIR="/var/cache/genkernel"
@@ -151,6 +157,7 @@ BUSYBOX_VER="VERSION_BUSYBOX"
BUSYBOX_SRCTAR="${DISTDIR}/busybox-${BUSYBOX_VER}.tar.bz2"
BUSYBOX_DIR="busybox-${BUSYBOX_VER}"
BUSYBOX_BINCACHE="%%CACHE%%/busybox-${BUSYBOX_VER}-%%ARCH%%.tar.bz2"
+# BUSYBOX_APPLETS="[ ash sh mount uname echo cut cat"
DEVICE_MAPPER_VER="VERSION_DMAP"
DEVICE_MAPPER_DIR="device-mapper.${DEVICE_MAPPER_VER}"
@@ -186,3 +193,8 @@ UNIONFS_FUSE_VER="VERSION_UNIONFS_FUSE"
UNIONFS_FUSE_DIR="unionfs-fuse-${UNIONFS_FUSE_VER}"
UNIONFS_FUSE_SRCTAR="${DISTDIR}/unionfs-fuse-${UNIONFS_FUSE_VER}.tar.bz2"
UNIONFS_FUSE_BINCACHE="%%CACHE%%/unionfs-fuse-${UNIONFS_FUSE_VER}-%%ARCH%%.bz2"
+
+GPG_VER="VERSION_GPG"
+GPG_DIR="gnupg-${GPG_VER}"
+GPG_SRCTAR="${DISTDIR}/gnupg-${GPG_VER}.tar.bz2"
+GPG_BINCACHE="%%CACHE%%/gnupg-${GPG_VER}-%%ARCH%%.bz2"
diff --git a/maintenance/docmatcher.py b/maintenance/docmatcher.py
new file mode 100644
index 0000000..4b6b94e
--- /dev/null
+++ b/maintenance/docmatcher.py
@@ -0,0 +1,281 @@
+#! /usr/bin/python
+# Copyright (C) 2010 Gentoo Foundation
+# Written by Sebastian Pipping <sebastian@pipping.org>
+# Licensed under GPL v2 or later
+
+from __future__ import print_function
+import re
+import sys
+import os
+
+
+NON_VARIABLES = ('UTF', 'USE', 'TCP', 'SMP', 'PXE', 'PPC', 'MAC',
+ 'GTK', 'GNU', 'CPU', 'DOS', 'NIC', 'NFS', 'ISO', 'TIMEOUT',
+ 'TFTP', 'SYSTEM', 'SPARC', 'RAID', 'LABEL', 'PROMPT', 'KERNEL',
+ 'GRP', 'DOCTYPE', 'DHCP', 'DEFAULT', 'ATARAID', 'APPEND')
+
+EXTRA_VARIABLES = ['ARCH_OVERRIDE', 'BOOTLOADER', 'CLEAR_CACHE_DIR', 'DEFAULT_KERNEL_SOURCE', 'DISTDIR', 'GK_SHARE', 'BUSYBOX_APPLETS']
+for app in ('DEVICE_MAPPER', 'UNIONFS_FUSE', 'BUSYBOX', 'DMRAID', 'LVM', 'ISCSI', 'FUSE', 'GPG'):
+ for prop in ('DIR', 'SRCTAR', 'VER'):
+ EXTRA_VARIABLES.append('%s_%s' % (app, prop))
+EXTRA_VARIABLES = tuple(EXTRA_VARIABLES)
+
+IGNORE_OPTIONS = ('help', 'version')
+
+
+def exract_gen_cmdline_sh():
+ f = open('gen_cmdline.sh', 'r')
+ gen_cmdline_sh = f.read()
+ f.close()
+
+ usage_lines = list()
+ parsing_lines = list()
+ dest = None
+
+ for line in gen_cmdline_sh.split('\n'):
+ if line in ('longusage() {', 'usage() {'):
+ dest = usage_lines
+ elif line == 'parse_cmdline() {':
+ dest = parsing_lines
+
+ if dest is not None:
+ dest.append(line)
+
+ if line == '}':
+ dest = None
+
+ del gen_cmdline_sh
+
+
+ parsing_code = '\n'.join(parsing_lines)
+ del parsing_lines
+
+ gen_cmdline_sh_parsing_long_params = set()
+ for match in re.finditer('--([a-z][a-z0-9-]+)', parsing_code):
+ para_name = match.group(1)
+ if para_name in IGNORE_OPTIONS:
+ continue
+ gen_cmdline_sh_parsing_long_params.add(para_name)
+
+ gen_cmdline_sh_variables = set()
+ for match in re.finditer('^\s*([A-Z_]+)=', parsing_code, re.MULTILINE):
+ var_name = match.group(1)
+ if var_name.startswith('CMD_'):
+ continue
+ gen_cmdline_sh_variables.add(var_name)
+
+ del parsing_code
+
+
+ gen_cmdline_sh_usage_long_params = set()
+ for match in re.finditer('--([a-z][a-z0-9-]+)', '\n'.join(usage_lines)):
+ para_name = match.group(1)
+ if para_name in IGNORE_OPTIONS:
+ continue
+ gen_cmdline_sh_usage_long_params.add(para_name)
+ del usage_lines
+
+ return gen_cmdline_sh_parsing_long_params, gen_cmdline_sh_usage_long_params, gen_cmdline_sh_variables
+
+
+def extract_genkernel_8_txt():
+ f = open(os.path.join('doc', 'genkernel.8.txt'), 'r')
+ genkernel_8_txt = f.read()
+ f.close()
+
+ # Preprocess
+ genkernel_8_txt = genkernel_8_txt.replace('*[*no-*]*','[no-]')
+
+ yes_no = re.compile('^\\[(no-)\\]([a-z0-9-]+)$')
+
+ genkernel_8_txt_long_params = set()
+ for match in re.finditer('--((?:[a-z]|\\[no-\\])[a-z0-9-]+)', genkernel_8_txt):
+ para_name = match.group(1)
+
+ # Black list
+ if para_name == 'no-':
+ continue
+
+ m = yes_no.match(para_name)
+ if m:
+ p_yes = m.group(2)
+ p_no = m.group(1) + m.group(2)
+ genkernel_8_txt_long_params.add(p_yes)
+ genkernel_8_txt_long_params.add(p_no)
+ else:
+ genkernel_8_txt_long_params.add(para_name)
+
+ del genkernel_8_txt
+
+ return genkernel_8_txt_long_params
+
+
+def extract_genkernel_xml(genkernel_xml_path, variables_blacklist):
+ f = open(genkernel_xml_path, 'r')
+ genkernel_xml = f.read()
+ f.close()
+
+ # Preprocess
+ genkernel_xml = genkernel_xml.replace('<c>','').replace('</c>','').replace('<b>','').replace('</b>','')
+
+ yes_no = re.compile('^(no-)([a-z0-9-]+)$')
+
+ genkernel_xml_long_params = set()
+ for match in re.finditer('--([a-z][a-z0-9-]+)', genkernel_xml):
+ para_name = match.group(1)
+
+ if para_name in IGNORE_OPTIONS:
+ continue
+
+ # Fix doc error "--no install"
+ if para_name == 'no':
+ para_name = 'no-install'
+
+ m = yes_no.match(para_name)
+ if m and para_name != 'no-ramdisk-modules':
+ p_yes = m.group(2)
+ p_no = m.group(1) + m.group(2)
+ genkernel_xml_long_params.add(p_yes)
+ genkernel_xml_long_params.add(p_no)
+ else:
+ genkernel_xml_long_params.add(para_name)
+
+ genkernel_xml_variables = set()
+ for match in re.finditer('[A-Z_]{3,}', genkernel_xml):
+ var_name = match.group(0)
+ if var_name in variables_blacklist:
+ continue
+ genkernel_xml_variables.add(var_name)
+
+ del genkernel_xml
+
+ return genkernel_xml_long_params, genkernel_xml_variables
+
+
+def extract_gen_determineargs_sh():
+ f = open('gen_determineargs.sh', 'r')
+ gen_determineargs_sh = f.read()
+ f.close()
+
+ gen_determineargs_sh_variables = set()
+ for match in re.finditer('set_config_with_override\s+[0-9]+\s+([A-Z_]+)', gen_determineargs_sh):
+ var_name = match.group(1)
+ gen_determineargs_sh_variables.add(var_name)
+
+ for match in re.finditer('([A-Z_]+)=`(?:arch|cache)_replace "\\$\\{\\1\\}"`', gen_determineargs_sh):
+ var_name = match.group(1)
+ gen_determineargs_sh_variables.add(var_name)
+
+ del gen_determineargs_sh
+
+ return gen_determineargs_sh_variables
+
+
+def extract_genkernel_conf(variables_blacklist):
+ f = open('genkernel.conf', 'r')
+ genkernel_conf = f.read()
+ f.close()
+
+ genkernel_conf_variables = set()
+ for match in re.finditer('^#*\\s*([A-Z_]{3,})', genkernel_conf, re.MULTILINE):
+ var_name = match.group(1)
+ if var_name in variables_blacklist:
+ continue
+ genkernel_conf_variables.add(var_name)
+
+ del genkernel_conf
+
+ return genkernel_conf_variables
+
+
+def print_set(s):
+ if s:
+ print('\n'.join(('- ' + e) for e in sorted(s)))
+ else:
+ print(' NONE')
+ print()
+
+
+def usage():
+ print('USAGE: %s GENTOO/xml/htdocs/doc/en/genkernel.xml' % os.path.basename(sys.argv[0]))
+
+
+def main():
+ if len(sys.argv) != 2:
+ usage()
+ sys.exit(1)
+
+ gen_cmdline_sh_parsing_long_params, gen_cmdline_sh_usage_long_params, gen_cmdline_sh_variables = exract_gen_cmdline_sh()
+ genkernel_8_txt_long_params = extract_genkernel_8_txt()
+ gen_determineargs_sh_variables = extract_gen_determineargs_sh()
+
+ variables_blacklist = set(NON_VARIABLES).difference(gen_determineargs_sh_variables)
+ known_variales = set(EXTRA_VARIABLES).union(gen_determineargs_sh_variables).union(gen_cmdline_sh_variables)
+
+ genkernel_xml_long_params, genkernel_xml_variables = extract_genkernel_xml(sys.argv[1], variables_blacklist)
+ genkernel_conf_variables = extract_genkernel_conf(variables_blacklist)
+
+
+ # Status quo
+ print('Options used by parser in *gen_cmdline.sh*:')
+ print_set(gen_cmdline_sh_parsing_long_params)
+
+ print('Options mentioned in usage of *gen_cmdline.sh*:')
+ print_set(gen_cmdline_sh_usage_long_params)
+
+ print('Options mentioned in *man page*:')
+ print_set(genkernel_8_txt_long_params)
+
+ print('Options mentioned in *web page*:')
+ print_set(genkernel_xml_long_params)
+
+
+ print('Variables set by *gen_cmdline.sh*:')
+ print_set(gen_cmdline_sh_variables)
+
+ print('Variables read by *gen_determineargs.sh*:')
+ print_set(gen_determineargs_sh_variables)
+
+ print('Variables mentioned in *web page*:')
+ print_set(genkernel_xml_variables)
+
+ print('Variables used in *genkernel.conf*:')
+ print_set(genkernel_conf_variables)
+
+
+ # Future work (due extensions)
+ print('Options missing from the *man page*:')
+ print_set(gen_cmdline_sh_parsing_long_params.difference(genkernel_8_txt_long_params))
+
+ print('Options missing from *--help*:')
+ print_set(gen_cmdline_sh_parsing_long_params.difference(gen_cmdline_sh_usage_long_params))
+
+ print('Options missing from *web page*:')
+ print_set(gen_cmdline_sh_parsing_long_params.difference(genkernel_xml_long_params))
+
+ print('Variables missing from *web page*:')
+ print_set(known_variales.difference(genkernel_xml_variables))
+
+ print('Variables missing from *genkernel.conf*:')
+ print_set(known_variales.difference(genkernel_conf_variables))
+
+
+ # Future work (due removal and updates)
+ print('Removed options still mentioned in the *man page*:')
+ print_set(genkernel_8_txt_long_params.difference(gen_cmdline_sh_parsing_long_params))
+
+ print('Removed options still mentioned in *--help*:')
+ print_set(gen_cmdline_sh_usage_long_params.difference(gen_cmdline_sh_parsing_long_params))
+
+ print('Removed options still mentioned in *web page*:')
+ print_set(genkernel_xml_long_params.difference(gen_cmdline_sh_parsing_long_params))
+
+ print('Removed variables still mentioned in *web page*:')
+ print_set(genkernel_xml_variables.difference(known_variales))
+
+ print('Removed variables still mentioned in *genkernel.conf*:')
+ print_set(genkernel_conf_variables.difference(known_variales))
+
+
+if __name__ == '__main__':
+ main()
diff --git a/patches/busybox/1.18.1/1.18.1-mdadm.diff b/patches/busybox/1.18.1/1.18.1-mdadm.diff
new file mode 100644
index 0000000..0f3107e
--- /dev/null
+++ b/patches/busybox/1.18.1/1.18.1-mdadm.diff
@@ -0,0 +1,5874 @@
+Based on:
+
+> Forward-port the mdadm tool from the Gentoo Busybox-1.1.3.
+> Should handle all types of metadata 0.90, 1.0, 1.1, 1.2.
+> If /etc/mdadm.conf does not exist in the initrd, it is created first, by
+> scanning devices, and then it is used.
+
+--- a/Config.in 2010-12-21 06:31:04.000000000 +0200
++++ mdadm/Config.in 2011-01-12 21:33:01.000000000 +0200
+@@ -749,6 +749,7 @@ source findutils/Config.in
+ source init/Config.in
+ source loginutils/Config.in
+ source e2fsprogs/Config.in
++source mdadm/Config.in
+ source modutils/Config.in
+ source util-linux/Config.in
+ source miscutils/Config.in
+--- a/include/applets.src.h 2010-12-21 06:31:04.000000000 +0200
++++ mdadm/include/applets.src.h 2011-01-12 21:33:01.000000000 +0200
+@@ -206,6 +206,7 @@ IF_KILLALL5(APPLET_ODDNAME(killall5, kil
+ IF_KLOGD(APPLET(klogd, _BB_DIR_SBIN, _BB_SUID_DROP))
+ IF_LAST(APPLET(last, _BB_DIR_USR_BIN, _BB_SUID_DROP))
+ IF_LENGTH(APPLET_NOFORK(length, length, _BB_DIR_USR_BIN, _BB_SUID_DROP, length))
++IF_MDADM(APPLET(mdadm, _BB_DIR_SBIN, _BB_SUID_DROP))
+ IF_LESS(APPLET(less, _BB_DIR_USR_BIN, _BB_SUID_DROP))
+ IF_SETARCH(APPLET_ODDNAME(linux32, setarch, _BB_DIR_BIN, _BB_SUID_DROP, linux32))
+ IF_SETARCH(APPLET_ODDNAME(linux64, setarch, _BB_DIR_BIN, _BB_SUID_DROP, linux64))
+--- a/include/usage.src.h 2010-12-21 06:29:45.000000000 +0200
++++ mdadm/include/usage.src.h 2011-01-12 21:33:01.000000000 +0200
+@@ -2404,6 +2404,11 @@ INSERT
+ "\n -w Warn about improperly formatted checksum lines" \
+ )
+
++#define mdadm_trivial_usage \
++ ""
++#define mdadm_full_usage \
++ "Assemble or Examine the mdadm arrays."
++
+ #define mdev_trivial_usage \
+ "[-s]"
+ #define mdev_full_usage "\n\n" \
+--- a/Makefile 2010-12-21 06:31:43.000000000 +0200
++++ mdadm/Makefile 2011-01-12 21:33:01.000000000 +0200
+@@ -478,6 +478,7 @@ libs-y := \
+ loginutils/ \
+ mailutils/ \
+ miscutils/ \
++ mdadm/ \
+ modutils/ \
+ networking/ \
+ networking/libiproute/ \
+--- a/mdadm/bitmap.h 1970-01-01 03:00:00.000000000 +0300
++++ mdadm/mdadm/bitmap.h 2011-01-12 21:33:01.000000000 +0200
+@@ -0,0 +1,287 @@
++/*
++ * bitmap.h: Copyright (C) Peter T. Breuer (ptb@ot.uc3m.es) 2003
++ *
++ * additions: Copyright (C) 2003-2004, Paul Clements, SteelEye Technology, Inc.
++ */
++#ifndef BITMAP_H
++#define BITMAP_H 1
++
++#define BITMAP_MAJOR_LO 3
++/* version 4 insists the bitmap is in little-endian order
++ * with version 3, it is host-endian which is non-portable
++ */
++#define BITMAP_MAJOR_HI 4
++#define BITMAP_MAJOR_HOSTENDIAN 3
++
++#define BITMAP_MINOR 39
++
++/*
++ * in-memory bitmap:
++ *
++ * Use 16 bit block counters to track pending writes to each "chunk".
++ * The 2 high order bits are special-purpose, the first is a flag indicating
++ * whether a resync is needed. The second is a flag indicating whether a
++ * resync is active.
++ * This means that the counter is actually 14 bits:
++ *
++ * +--------+--------+------------------------------------------------+
++ * | resync | resync | counter |
++ * | needed | active | |
++ * | (0-1) | (0-1) | (0-16383) |
++ * +--------+--------+------------------------------------------------+
++ *
++ * The "resync needed" bit is set when:
++ * a '1' bit is read from storage at startup.
++ * a write request fails on some drives
++ * a resync is aborted on a chunk with 'resync active' set
++ * It is cleared (and resync-active set) when a resync starts across all drives
++ * of the chunk.
++ *
++ *
++ * The "resync active" bit is set when:
++ * a resync is started on all drives, and resync_needed is set.
++ * resync_needed will be cleared (as long as resync_active wasn't already set).
++ * It is cleared when a resync completes.
++ *
++ * The counter counts pending write requests, plus the on-disk bit.
++ * When the counter is '1' and the resync bits are clear, the on-disk
++ * bit can be cleared aswell, thus setting the counter to 0.
++ * When we set a bit, or in the counter (to start a write), if the fields is
++ * 0, we first set the disk bit and set the counter to 1.
++ *
++ * If the counter is 0, the on-disk bit is clear and the stipe is clean
++ * Anything that dirties the stipe pushes the counter to 2 (at least)
++ * and sets the on-disk bit (lazily).
++ * If a periodic sweep find the counter at 2, it is decremented to 1.
++ * If the sweep find the counter at 1, the on-disk bit is cleared and the
++ * counter goes to zero.
++ *
++ * Also, we'll hijack the "map" pointer itself and use it as two 16 bit block
++ * counters as a fallback when "page" memory cannot be allocated:
++ *
++ * Normal case (page memory allocated):
++ *
++ * page pointer (32-bit)
++ *
++ * [ ] ------+
++ * |
++ * +-------> [ ][ ]..[ ] (4096 byte page == 2048 counters)
++ * c1 c2 c2048
++ *
++ * Hijacked case (page memory allocation failed):
++ *
++ * hijacked page pointer (32-bit)
++ *
++ * [ ][ ] (no page memory allocated)
++ * counter #1 (16-bit) counter #2 (16-bit)
++ *
++ */
++
++#ifdef __KERNEL__
++
++#define PAGE_BITS (PAGE_SIZE << 3)
++#define PAGE_BIT_SHIFT (PAGE_SHIFT + 3)
++
++typedef __u16 bitmap_counter_t;
++#define COUNTER_BITS 16
++#define COUNTER_BIT_SHIFT 4
++#define COUNTER_BYTE_RATIO (COUNTER_BITS / 8)
++#define COUNTER_BYTE_SHIFT (COUNTER_BIT_SHIFT - 3)
++
++#define NEEDED_MASK ((bitmap_counter_t) (1 << (COUNTER_BITS - 1)))
++#define RESYNC_MASK ((bitmap_counter_t) (1 << (COUNTER_BITS - 2)))
++#define COUNTER_MAX ((bitmap_counter_t) RESYNC_MASK - 1)
++#define NEEDED(x) (((bitmap_counter_t) x) & NEEDED_MASK)
++#define RESYNC(x) (((bitmap_counter_t) x) & RESYNC_MASK)
++#define COUNTER(x) (((bitmap_counter_t) x) & COUNTER_MAX)
++
++/* how many counters per page? */
++#define PAGE_COUNTER_RATIO (PAGE_BITS / COUNTER_BITS)
++/* same, except a shift value for more efficient bitops */
++#define PAGE_COUNTER_SHIFT (PAGE_BIT_SHIFT - COUNTER_BIT_SHIFT)
++/* same, except a mask value for more efficient bitops */
++#define PAGE_COUNTER_MASK (PAGE_COUNTER_RATIO - 1)
++
++#define BITMAP_BLOCK_SIZE 512
++#define BITMAP_BLOCK_SHIFT 9
++
++/* how many blocks per chunk? (this is variable) */
++#define CHUNK_BLOCK_RATIO(bitmap) ((bitmap)->chunksize >> BITMAP_BLOCK_SHIFT)
++#define CHUNK_BLOCK_SHIFT(bitmap) ((bitmap)->chunkshift - BITMAP_BLOCK_SHIFT)
++#define CHUNK_BLOCK_MASK(bitmap) (CHUNK_BLOCK_RATIO(bitmap) - 1)
++
++/* when hijacked, the counters and bits represent even larger "chunks" */
++/* there will be 1024 chunks represented by each counter in the page pointers */
++#define PAGEPTR_BLOCK_RATIO(bitmap) \
++ (CHUNK_BLOCK_RATIO(bitmap) << PAGE_COUNTER_SHIFT >> 1)
++#define PAGEPTR_BLOCK_SHIFT(bitmap) \
++ (CHUNK_BLOCK_SHIFT(bitmap) + PAGE_COUNTER_SHIFT - 1)
++#define PAGEPTR_BLOCK_MASK(bitmap) (PAGEPTR_BLOCK_RATIO(bitmap) - 1)
++
++/*
++ * on-disk bitmap:
++ *
++ * Use one bit per "chunk" (block set). We do the disk I/O on the bitmap
++ * file a page at a time. There's a superblock at the start of the file.
++ */
++
++/* map chunks (bits) to file pages - offset by the size of the superblock */
++#define CHUNK_BIT_OFFSET(chunk) ((chunk) + (sizeof(bitmap_super_t) << 3))
++
++#endif
++
++/*
++ * bitmap structures:
++ */
++
++#define BITMAP_MAGIC 0x6d746962
++
++/* use these for bitmap->flags and bitmap->sb->state bit-fields */
++enum bitmap_state {
++ BITMAP_ACTIVE = 0x001, /* the bitmap is in use */
++ BITMAP_STALE = 0x002 /* the bitmap file is out of date or had -EIO */
++};
++
++/* the superblock at the front of the bitmap file -- little endian */
++typedef struct bitmap_super_s {
++ __u32 magic; /* 0 BITMAP_MAGIC */
++ __u32 version; /* 4 the bitmap major for now, could change... */
++ __u8 uuid[16]; /* 8 128 bit uuid - must match md device uuid */
++ __u64 events; /* 24 event counter for the bitmap (1)*/
++ __u64 events_cleared;/*32 event counter when last bit cleared (2) */
++ __u64 sync_size; /* 40 the size of the md device's sync range(3) */
++ __u32 state; /* 48 bitmap state information */
++ __u32 chunksize; /* 52 the bitmap chunk size in bytes */
++ __u32 daemon_sleep; /* 56 seconds between disk flushes */
++ __u32 write_behind; /* 60 number of outstanding write-behind writes */
++
++ __u8 pad[256 - 64]; /* set to zero */
++} bitmap_super_t;
++
++/* notes:
++ * (1) This event counter is updated before the eventcounter in the md superblock
++ * When a bitmap is loaded, it is only accepted if this event counter is equal
++ * to, or one greater than, the event counter in the superblock.
++ * (2) This event counter is updated when the other one is *if*and*only*if* the
++ * array is not degraded. As bits are not cleared when the array is degraded,
++ * this represents the last time that any bits were cleared.
++ * If a device is being added that has an event count with this value or
++ * higher, it is accepted as conforming to the bitmap.
++ * (3)This is the number of sectors represented by the bitmap, and is the range that
++ * resync happens across. For raid1 and raid5/6 it is the size of individual
++ * devices. For raid10 it is the size of the array.
++ */
++
++#ifdef __KERNEL__
++
++/* the in-memory bitmap is represented by bitmap_pages */
++struct bitmap_page {
++ /*
++ * map points to the actual memory page
++ */
++ char *map;
++ /*
++ * in emergencies (when map cannot be alloced), hijack the map
++ * pointer and use it as two counters itself
++ */
++ unsigned int hijacked;
++ /*
++ * count of dirty bits on the page
++ */
++ int count;
++};
++
++/* keep track of bitmap file pages that have pending writes on them */
++struct page_list {
++ struct list_head list;
++ struct page *page;
++};
++
++/* the main bitmap structure - one per mddev */
++struct bitmap {
++ struct bitmap_page *bp;
++ unsigned long pages; /* total number of pages in the bitmap */
++ unsigned long missing_pages; /* number of pages not yet allocated */
++
++ mddev_t *mddev; /* the md device that the bitmap is for */
++
++ int counter_bits; /* how many bits per block counter */
++
++ /* bitmap chunksize -- how much data does each bit represent? */
++ unsigned long chunksize;
++ unsigned long chunkshift; /* chunksize = 2^chunkshift (for bitops) */
++ unsigned long chunks; /* total number of data chunks for the array */
++
++ /* We hold a count on the chunk currently being synced, and drop
++ * it when the last block is started. If the resync is aborted
++ * midway, we need to be able to drop that count, so we remember
++ * the counted chunk..
++ */
++ unsigned long syncchunk;
++
++ __u64 events_cleared;
++
++ /* bitmap spinlock */
++ spinlock_t lock;
++
++ struct file *file; /* backing disk file */
++ struct page *sb_page; /* cached copy of the bitmap file superblock */
++ struct page **filemap; /* list of cache pages for the file */
++ unsigned long *filemap_attr; /* attributes associated w/ filemap pages */
++ unsigned long file_pages; /* number of pages in the file */
++
++ unsigned long flags;
++
++ /*
++ * the bitmap daemon - periodically wakes up and sweeps the bitmap
++ * file, cleaning up bits and flushing out pages to disk as necessary
++ */
++ mdk_thread_t *daemon;
++ unsigned long daemon_sleep; /* how many seconds between updates? */
++
++ /*
++ * bitmap write daemon - this daemon performs writes to the bitmap file
++ * this thread is only needed because of a limitation in ext3 (jbd)
++ * that does not allow a task to have two journal transactions ongoing
++ * simultaneously (even if the transactions are for two different
++ * filesystems) -- in the case of bitmap, that would be the filesystem
++ * that the bitmap file resides on and the filesystem that is mounted
++ * on the md device -- see current->journal_info in jbd/transaction.c
++ */
++ mdk_thread_t *write_daemon;
++ mdk_thread_t *writeback_daemon;
++ spinlock_t write_lock;
++ struct semaphore write_ready;
++ struct semaphore write_done;
++ unsigned long writes_pending;
++ wait_queue_head_t write_wait;
++ struct list_head write_pages;
++ struct list_head complete_pages;
++ mempool_t *write_pool;
++};
++
++/* the bitmap API */
++
++/* these are used only by md/bitmap */
++int bitmap_create(mddev_t *mddev);
++void bitmap_destroy(mddev_t *mddev);
++int bitmap_active(struct bitmap *bitmap);
++
++char *file_path(struct file *file, char *buf, int count);
++void bitmap_print_sb(struct bitmap *bitmap);
++int bitmap_update_sb(struct bitmap *bitmap);
++
++int bitmap_setallbits(struct bitmap *bitmap);
++
++/* these are exported */
++void bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors);
++void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long sectors,
++ int success);
++int bitmap_start_sync(struct bitmap *bitmap, sector_t offset, int *blocks);
++void bitmap_end_sync(struct bitmap *bitmap, sector_t offset, int *blocks, int aborted);
++void bitmap_close_sync(struct bitmap *bitmap);
++
++int bitmap_unplug(struct bitmap *bitmap);
++#endif
++
++#endif
+diff -pruN a/mdadm/config.c mdadm/mdadm/config.c
+--- a/mdadm/config.c 1970-01-01 03:00:00.000000000 +0300
++++ mdadm/mdadm/config.c 2011-01-12 21:33:01.000000000 +0200
+@@ -0,0 +1,824 @@
++/*
++ * mdadm - manage Linux "md" devices aka RAID arrays.
++ *
++ * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * Author: Neil Brown
++ * Email: <neilb@cse.unsw.edu.au>
++ * Paper: Neil Brown
++ * School of Computer Science and Engineering
++ * The University of New South Wales
++ * Sydney, 2052
++ * Australia
++ */
++
++#include "mdadm.h"
++#include "dlink.h"
++#include <sys/dir.h>
++#include <glob.h>
++#include <fnmatch.h>
++#include <ctype.h>
++#include <pwd.h>
++#include <grp.h>
++
++mapping_t r5layout[] = {
++ { "left-asymmetric", 0},
++ { "right-asymmetric", 1},
++ { "left-symmetric", 2},
++ { "right-symmetric", 3},
++
++ { "default", 2},
++ { "la", 0},
++ { "ra", 1},
++ { "ls", 2},
++ { "rs", 3},
++ { NULL, 0}
++};
++
++mapping_t pers[] = {
++ { "linear", -1},
++ { "raid0", 0},
++ { "0", 0},
++ { "stripe", 0},
++ { "raid1", 1},
++ { "1", 1},
++ { "mirror", 1},
++ { "raid4", 4},
++ { "4", 4},
++ { "raid5", 5},
++ { "5", 5},
++ { "multipath", -4},
++ { "mp", -4},
++ { "raid6", 6},
++ { "6", 6},
++ { "raid10", 10},
++ { "10", 10},
++ { "faulty", -5},
++ { NULL, 0}
++};
++/*
++ * Read the config file
++ *
++ * conf_get_uuids gets a list of devicename+uuid pairs
++ * conf_get_devs gets device names after expanding wildcards
++ *
++ * Each keeps the returned list and frees it when asked to make
++ * a new list.
++ *
++ * The format of the config file needs to be fairly extensible.
++ * Now, arrays only have names and uuids and devices merely are.
++ * But later arrays might want names, and devices might want superblock
++ * versions, and who knows what else.
++ * I like free format, abhore backslash line continuation, adore
++ * indentation for structure and am ok about # comments.
++ *
++ * So, each line that isn't blank or a #comment must either start
++ * with a key word, and not be indented, or must start with a
++ * non-key-word and must be indented.
++ *
++ * Keywords are DEVICE and ARRAY
++ * DEV{ICE} introduces some devices that might contain raid components.
++ * e.g.
++ * DEV style=0 /dev/sda* /dev/hd*
++ * DEV style=1 /dev/sd[b-f]*
++ * ARR{AY} describes an array giving md device and attributes like uuid=whatever
++ * e.g.
++ * ARRAY /dev/md0 uuid=whatever name=something
++ * Spaces separate words on each line. Quoting, with "" or '' protects them,
++ * but may not wrap over lines
++ *
++ */
++
++#ifndef CONFFILE
++#define CONFFILE "/etc/mdadm.conf"
++#endif
++#ifndef CONFFILE2
++/* for Debian compatibility .... */
++#define CONFFILE2 "/etc/mdadm/mdadm.conf"
++#endif
++char DefaultConfFile[] = CONFFILE;
++char DefaultAltConfFile[] = CONFFILE2;
++
++enum linetype { Devices, Array, Mailaddr, Mailfrom, Program, CreateDev, Homehost, LTEnd };
++char *keywords[] = {
++ [Devices] = "devices",
++ [Array] = "array",
++ [Mailaddr] = "mailaddr",
++ [Mailfrom] = "mailfrom",
++ [Program] = "program",
++ [CreateDev]= "create",
++ [Homehost] = "homehost",
++ [LTEnd] = NULL
++};
++
++/*
++ * match_keyword returns an index into the keywords array, or -1 for no match
++ * case is ignored, and at least three characters must be given
++ */
++
++int match_keyword(char *word)
++{
++ int len = strlen(word);
++ int n;
++
++ if (len < 3) return -1;
++ for (n=0; keywords[n]; n++) {
++ if (strncasecmp(word, keywords[n], len)==0)
++ return n;
++ }
++ return -1;
++}
++
++/* conf_word gets one word from the conf file.
++ * if "allow_key", then accept words at the start of a line,
++ * otherwise stop when such a word is found.
++ * We assume that the file pointer is at the end of a word, so the
++ * next character is a space, or a newline. If not, it is the start of a line.
++ */
++
++char *conf_word(FILE *file, int allow_key)
++{
++ int wsize = 100;
++ int len = 0;
++ int c;
++ int quote;
++ int wordfound = 0;
++ char *word = malloc(wsize);
++
++ if (!word) abort();
++
++ while (wordfound==0) {
++ /* at the end of a word.. */
++ c = getc(file);
++ if (c == '#')
++ while (c != EOF && c != '\n')
++ c = getc(file);
++ if (c == EOF) break;
++ if (c == '\n') continue;
++
++ if (c != ' ' && c != '\t' && ! allow_key) {
++ ungetc(c, file);
++ break;
++ }
++ /* looks like it is safe to get a word here, if there is one */
++ quote = 0;
++ /* first, skip any spaces */
++ while (c == ' ' || c == '\t')
++ c = getc(file);
++ if (c != EOF && c != '\n' && c != '#') {
++ /* we really have a character of a word, so start saving it */
++ while (c != EOF && c != '\n' && (quote || (c!=' ' && c != '\t'))) {
++ wordfound = 1;
++ if (quote && c == quote) quote = 0;
++ else if (quote == 0 && (c == '\'' || c == '"'))
++ quote = c;
++ else {
++ if (len == wsize-1) {
++ wsize += 100;
++ word = realloc(word, wsize);
++ if (!word) abort();
++ }
++ word[len++] = c;
++ }
++ c = getc(file);
++ }
++ }
++ if (c != EOF) ungetc(c, file);
++ }
++ word[len] = 0;
++/* printf("word is <%s>\n", word); */
++ if (!wordfound) {
++ free(word);
++ word = NULL;
++ }
++ return word;
++}
++
++/*
++ * conf_line reads one logical line from the conffile.
++ * It skips comments and continues until it finds a line that starts
++ * with a non blank/comment. This character is pushed back for the next call
++ * A doubly linked list of words is returned.
++ * the first word will be a keyword. Other words will have had quotes removed.
++ */
++
++char *conf_line(FILE *file)
++{
++ char *w;
++ char *list;
++
++ w = conf_word(file, 1);
++ if (w == NULL) return NULL;
++
++ list = dl_strdup(w);
++ free(w);
++ dl_init(list);
++
++ while ((w = conf_word(file,0))){
++ char *w2 = dl_strdup(w);
++ free(w);
++ dl_add(list, w2);
++ }
++/* printf("got a line\n");*/
++ return list;
++}
++
++void free_line(char *line)
++{
++ char *w;
++ for (w=dl_next(line); w != line; w=dl_next(line)) {
++ dl_del(w);
++ dl_free(w);
++ }
++ dl_free(line);
++}
++
++
++struct conf_dev {
++ struct conf_dev *next;
++ char *name;
++} *cdevlist = NULL;
++
++mddev_dev_t load_partitions(void)
++{
++ FILE *f = fopen("/proc/partitions", "r");
++ char buf[1024];
++ mddev_dev_t rv = NULL;
++ if (f == NULL) {
++ fprintf(stderr, Name ": cannot open /proc/partitions\n");
++ return NULL;
++ }
++ while (fgets(buf, 1024, f)) {
++ int major, minor;
++ char *name, *mp;
++ mddev_dev_t d;
++
++ buf[1023] = '\0';
++ if (buf[0] != ' ')
++ continue;
++ major = strtoul(buf, &mp, 10);
++ if (mp == buf || *mp != ' ')
++ continue;
++ minor = strtoul(mp, NULL, 10);
++
++ name = map_dev(major, minor, 1);
++ if (!name)
++ continue;
++ d = malloc(sizeof(*d));
++ d->devname = strdup(name);
++ d->next = rv;
++ d->used = 0;
++ rv = d;
++ }
++ fclose(f);
++ return rv;
++}
++
++struct createinfo createinfo = {
++ .autof = 2, /* by default, create devices with standard names */
++ .symlinks = 1,
++#ifdef DEBIAN
++ .gid = 6, /* disk */
++ .mode = 0660,
++#else
++ .mode = 0600,
++#endif
++};
++
++int parse_auto(char *str, char *msg, int config)
++{
++ int autof;
++ if (str == NULL || *str == 0)
++ autof = 2;
++ else if (strcasecmp(str,"no")==0)
++ autof = 1;
++ else if (strcasecmp(str,"yes")==0)
++ autof = 2;
++ else if (strcasecmp(str,"md")==0)
++ autof = config?5:3;
++ else {
++ /* There might be digits, and maybe a hypen, at the end */
++ char *e = str + strlen(str);
++ int num = 4;
++ int len;
++ while (e > str && isdigit(e[-1]))
++ e--;
++ if (*e) {
++ num = atoi(e);
++ if (num <= 0) num = 1;
++ }
++ if (e > str && e[-1] == '-')
++ e--;
++ len = e - str;
++ if ((len == 2 && strncasecmp(str,"md",2)==0)) {
++ autof = config ? 5 : 3;
++ } else if ((len == 3 && strncasecmp(str,"yes",3)==0)) {
++ autof = 2;
++ } else if ((len == 3 && strncasecmp(str,"mdp",3)==0)) {
++ autof = config ? 6 : 4;
++ } else if ((len == 1 && strncasecmp(str,"p",1)==0) ||
++ (len >= 4 && strncasecmp(str,"part",4)==0)) {
++ autof = 6;
++ } else {
++ fprintf(stderr, Name ": %s arg of \"%s\" unrecognised: use no,yes,md,mdp,part\n"
++ " optionally followed by a number.\n",
++ msg, str);
++ exit(2);
++ }
++ autof |= num << 3;
++ }
++ return autof;
++}
++
++static void createline(char *line)
++{
++ char *w;
++ char *ep;
++
++ for (w=dl_next(line); w!=line; w=dl_next(w)) {
++ if (strncasecmp(w, "auto=", 5) == 0)
++ createinfo.autof = parse_auto(w+5, "auto=", 1);
++ else if (strncasecmp(w, "owner=", 6) == 0) {
++ if (w[6] == 0) {
++ fprintf(stderr, Name ": missing owner name\n");
++ continue;
++ }
++ createinfo.uid = strtoul(w+6, &ep, 10);
++ if (*ep != 0) {
++ struct passwd *pw;
++ /* must be a name */
++ pw = getpwnam(w+6);
++ if (pw)
++ createinfo.uid = pw->pw_uid;
++ else
++ fprintf(stderr, Name ": CREATE user %s not found\n", w+6);
++ }
++ } else if (strncasecmp(w, "group=", 6) == 0) {
++ if (w[6] == 0) {
++ fprintf(stderr, Name ": missing group name\n");
++ continue;
++ }
++ createinfo.gid = strtoul(w+6, &ep, 10);
++ if (*ep != 0) {
++ struct group *gr;
++ /* must be a name */
++ gr = getgrnam(w+6);
++ if (gr)
++ createinfo.gid = gr->gr_gid;
++ else
++ fprintf(stderr, Name ": CREATE group %s not found\n", w+6);
++ }
++ } else if (strncasecmp(w, "mode=", 5) == 0) {
++ if (w[5] == 0) {
++ fprintf(stderr, Name ": missing CREATE mode\n");
++ continue;
++ }
++ createinfo.mode = strtoul(w+5, &ep, 8);
++ if (*ep != 0) {
++ createinfo.mode = 0600;
++ fprintf(stderr, Name ": unrecognised CREATE mode %s\n",
++ w+5);
++ }
++ } else if (strncasecmp(w, "metadata=", 9) == 0) {
++ /* style of metadata to use by default */
++ int i;
++ for (i=0; superlist[i] && !createinfo.supertype; i++)
++ createinfo.supertype =
++ superlist[i]->match_metadata_desc(w+9);
++ if (!createinfo.supertype)
++ fprintf(stderr, Name ": metadata format %s unknown, ignoring\n",
++ w+9);
++ } else if (strncasecmp(w, "symlinks=yes", 12) == 0)
++ createinfo.symlinks = 1;
++ else if (strncasecmp(w, "symlinks=no", 11) == 0)
++ createinfo.symlinks = 0;
++ else {
++ fprintf(stderr, Name ": unrecognised word on CREATE line: %s\n",
++ w);
++ }
++ }
++}
++
++void devline(char *line)
++{
++ char *w;
++ struct conf_dev *cd;
++
++ for (w=dl_next(line); w != line; w=dl_next(w)) {
++ if (w[0] == '/' || strcasecmp(w, "partitions") == 0) {
++ cd = malloc(sizeof(*cd));
++ cd->name = strdup(w);
++ cd->next = cdevlist;
++ cdevlist = cd;
++ } else {
++ fprintf(stderr, Name ": unreconised word on DEVICE line: %s\n",
++ w);
++ }
++ }
++}
++
++mddev_ident_t mddevlist = NULL;
++mddev_ident_t *mddevlp = &mddevlist;
++
++void arrayline(char *line)
++{
++ char *w;
++
++ struct mddev_ident_s mis;
++ mddev_ident_t mi;
++
++ mis.uuid_set = 0;
++ mis.super_minor = UnSet;
++ mis.level = UnSet;
++ mis.raid_disks = UnSet;
++ mis.spare_disks = 0;
++ mis.devices = NULL;
++ mis.devname = NULL;
++ mis.spare_group = NULL;
++ mis.autof = 0;
++ mis.next = NULL;
++ mis.st = NULL;
++ mis.bitmap_fd = -1;
++ mis.bitmap_file = NULL;
++ mis.name[0] = 0;
++
++ for (w=dl_next(line); w!=line; w=dl_next(w)) {
++ if (w[0] == '/') {
++ if (mis.devname)
++ fprintf(stderr, Name ": only give one device per ARRAY line: %s and %s\n",
++ mis.devname, w);
++ else mis.devname = w;
++ } else if (strncasecmp(w, "uuid=", 5)==0 ) {
++ if (mis.uuid_set)
++ fprintf(stderr, Name ": only specify uuid once, %s ignored.\n",
++ w);
++ else {
++ if (parse_uuid(w+5, mis.uuid))
++ mis.uuid_set = 1;
++ else
++ fprintf(stderr, Name ": bad uuid: %s\n", w);
++ }
++ } else if (strncasecmp(w, "super-minor=", 12)==0 ) {
++ if (mis.super_minor != UnSet)
++ fprintf(stderr, Name ": only specify super-minor once, %s ignored.\n",
++ w);
++ else {
++ char *endptr;
++ mis.super_minor= strtol(w+12, &endptr, 10);
++ if (w[12]==0 || endptr[0]!=0 || mis.super_minor < 0) {
++ fprintf(stderr, Name ": invalid super-minor number: %s\n",
++ w);
++ mis.super_minor = UnSet;
++ }
++ }
++ } else if (strncasecmp(w, "name=", 5)==0) {
++ if (mis.name[0])
++ fprintf(stderr, Name ": only specify name once, %s ignored.\n",
++ w);
++ else if (strlen(w+5) > 32)
++ fprintf(stderr, Name ": name too long, ignoring %s\n", w);
++ else
++ strcpy(mis.name, w+5);
++
++ } else if (strncasecmp(w, "bitmap=", 7) == 0) {
++ if (mis.bitmap_file)
++ fprintf(stderr, Name ": only specify bitmap file once. %s ignored\n",
++ w);
++ else
++ mis.bitmap_file = strdup(w+7);
++
++ } else if (strncasecmp(w, "devices=", 8 ) == 0 ) {
++ if (mis.devices)
++ fprintf(stderr, Name ": only specify devices once (use a comma separated list). %s ignored\n",
++ w);
++ else
++ mis.devices = strdup(w+8);
++ } else if (strncasecmp(w, "spare-group=", 12) == 0 ) {
++ if (mis.spare_group)
++ fprintf(stderr, Name ": only specify one spare group per array. %s ignored.\n",
++ w);
++ else
++ mis.spare_group = strdup(w+12);
++ } else if (strncasecmp(w, "level=", 6) == 0 ) {
++ /* this is mainly for compatability with --brief output */
++ mis.level = map_name(pers, w+6);
++ } else if (strncasecmp(w, "disks=", 6) == 0 ) {
++ /* again, for compat */
++ mis.raid_disks = atoi(w+6);
++ } else if (strncasecmp(w, "num-devices=", 12) == 0 ) {
++ /* again, for compat */
++ mis.raid_disks = atoi(w+12);
++ } else if (strncasecmp(w, "spares=", 7) == 0 ) {
++ /* for warning if not all spares present */
++ mis.spare_disks = atoi(w+7);
++ } else if (strncasecmp(w, "metadata=", 9) == 0) {
++ /* style of metadata on the devices. */
++ int i;
++
++ for(i=0; superlist[i] && !mis.st; i++)
++ mis.st = superlist[i]->match_metadata_desc(w+9);
++
++ if (!mis.st)
++ fprintf(stderr, Name ": metadata format %s unknown, ignored.\n", w+9);
++ } else if (strncasecmp(w, "auto=", 5) == 0 ) {
++ /* whether to create device special files as needed */
++ mis.autof = parse_auto(w+5, "auto type", 0);
++ } else {
++ fprintf(stderr, Name ": unrecognised word on ARRAY line: %s\n",
++ w);
++ }
++ }
++ if (mis.devname == NULL)
++ fprintf(stderr, Name ": ARRAY line with no device\n");
++ else if (mis.uuid_set == 0 && mis.devices == NULL && mis.super_minor == UnSet && mis.name[0] == 0)
++ fprintf(stderr, Name ": ARRAY line %s has no identity information.\n", mis.devname);
++ else {
++ mi = malloc(sizeof(*mi));
++ *mi = mis;
++ mi->devname = strdup(mis.devname);
++ mi->next = NULL;
++ *mddevlp = mi;
++ mddevlp = &mi->next;
++ }
++}
++
++static char *alert_email = NULL;
++void mailline(char *line)
++{
++ char *w;
++
++ for (w=dl_next(line); w != line ; w=dl_next(w)) {
++ if (alert_email == NULL)
++ alert_email = strdup(w);
++ else
++ fprintf(stderr, Name ": excess address on MAIL line: %s - ignored\n",
++ w);
++ }
++}
++
++static char *alert_mail_from = NULL;
++void mailfromline(char *line)
++{
++ char *w;
++
++ for (w=dl_next(line); w != line ; w=dl_next(w)) {
++ if (alert_mail_from == NULL)
++ alert_mail_from = strdup(w);
++ else {
++ char *t= NULL;
++ asprintf(&t, "%s %s", alert_mail_from, w);
++ free(alert_mail_from);
++ alert_mail_from = t;
++ }
++ }
++}
++
++
++static char *alert_program = NULL;
++void programline(char *line)
++{
++ char *w;
++
++ for (w=dl_next(line); w != line ; w=dl_next(w)) {
++ if (alert_program == NULL)
++ alert_program = strdup(w);
++ else
++ fprintf(stderr, Name ": excess program on PROGRAM line: %s - ignored\n",
++ w);
++ }
++}
++
++static char *home_host = NULL;
++void homehostline(char *line)
++{
++ char *w;
++
++ for (w=dl_next(line); w != line ; w=dl_next(w)) {
++ if (home_host == NULL)
++ home_host = strdup(w);
++ else
++ fprintf(stderr, Name ": excess host name on HOMEHOST line: %s - ignored\n",
++ w);
++ }
++}
++
++
++int loaded = 0;
++
++static char *conffile = NULL;
++void set_conffile(char *file)
++{
++ conffile = file;
++}
++
++void load_conffile(void)
++{
++ FILE *f;
++ char *line;
++
++ if (loaded) return;
++ if (conffile == NULL)
++ conffile = DefaultConfFile;
++
++ if (strcmp(conffile, "none") == 0) {
++ loaded = 1;
++ return;
++ }
++ if (strcmp(conffile, "partitions")==0) {
++ char *list = dl_strdup("DEV");
++ dl_init(list);
++ dl_add(list, dl_strdup("partitions"));
++ devline(list);
++ free_line(list);
++ loaded = 1;
++ return;
++ }
++ f = fopen(conffile, "r");
++ /* Debian chose to relocate mdadm.conf into /etc/mdadm/.
++ * To allow Debian users to compile from clean source and still
++ * have a working mdadm, we read /etc/mdadm/mdadm.conf
++ * if /etc/mdadm.conf doesn't exist
++ */
++ if (f == NULL &&
++ conffile == DefaultConfFile) {
++ f = fopen(DefaultAltConfFile, "r");
++ if (f)
++ conffile = DefaultAltConfFile;
++ }
++ if (f == NULL)
++ return;
++
++ loaded = 1;
++ while ((line=conf_line(f))) {
++ switch(match_keyword(line)) {
++ case Devices:
++ devline(line);
++ break;
++ case Array:
++ arrayline(line);
++ break;
++ case Mailaddr:
++ mailline(line);
++ break;
++ case Mailfrom:
++ mailfromline(line);
++ break;
++ case Program:
++ programline(line);
++ break;
++ case CreateDev:
++ createline(line);
++ break;
++ case Homehost:
++ homehostline(line);
++ break;
++ default:
++ fprintf(stderr, Name ": Unknown keyword %s\n", line);
++ }
++ free_line(line);
++ }
++
++ fclose(f);
++
++/* printf("got file\n"); */
++}
++
++char *conf_get_mailaddr(void)
++{
++ load_conffile();
++ return alert_email;
++}
++
++char *conf_get_mailfrom(void)
++{
++ load_conffile();
++ return alert_mail_from;
++}
++
++char *conf_get_program(void)
++{
++ load_conffile();
++ return alert_program;
++}
++
++char *conf_get_homehost(void)
++{
++ load_conffile();
++ return home_host;
++}
++
++struct createinfo *conf_get_create_info(void)
++{
++ load_conffile();
++ return &createinfo;
++}
++
++mddev_ident_t conf_get_ident(char *dev)
++{
++ mddev_ident_t rv;
++ load_conffile();
++ rv = mddevlist;
++ while (dev && rv && strcmp(dev, rv->devname)!=0)
++ rv = rv->next;
++ return rv;
++}
++
++mddev_dev_t conf_get_devs()
++{
++ glob_t globbuf;
++ struct conf_dev *cd;
++ int flags = 0;
++ static mddev_dev_t dlist = NULL;
++ unsigned int i;
++
++ while (dlist) {
++ mddev_dev_t t = dlist;
++ dlist = dlist->next;
++ free(t->devname);
++ free(t);
++ }
++
++ load_conffile();
++
++ if (cdevlist == NULL)
++ /* default to 'partitions */
++ dlist = load_partitions();
++
++ for (cd=cdevlist; cd; cd=cd->next) {
++ if (strcasecmp(cd->name, "partitions")==0 && dlist == NULL)
++ dlist = load_partitions();
++ else {
++ glob(cd->name, flags, NULL, &globbuf);
++ flags |= GLOB_APPEND;
++ }
++ }
++ if (flags & GLOB_APPEND) {
++ for (i=0; i<globbuf.gl_pathc; i++) {
++ mddev_dev_t t = malloc(sizeof(*t));
++ t->devname = strdup(globbuf.gl_pathv[i]);
++ t->next = dlist;
++ t->used = 0;
++ dlist = t;
++/* printf("one dev is %s\n", t->devname);*/
++ }
++ globfree(&globbuf);
++ }
++
++ return dlist;
++}
++
++int conf_test_dev(char *devname)
++{
++ struct conf_dev *cd;
++ if (cdevlist == NULL)
++ /* allow anything by default */
++ return 1;
++ for (cd = cdevlist ; cd ; cd = cd->next) {
++ if (strcasecmp(cd->name, "partitions") == 0)
++ return 1;
++ if (fnmatch(cd->name, devname, FNM_PATHNAME) == 0)
++ return 1;
++ }
++ return 0;
++}
++
++
++int match_oneof(char *devices, char *devname)
++{
++ /* check if one of the comma separated patterns in devices
++ * matches devname
++ */
++
++
++ while (devices && *devices) {
++ char patn[1024];
++ char *p = devices;
++ devices = strchr(devices, ',');
++ if (!devices)
++ devices = p + strlen(p);
++ if (devices-p < 1024) {
++ strncpy(patn, p, devices-p);
++ patn[devices-p] = 0;
++ if (fnmatch(patn, devname, FNM_PATHNAME)==0)
++ return 1;
++ }
++ if (*devices == ',')
++ devices++;
++ }
++ return 0;
++}
+--- a/mdadm/Config.in 1970-01-01 03:00:00.000000000 +0300
++++ mdadm/mdadm/Config.in 2011-01-12 21:33:01.000000000 +0200
+@@ -0,0 +1,15 @@
++#
++# For a description of the syntax of this configuration file,
++# see scripts/kbuild/config-language.txt.
++#
++
++menu "Linux mdadm Utilities"
++
++config MDADM
++ bool "mdadm"
++ default n
++ help
++ assemble or examine raid array
++
++endmenu
++
+--- a/mdadm/dlink.c 1970-01-01 03:00:00.000000000 +0300
++++ mdadm/mdadm/dlink.c 2011-01-12 21:33:01.000000000 +0200
+@@ -0,0 +1,79 @@
++
++/* doubly linked lists */
++/* This is free software. No strings attached. No copyright claimed */
++
++#include <unistd.h>
++#include <stdlib.h>
++#include <string.h>
++#ifdef __dietlibc__
++char *strncpy(char *dest, const char *src, size_t n) __THROW;
++#endif
++#include "dlink.h"
++
++
++void *dl_head()
++{
++ void *h;
++ h = dl_alloc(0);
++ dl_next(h) = h;
++ dl_prev(h) = h;
++ return h;
++}
++
++void dl_free(void *v)
++{
++ struct __dl_head *vv = v;
++ free(vv-1);
++}
++
++void dl_init(void *v)
++{
++ dl_next(v) = v;
++ dl_prev(v) = v;
++}
++
++void dl_insert(void *head, void *val)
++{
++ dl_next(val) = dl_next(head);
++ dl_prev(val) = head;
++ dl_next(dl_prev(val)) = val;
++ dl_prev(dl_next(val)) = val;
++}
++
++void dl_add(void *head, void *val)
++{
++ dl_prev(val) = dl_prev(head);
++ dl_next(val) = head;
++ dl_next(dl_prev(val)) = val;
++ dl_prev(dl_next(val)) = val;
++}
++
++void dl_del(void *val)
++{
++ if (dl_prev(val) == 0 || dl_next(val) == 0)
++ return;
++ dl_prev(dl_next(val)) = dl_prev(val);
++ dl_next(dl_prev(val)) = dl_next(val);
++ dl_prev(val) = dl_next(val) = 0;
++}
++
++char *dl_strndup(char *s, int l)
++{
++ char *n;
++ if (s == NULL)
++ return NULL;
++ n = dl_newv(char, l+1);
++ if (n == NULL)
++ return NULL;
++ else
++ {
++ strncpy(n, s, l);
++ n[l] = 0;
++ return n;
++ }
++}
++
++char *dl_strdup(char *s)
++{
++ return dl_strndup(s, (int)strlen(s));
++}
+--- a/mdadm/dlink.h 1970-01-01 03:00:00.000000000 +0300
++++ mdadm/mdadm/dlink.h 2011-01-12 21:33:01.000000000 +0200
+@@ -0,0 +1,25 @@
++
++/* doubley linked lists */
++/* This is free software. No strings attached. No copyright claimed */
++
++struct __dl_head
++{
++ void * dh_prev;
++ void * dh_next;
++};
++
++#define dl_alloc(size) ((void*)(((char*)calloc(1,(size)+sizeof(struct __dl_head)))+sizeof(struct __dl_head)))
++#define dl_new(t) ((t*)dl_alloc(sizeof(t)))
++#define dl_newv(t,n) ((t*)dl_alloc(sizeof(t)*n))
++
++#define dl_next(p) *(&(((struct __dl_head*)(p))[-1].dh_next))
++#define dl_prev(p) *(&(((struct __dl_head*)(p))[-1].dh_prev))
++
++void *dl_head(void);
++char *dl_strdup(char *);
++char *dl_strndup(char *, int);
++void dl_insert(void*, void*);
++void dl_add(void*, void*);
++void dl_del(void*);
++void dl_free(void*);
++void dl_init(void*);
+--- a/mdadm/Kbuild 1970-01-01 03:00:00.000000000 +0300
++++ mdadm/mdadm/Kbuild 2011-01-12 21:33:01.000000000 +0200
+@@ -0,0 +1,9 @@
++# Makefile for busybox
++#
++# Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org>
++#
++# Licensed under the GPL v2, see the file LICENSE in this tarball.
++
++lib-y:=
++MDADM-y:= config.o util.o dlink.o sha1.o super0.o super1.o mdexamine.o mdassemble.o
++lib-$(CONFIG_MDADM) += mdadm.o $(MDADM-y)
+--- a/mdadm/md5.h 1970-01-01 03:00:00.000000000 +0300
++++ mdadm/mdadm/md5.h 2011-01-12 21:33:01.000000000 +0200
+@@ -0,0 +1,134 @@
++/* Declaration of functions and data types used for MD5 sum computing
++ library functions.
++ Copyright (C) 1995-1997,1999-2005 Free Software Foundation, Inc.
++
++ NOTE: The canonical source of this file is maintained with the GNU C
++ Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu.
++
++ This program is free software; you can redistribute it and/or modify it
++ under the terms of the GNU General Public License as published by the
++ Free Software Foundation; either version 2, or (at your option) any
++ later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software Foundation,
++ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
++
++#ifndef _MD5_H
++#define _MD5_H 1
++
++#include <stdio.h>
++
++# include <inttypes.h>
++#if HAVE_STDINT_H || _LIBC
++# include <stdint.h>
++#endif
++
++#ifndef __GNUC_PREREQ
++# if defined __GNUC__ && defined __GNUC_MINOR__
++# define __GNUC_PREREQ(maj, min) \
++ ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
++# else
++# define __GNUC_PREREQ(maj, min) 0
++# endif
++#endif
++
++#ifndef __THROW
++# if defined __cplusplus && __GNUC_PREREQ (2,8)
++# define __THROW throw ()
++# else
++# define __THROW
++# endif
++#endif
++
++#ifndef __attribute__
++# if ! __GNUC_PREREQ (2,8) || __STRICT_ANSI__
++# define __attribute__(x)
++# endif
++#endif
++
++#ifndef _LIBC
++# define __md5_buffer md5_buffer
++# define __md5_finish_ctx md5_finish_ctx
++# define __md5_init_ctx md5_init_ctx
++# define __md5_process_block md5_process_block
++# define __md5_process_bytes md5_process_bytes
++# define __md5_read_ctx md5_read_ctx
++# define __md5_stream md5_stream
++#endif
++
++typedef uint32_t md5_uint32;
++
++/* Structure to save state of computation between the single steps. */
++struct md5_ctx
++{
++ md5_uint32 A;
++ md5_uint32 B;
++ md5_uint32 C;
++ md5_uint32 D;
++
++ md5_uint32 total[2];
++ md5_uint32 buflen;
++ char buffer[128] __attribute__ ((__aligned__ (__alignof__ (md5_uint32))));
++};
++
++/*
++ * The following three functions are build up the low level used in
++ * the functions `md5_stream' and `md5_buffer'.
++ */
++
++/* Initialize structure containing state of computation.
++ (RFC 1321, 3.3: Step 3) */
++extern void __md5_init_ctx (struct md5_ctx *ctx) __THROW;
++
++/* Starting with the result of former calls of this function (or the
++ initialization function update the context for the next LEN bytes
++ starting at BUFFER.
++ It is necessary that LEN is a multiple of 64!!! */
++extern void __md5_process_block (const void *buffer, size_t len,
++ struct md5_ctx *ctx) __THROW;
++
++/* Starting with the result of former calls of this function (or the
++ initialization function update the context for the next LEN bytes
++ starting at BUFFER.
++ It is NOT required that LEN is a multiple of 64. */
++extern void __md5_process_bytes (const void *buffer, size_t len,
++ struct md5_ctx *ctx) __THROW;
++
++/* Process the remaining bytes in the buffer and put result from CTX
++ in first 16 bytes following RESBUF. The result is always in little
++ endian byte order, so that a byte-wise output yields to the wanted
++ ASCII representation of the message digest.
++
++ IMPORTANT: On some systems it is required that RESBUF be correctly
++ aligned for a 32 bits value. */
++extern void *__md5_finish_ctx (struct md5_ctx *ctx, void *resbuf) __THROW;
++
++
++/* Put result from CTX in first 16 bytes following RESBUF. The result is
++ always in little endian byte order, so that a byte-wise output yields
++ to the wanted ASCII representation of the message digest.
++
++ IMPORTANT: On some systems it is required that RESBUF is correctly
++ aligned for a 32 bits value. */
++extern void *__md5_read_ctx (const struct md5_ctx *ctx, void *resbuf) __THROW;
++
++
++/* Compute MD5 message digest for bytes read from STREAM. The
++ resulting message digest number will be written into the 16 bytes
++ beginning at RESBLOCK. */
++extern int __md5_stream (FILE *stream, void *resblock) __THROW;
++
++/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
++ result is always in little endian byte order, so that a byte-wise
++ output yields to the wanted ASCII representation of the message
++ digest. */
++extern void *__md5_buffer (const char *buffer, size_t len,
++ void *resblock) __THROW;
++
++#endif /* md5.h */
+--- a/mdadm/mdadm.c 1970-01-01 03:00:00.000000000 +0300
++++ mdadm/mdadm/mdadm.c 2011-01-12 21:33:01.000000000 +0200
+@@ -0,0 +1,18 @@
++/*
++ * mdadm support for busybox.
++ * added by Alan Hourihane <alanh@fairlite.demon.co.uk>
++ */
++#include <string.h>
++
++extern int mdassemble_main(int argc, char **argv);
++extern int mdexamine_main(int argc, char **argv);
++
++int mdadm_main(int argc, char **argv) {
++ if (argc >= 2) {
++ if (!strncmp(argv[1],"--assemble",10))
++ return mdassemble_main(argc, argv);
++ if (!strncmp(argv[1],"--examine",9))
++ return mdexamine_main(argc, argv);
++ }
++ return 0;
++}
+--- a/mdadm/mdadm.h 1970-01-01 03:00:00.000000000 +0300
++++ mdadm/mdadm/mdadm.h 2011-01-12 21:33:01.000000000 +0200
+@@ -0,0 +1,540 @@
++/*
++ * mdadm - manage Linux "md" devices aka RAID arrays.
++ *
++ * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * Author: Neil Brown
++ * Email: <neilb@cse.unsw.edu.au>
++ * Paper: Neil Brown
++ * School of Computer Science and Engineering
++ * The University of New South Wales
++ * Sydney, 2052
++ * Australia
++ */
++
++#include <unistd.h>
++#ifndef __dietlibc__
++extern __off64_t lseek64 __P ((int __fd, __off64_t __offset, int __whence));
++#else
++# if defined(__NO_STAT64) || __WORDSIZE != 32
++# define lseek64 lseek
++# endif
++#endif
++
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <stdlib.h>
++#include <time.h>
++#include <sys/time.h>
++#include <getopt.h>
++#include <fcntl.h>
++#include <stdio.h>
++#include <errno.h>
++#include <string.h>
++#include <syslog.h>
++#ifdef __dietlibc__
++#include <strings.h>
++/* dietlibc has deprecated random and srandom!! */
++#define random rand
++#define srandom srand
++#endif
++
++
++#include <linux/kdev_t.h>
++/*#include <linux/fs.h> */
++#include <sys/mount.h>
++#include <asm/types.h>
++#include <sys/ioctl.h>
++#define MD_MAJOR 9
++#define MdpMinorShift 6
++
++#ifndef BLKGETSIZE64
++#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
++#endif
++
++#define DEFAULT_BITMAP_CHUNK 4096
++#define DEFAULT_BITMAP_DELAY 5
++#define DEFAULT_MAX_WRITE_BEHIND 256
++
++#include "md_u.h"
++#include "md_p.h"
++#include "bitmap.h"
++
++#include <endian.h>
++/* Redhat don't like to #include <asm/byteorder.h>, and
++ * some time include <linux/byteorder/xxx_endian.h> isn't enough,
++ * and there is no standard conversion function so... */
++/* And dietlibc doesn't think byteswap is ok, so.. */
++/* #include <byteswap.h> */
++#define bswap_16(x) (((x) & 0x00ffU) << 8 | \
++ ((x) & 0xff00U) >> 8)
++#define bswap_32(x) (((x) & 0x000000ffU) << 24 | \
++ ((x) & 0xff000000U) >> 24 | \
++ ((x) & 0x0000ff00U) << 8 | \
++ ((x) & 0x00ff0000U) >> 8)
++#define bswap_64(x) (((x) & 0x00000000000000ffULL) << 56 | \
++ ((x) & 0xff00000000000000ULL) >> 56 | \
++ ((x) & 0x000000000000ff00ULL) << 40 | \
++ ((x) & 0x00ff000000000000ULL) >> 40 | \
++ ((x) & 0x0000000000ff0000ULL) << 24 | \
++ ((x) & 0x0000ff0000000000ULL) >> 24 | \
++ ((x) & 0x00000000ff000000ULL) << 8 | \
++ ((x) & 0x000000ff00000000ULL) >> 8)
++
++#if BYTE_ORDER == LITTLE_ENDIAN
++#define __cpu_to_le16(_x) (_x)
++#define __cpu_to_le32(_x) (_x)
++#define __cpu_to_le64(_x) (_x)
++#define __le16_to_cpu(_x) (_x)
++#define __le32_to_cpu(_x) (_x)
++#define __le64_to_cpu(_x) (_x)
++#elif BYTE_ORDER == BIG_ENDIAN
++#define __cpu_to_le16(_x) bswap_16(_x)
++#define __cpu_to_le32(_x) bswap_32(_x)
++#define __cpu_to_le64(_x) bswap_64(_x)
++#define __le16_to_cpu(_x) bswap_16(_x)
++#define __le32_to_cpu(_x) bswap_32(_x)
++#define __le64_to_cpu(_x) bswap_64(_x)
++#else
++# error "unknown endianness."
++#endif
++
++
++
++/* general information that might be extracted from a superblock */
++struct mdinfo {
++ mdu_array_info_t array;
++ mdu_disk_info_t disk;
++ __u64 events;
++ int uuid[4];
++ char name[33];
++ unsigned long long data_offset;
++ unsigned long long component_size;
++ int reshape_active;
++ unsigned long long reshape_progress;
++ int new_level, delta_disks, new_layout, new_chunk;
++};
++
++struct createinfo {
++ int uid;
++ int gid;
++ int autof;
++ int mode;
++ int symlinks;
++ struct supertype *supertype;
++};
++
++#define Name "mdadm"
++
++enum mode {
++ ASSEMBLE=1,
++ BUILD,
++ CREATE,
++ MANAGE,
++ MISC,
++ MONITOR,
++ GROW,
++ INCREMENTAL,
++ AUTODETECT,
++};
++
++extern char short_options[];
++extern char short_bitmap_auto_options[];
++extern struct option long_options[];
++extern char Version[], Usage[], Help[], OptionHelp[],
++ Help_create[], Help_build[], Help_assemble[], Help_grow[],
++ Help_incr[],
++ Help_manage[], Help_misc[], Help_monitor[], Help_config[];
++
++/* for option that don't have short equivilents, we assign arbitrary
++ * small numbers. '1' means an undecorated option, so we start at '2'.
++ */
++enum special_options {
++ AssumeClean = 2,
++ BitmapChunk,
++ WriteBehind,
++ ReAdd,
++ NoDegraded,
++ Sparc22,
++ BackupFile,
++ HomeHost,
++ AutoHomeHost,
++ Symlinks,
++ AutoDetect,
++};
++
++/* structures read from config file */
++/* List of mddevice names and identifiers
++ * Identifiers can be:
++ * uuid=128-hex-uuid
++ * super-minor=decimal-minor-number-from-superblock
++ * devices=comma,separated,list,of,device,names,with,wildcards
++ *
++ * If multiple fields are present, the intersection of all matching
++ * devices is considered
++ */
++#define UnSet (0xfffe)
++typedef struct mddev_ident_s {
++ char *devname;
++
++ int uuid_set;
++ int uuid[4];
++ char name[33];
++
++ unsigned int super_minor;
++
++ char *devices; /* comma separated list of device
++ * names with wild cards
++ */
++ int level;
++ unsigned int raid_disks;
++ unsigned int spare_disks;
++ struct supertype *st;
++ int autof; /* 1 for normal, 2 for partitioned */
++ char *spare_group;
++ char *bitmap_file;
++ int bitmap_fd;
++
++ struct mddev_ident_s *next;
++} *mddev_ident_t;
++
++/* List of device names - wildcards expanded */
++typedef struct mddev_dev_s {
++ char *devname;
++ char disposition; /* 'a' for add, 'r' for remove, 'f' for fail.
++ * Not set for names read from .config
++ */
++ char writemostly;
++ char re_add;
++ char used; /* set when used */
++ struct mddev_dev_s *next;
++} *mddev_dev_t;
++
++typedef struct mapping {
++ char *name;
++ int num;
++} mapping_t;
++
++
++struct mdstat_ent {
++ char *dev;
++ int devnum;
++ int active;
++ char *level;
++ char *pattern; /* U or up, _ for down */
++ int percent; /* -1 if no resync */
++ int resync; /* 1 if resync, 0 if recovery */
++ struct mdstat_ent *next;
++};
++
++extern struct mdstat_ent *mdstat_read(int hold, int start);
++extern void free_mdstat(struct mdstat_ent *ms);
++extern void mdstat_wait(int seconds);
++extern int mddev_busy(int devnum);
++
++struct map_ent {
++ struct map_ent *next;
++ int devnum;
++ int major,minor;
++ int uuid[4];
++ char *path;
++};
++extern int map_update(struct map_ent **mpp, int devnum, int major, int minor,
++ int uuid[4], char *path);
++extern struct map_ent *map_by_uuid(struct map_ent **map, int uuid[4]);
++extern void map_read(struct map_ent **melp);
++extern int map_write(struct map_ent *mel);
++extern void map_delete(struct map_ent **mapp, int devnum);
++extern void map_free(struct map_ent *map);
++extern void map_add(struct map_ent **melp,
++ int devnum, int major, int minor, int uuid[4], char *path);
++
++/* Data structure for holding info read from sysfs */
++struct sysdev {
++ char name[20];
++ int role;
++ int major, minor;
++ unsigned long long offset, size;
++ int state;
++ int errors;
++ struct sysdev *next;
++};
++struct sysarray {
++ char name[20];
++ struct sysdev *devs;
++ int chunk;
++ unsigned long long component_size;
++ int layout;
++ int level;
++ int spares;
++ int cache_size;
++ int mismatch_cnt;
++ int major_version, minor_version;
++};
++/* various details can be requested */
++#define GET_LEVEL 1
++#define GET_LAYOUT 2
++#define GET_COMPONENT 4
++#define GET_CHUNK 8
++#define GET_CACHE 16
++#define GET_MISMATCH 32
++#define GET_VERSION 64
++
++#define GET_DEVS 1024 /* gets role, major, minor */
++#define GET_OFFSET 2048
++#define GET_SIZE 4096
++#define GET_STATE 8192
++#define GET_ERROR 16384
++
++/* If fd >= 0, get the array it is open on,
++ * else use devnum. >=0 -> major9. <0.....
++ */
++extern void sysfs_free(struct sysarray *sra);
++extern struct sysarray *sysfs_read(int fd, int devnum, unsigned long options);
++extern int sysfs_set_str(struct sysarray *sra, struct sysdev *dev,
++ char *name, char *val);
++extern int sysfs_set_num(struct sysarray *sra, struct sysdev *dev,
++ char *name, unsigned long long val);
++extern int sysfs_get_ll(struct sysarray *sra, struct sysdev *dev,
++ char *name, unsigned long long *val);
++
++
++extern int save_stripes(int *source, unsigned long long *offsets,
++ int raid_disks, int chunk_size, int level, int layout,
++ int nwrites, int *dest,
++ unsigned long long start, unsigned long long length);
++extern int restore_stripes(int *dest, unsigned long long *offsets,
++ int raid_disks, int chunk_size, int level, int layout,
++ int source, unsigned long long read_offset,
++ unsigned long long start, unsigned long long length);
++
++#ifndef Sendmail
++#define Sendmail "/usr/lib/sendmail -t"
++#endif
++
++#define SYSLOG_FACILITY LOG_DAEMON
++
++extern char *map_num(mapping_t *map, int num);
++extern int map_name(mapping_t *map, char *name);
++extern mapping_t r5layout[], pers[], modes[], faultylayout[];
++
++extern char *map_dev(int major, int minor, int create);
++
++
++extern struct superswitch {
++ void (*examine_super)(void *sbv, char *homehost);
++ void (*brief_examine_super)(void *sbv);
++ void (*detail_super)(void *sbv, char *homehost);
++ void (*export_super)(void *sbv);
++ void (*brief_detail_super)(void *sbv);
++ void (*uuid_from_super)(int uuid[4], void *sbv);
++ void (*getinfo_super)(struct mdinfo *info, void *sbv);
++ int (*match_home)(void *sbv, char *homehost);
++ int (*update_super)(struct mdinfo *info, void *sbv, char *update,
++ char *devname, int verbose,
++ int uuid_set, char *homehost);
++ int (*init_super)(struct supertype *st, void **sbp, mdu_array_info_t *info, unsigned long long size, char *name, char *homehost, int *uuid);
++ void (*add_to_super)(void *sbv, mdu_disk_info_t *dinfo);
++ int (*store_super)(struct supertype *st, int fd, void *sbv);
++ int (*write_init_super)(struct supertype *st, void *sbv, mdu_disk_info_t *dinfo, char *devname);
++ int (*compare_super)(void **firstp, void *secondv);
++ int (*load_super)(struct supertype *st, int fd, void **sbp, char *devname);
++ struct supertype * (*match_metadata_desc)(char *arg);
++ __u64 (*avail_size)(struct supertype *st, __u64 size);
++ int (*add_internal_bitmap)(struct supertype *st, void *sbv, int *chunkp,
++ int delay, int write_behind,
++ unsigned long long size, int may_change, int major);
++ void (*locate_bitmap)(struct supertype *st, int fd, void *sbv);
++ int (*write_bitmap)(struct supertype *st, int fd, void *sbv);
++ int major;
++ int swapuuid; /* true if uuid is bigending rather than hostendian */
++} super0, super1, *superlist[];
++
++struct supertype {
++ struct superswitch *ss;
++ int minor_version;
++ int max_devs;
++};
++
++extern struct supertype *super_by_version(int vers, int minor);
++extern struct supertype *guess_super(int fd);
++extern int get_dev_size(int fd, char *dname, unsigned long long *sizep);
++extern void get_one_disk(int mdfd, mdu_array_info_t *ainf,
++ mdu_disk_info_t *disk);
++
++#if __GNUC__ < 3
++struct stat64;
++#endif
++
++#define HAVE_NFTW we assume
++#define HAVE_FTW
++
++#ifdef UCLIBC
++# include <features.h>
++# ifndef __UCLIBC_HAS_FTW__
++# undef HAVE_FTW
++# undef HAVE_NFTW
++# endif
++#endif
++
++#ifdef __dietlibc__
++# undef HAVE_NFTW
++#endif
++
++#ifndef HAVE_NFTW
++# define FTW_PHYS 1
++# ifndef HAVE_FTW
++ struct FTW {};
++# endif
++#endif
++
++#ifdef HAVE_FTW
++# include <ftw.h>
++#endif
++
++extern int add_dev(const char *name, const struct stat *stb, int flag, struct FTW *s);
++
++
++extern int Manage_ro(char *devname, int fd, int readonly);
++extern int Manage_runstop(char *devname, int fd, int runstop, int quiet);
++extern int Manage_resize(char *devname, int fd, long long size, int raid_disks);
++extern int Manage_reconfig(char *devname, int fd, int layout);
++extern int Manage_subdevs(char *devname, int fd,
++ mddev_dev_t devlist, int verbose);
++extern int autodetect(void);
++extern int Grow_Add_device(char *devname, int fd, char *newdev);
++extern int Grow_addbitmap(char *devname, int fd, char *file, int chunk, int delay, int write_behind, int force);
++extern int Grow_reshape(char *devname, int fd, int quiet, char *backup_file,
++ long long size,
++ int level, int layout, int chunksize, int raid_disks);
++extern int Grow_restart(struct supertype *st, struct mdinfo *info,
++ int *fdlist, int cnt, char *backup_file);
++
++
++extern int Assemble(struct supertype *st, char *mddev, int mdfd,
++ mddev_ident_t ident,
++ mddev_dev_t devlist, char *backup_file,
++ int readonly, int runstop,
++ char *update, char *homehost,
++ int verbose, int force);
++
++extern int Build(char *mddev, int mdfd, int chunk, int level, int layout,
++ int raiddisks,
++ mddev_dev_t devlist, int assume_clean,
++ char *bitmap_file, int bitmap_chunk, int write_behind, int delay, int verbose);
++
++
++extern int Create(struct supertype *st, char *mddev, int mdfd,
++ int chunk, int level, int layout, unsigned long long size, int raiddisks, int sparedisks,
++ char *name, char *homehost, int *uuid,
++ int subdevs, mddev_dev_t devlist,
++ int runstop, int verbose, int force, int assume_clean,
++ char *bitmap_file, int bitmap_chunk, int write_behind, int delay);
++
++extern int Detail(char *dev, int brief, int export, int test, char *homehost);
++extern int Query(char *dev);
++
++extern int md_get_version(int fd);
++extern int get_linux_version(void);
++extern int parse_uuid(char *str, int uuid[4]);
++extern int check_ext2(int fd, char *name);
++extern int check_reiser(int fd, char *name);
++extern int check_raid(int fd, char *name);
++
++extern int get_mdp_major(void);
++extern int dev_open(char *dev, int flags);
++extern int is_standard(char *dev, int *nump);
++
++extern int parse_auto(char *str, char *msg, int config);
++extern mddev_ident_t conf_get_ident(char *dev);
++extern mddev_dev_t conf_get_devs(void);
++extern int conf_test_dev(char *devname);
++extern struct createinfo *conf_get_create_info(void);
++extern void set_conffile(char *file);
++extern char *conf_get_mailaddr(void);
++extern char *conf_get_mailfrom(void);
++extern char *conf_get_program(void);
++extern char *conf_get_homehost(void);
++extern char *conf_line(FILE *file);
++extern char *conf_word(FILE *file, int allow_key);
++extern void free_line(char *line);
++extern int match_oneof(char *devices, char *devname);
++extern void uuid_from_super(int uuid[4], mdp_super_t *super);
++extern int same_uuid(int a[4], int b[4], int swapuuid);
++extern void copy_uuid(void *a, int b[4], int swapuuid);
++/* extern int compare_super(mdp_super_t *first, mdp_super_t *second);*/
++extern unsigned long calc_csum(void *super, int bytes);
++extern int enough(int level, int raid_disks, int layout, int clean,
++ char *avail, int avail_disks);
++extern int ask(char *mesg);
++extern unsigned long long get_component_size(int fd);
++extern void remove_partitions(int fd);
++
++
++extern char *human_size(long long bytes);
++char *human_size_brief(long long bytes);
++
++extern void put_md_name(char *name);
++extern char *get_md_name(int dev);
++
++extern char DefaultConfFile[];
++
++extern int open_mddev(char *dev, int autof);
++extern int open_mddev_devnum(char *devname, int devnum, char *name,
++ char *chosen_name);
++
++
++#define LEVEL_MULTIPATH (-4)
++#define LEVEL_LINEAR (-1)
++#define LEVEL_FAULTY (-5)
++
++
++/* faulty stuff */
++
++#define WriteTransient 0
++#define ReadTransient 1
++#define WritePersistent 2
++#define ReadPersistent 3
++#define WriteAll 4 /* doesn't go to device */
++#define ReadFixable 5
++#define Modes 6
++
++#define ClearErrors 31
++#define ClearFaults 30
++
++#define AllPersist 100 /* internal use only */
++#define NoPersist 101
++
++#define ModeMask 0x1f
++#define ModeShift 5
++
++
++#ifdef __TINYC__
++#undef minor
++#undef major
++#undef makedev
++#define minor(x) ((x)&0xff)
++#define major(x) (((x)>>8)&0xff)
++#define makedev(M,m) (((M)<<8) | (m))
++#endif
++
++/* for raid5 */
++#define ALGORITHM_LEFT_ASYMMETRIC 0
++#define ALGORITHM_RIGHT_ASYMMETRIC 1
++#define ALGORITHM_LEFT_SYMMETRIC 2
++#define ALGORITHM_RIGHT_SYMMETRIC 3
+--- a/mdadm/mdassemble.c 1970-01-01 03:00:00.000000000 +0300
++++ mdadm/mdadm/mdassemble.c 2011-01-12 21:33:01.000000000 +0200
+@@ -0,0 +1,908 @@
++/*
++ * mdadm - manage Linux "md" devices aka RAID arrays.
++ *
++ * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * Author: Neil Brown
++ * Email: <neilb@cse.unsw.edu.au>
++ * Paper: Neil Brown
++ * School of Computer Science and Engineering
++ * The University of New South Wales
++ * Sydney, 2052
++ * Australia
++ */
++
++#include "mdadm.h"
++#include <ctype.h>
++
++static int name_matches(char *found, char *required, char *homehost)
++{
++ /* See if the name found matches the required name, possibly
++ * prefixed with 'homehost'
++ */
++ char fnd[33];
++
++ strncpy(fnd, found, 32);
++ fnd[32] = 0;
++ if (strcmp(found, required)==0)
++ return 1;
++ if (homehost) {
++ int l = strlen(homehost);
++ if (l < 32 && fnd[l] == ':' &&
++ strcmp(fnd+l+1, required)==0)
++ return 1;
++ }
++ return 0;
++}
++
++int open_mddev(char *dev, int autof/*unused */)
++{
++ int mdfd = open(dev, O_RDWR, 0);
++ if (mdfd < 0)
++ fprintf(stderr, Name ": error opening %s: %s\n",
++ dev, strerror(errno));
++ else if (md_get_version(mdfd) <= 0) {
++ fprintf(stderr, Name ": %s does not appear to be an md device\n",
++ dev);
++ close(mdfd);
++ mdfd = -1;
++ }
++ return mdfd;
++}
++
++int Assemble(struct supertype *st, char *mddev, int mdfd,
++ mddev_ident_t ident,
++ mddev_dev_t devlist, char *backup_file,
++ int readonly, int runstop,
++ char *update, char *homehost,
++ int verbose, int force)
++{
++ /*
++ * The task of Assemble is to find a collection of
++ * devices that should (according to their superblocks)
++ * form an array, and to give this collection to the MD driver.
++ * In Linux-2.4 and later, this involves submitting a
++ * SET_ARRAY_INFO ioctl with no arg - to prepare
++ * the array - and then submit a number of
++ * ADD_NEW_DISK ioctls to add disks into
++ * the array. Finally RUN_ARRAY might
++ * be submitted to start the array.
++ *
++ * Much of the work of Assemble is in finding and/or
++ * checking the disks to make sure they look right.
++ *
++ * If mddev is not set, then scan must be set and we
++ * read through the config file for dev+uuid mapping
++ * We recurse, setting mddev, for each device that
++ * - isn't running
++ * - has a valid uuid (or any uuid if !uuidset)
++ *
++ * If mddev is set, we try to determine state of md.
++ * check version - must be at least 0.90.0
++ * check kernel version. must be at least 2.4.
++ * If not, we can possibly fall back on START_ARRAY
++ * Try to GET_ARRAY_INFO.
++ * If possible, give up
++ * If not, try to STOP_ARRAY just to make sure
++ *
++ * If !uuidset and scan, look in conf-file for uuid
++ * If not found, give up
++ * If !devlist and scan and uuidset, get list of devs from conf-file
++ *
++ * For each device:
++ * Check superblock - discard if bad
++ * Check uuid (set if we don't have one) - discard if no match
++ * Check superblock similarity if we have a superblock - discard if different
++ * Record events, devicenum
++ * This should give us a list of devices for the array
++ * We should collect the most recent event number
++ *
++ * Count disks with recent enough event count
++ * While force && !enough disks
++ * Choose newest rejected disks, update event count
++ * mark clean and rewrite superblock
++ * If recent kernel:
++ * SET_ARRAY_INFO
++ * foreach device with recent events : ADD_NEW_DISK
++ * if runstop == 1 || "enough" disks and runstop==0 -> RUN_ARRAY
++ * If old kernel:
++ * Check the device numbers in superblock are right
++ * update superblock if any changes
++ * START_ARRAY
++ *
++ */
++ int clean = 0;
++ int old_linux = 0;
++ int vers = 0; /* Keep gcc quite - it really is initialised */
++ void *first_super = NULL, *super = NULL;
++ struct {
++ char *devname;
++ unsigned int major, minor;
++ unsigned int oldmajor, oldminor;
++ long long events;
++ int uptodate;
++ int state;
++ int raid_disk;
++ int disk_nr;
++ } *devices;
++ int *best = NULL; /* indexed by raid_disk */
++ unsigned int bestcnt = 0;
++ int devcnt = 0;
++ unsigned int okcnt, sparecnt;
++ unsigned int req_cnt;
++ unsigned int i;
++ int most_recent = 0;
++ int chosen_drive;
++ int change = 0;
++ int inargv = 0;
++ int bitmap_done;
++ int start_partial_ok = (runstop >= 0) && (force || devlist==NULL || mdfd < 0);
++ unsigned int num_devs;
++ mddev_dev_t tmpdev;
++ struct mdinfo info;
++ char *avail;
++ int nextspare = 0;
++
++ if (mdfd < 0)
++ return 2;
++
++ if (get_linux_version() < 2004000)
++ old_linux = 1;
++
++ if (mdfd >= 0) {
++ vers = md_get_version(mdfd);
++ if (vers <= 0) {
++ fprintf(stderr, Name ": %s appears not to be an md device.\n", mddev);
++ return 1;
++ }
++ if (vers < 9000) {
++ fprintf(stderr, Name ": Assemble requires driver version 0.90.0 or later.\n"
++ " Upgrade your kernel or try --build\n");
++ return 1;
++ }
++
++ if (ioctl(mdfd, GET_ARRAY_INFO, &info.array)>=0) {
++ fprintf(stderr, Name ": device %s already active - cannot assemble it\n",
++ mddev);
++ return 1;
++ }
++ ioctl(mdfd, STOP_ARRAY, NULL); /* just incase it was started but has no content */
++ }
++ /*
++ * If any subdevs are listed, then any that don't
++ * match ident are discarded. Remainder must all match and
++ * become the array.
++ * If no subdevs, then we scan all devices in the config file, but
++ * there must be something in the identity
++ */
++
++ if (!devlist &&
++ ident->uuid_set == 0 &&
++ ident->super_minor < 0 &&
++ ident->devices == NULL) {
++ fprintf(stderr, Name ": No identity information available for %s - cannot assemble.\n",
++ mddev ? mddev : "further assembly");
++ return 1;
++ }
++ if (devlist == NULL)
++ devlist = conf_get_devs();
++ else if (mdfd >= 0)
++ inargv = 1;
++
++ tmpdev = devlist; num_devs = 0;
++ while (tmpdev) {
++ if (tmpdev->used)
++ tmpdev->used = 2;
++ else
++ num_devs++;
++ tmpdev = tmpdev->next;
++ }
++ devices = malloc(num_devs * sizeof(*devices));
++
++ if (!st && ident->st) st = ident->st;
++
++ if (verbose>0)
++ fprintf(stderr, Name ": looking for devices for %s\n",
++ mddev ? mddev : "further assembly");
++
++ /* first walk the list of devices to find a consistent set
++ * that match the criterea, if that is possible.
++ * We flag the one we like with 'used'.
++ */
++ for (tmpdev = devlist;
++ tmpdev;
++ tmpdev = tmpdev->next) {
++ char *devname = tmpdev->devname;
++ int dfd;
++ struct stat stb;
++ struct supertype *tst = st;
++
++ if (tmpdev->used > 1) continue;
++
++ if (ident->devices &&
++ !match_oneof(ident->devices, devname)) {
++ if ((inargv && verbose>=0) || verbose > 0)
++ fprintf(stderr, Name ": %s is not one of %s\n", devname, ident->devices);
++ continue;
++ }
++
++ if (super) {
++ free(super);
++ super = NULL;
++ }
++
++ dfd = dev_open(devname, O_RDONLY|O_EXCL);
++ if (dfd < 0) {
++ if ((inargv && verbose >= 0) || verbose > 0)
++ fprintf(stderr, Name ": cannot open device %s: %s\n",
++ devname, strerror(errno));
++ tmpdev->used = 2;
++ } else if (fstat(dfd, &stb)< 0) {
++ /* Impossible! */
++ fprintf(stderr, Name ": fstat failed for %s: %s\n",
++ devname, strerror(errno));
++ tmpdev->used = 2;
++ } else if ((stb.st_mode & S_IFMT) != S_IFBLK) {
++ fprintf(stderr, Name ": %s is not a block device.\n",
++ devname);
++ tmpdev->used = 2;
++ } else if (!tst && (tst = guess_super(dfd)) == NULL) {
++ if ((inargv && verbose >= 0) || verbose > 0)
++ fprintf(stderr, Name ": no recogniseable superblock on %s\n",
++ devname);
++ tmpdev->used = 2;
++ } else if (tst->ss->load_super(tst,dfd, &super, NULL)) {
++ if ((inargv && verbose >= 0) || verbose > 0)
++ fprintf( stderr, Name ": no RAID superblock on %s\n",
++ devname);
++ } else {
++ tst->ss->getinfo_super(&info, super);
++ }
++ if (dfd >= 0) close(dfd);
++
++ if (ident->uuid_set && (!update || strcmp(update, "uuid")!= 0) &&
++ (!super || same_uuid(info.uuid, ident->uuid, tst->ss->swapuuid)==0)) {
++ if ((inargv && verbose >= 0) || verbose > 0)
++ fprintf(stderr, Name ": %s has wrong uuid.\n",
++ devname);
++ continue;
++ }
++ if (ident->name[0] && (!update || strcmp(update, "name")!= 0) &&
++ (!super || name_matches(info.name, ident->name, homehost)==0)) {
++ if ((inargv && verbose >= 0) || verbose > 0)
++ fprintf(stderr, Name ": %s has wrong name.\n",
++ devname);
++ continue;
++ }
++ if (ident->super_minor != UnSet &&
++ (!super || ident->super_minor != info.array.md_minor)) {
++ if ((inargv && verbose >= 0) || verbose > 0)
++ fprintf(stderr, Name ": %s has wrong super-minor.\n",
++ devname);
++ continue;
++ }
++ if (ident->level != UnSet &&
++ (!super|| ident->level != info.array.level)) {
++ if ((inargv && verbose >= 0) || verbose > 0)
++ fprintf(stderr, Name ": %s has wrong raid level.\n",
++ devname);
++ continue;
++ }
++ if (ident->raid_disks != UnSet &&
++ (!super || ident->raid_disks!= info.array.raid_disks)) {
++ if ((inargv && verbose >= 0) || verbose > 0)
++ fprintf(stderr, Name ": %s requires wrong number of drives.\n",
++ devname);
++ continue;
++ }
++ if (mdfd < 0) {
++ if (tst == NULL || super == NULL)
++ continue;
++ if (update == NULL &&
++ tst->ss->match_home(super, homehost)==0) {
++ if ((inargv && verbose >= 0) || verbose > 0)
++ fprintf(stderr, Name ": %s is not built for host %s.\n",
++ devname, homehost);
++ /* Auto-assemble, and this is not a usable host */
++ /* if update != NULL, we are updating the host
++ * name... */
++ continue;
++ }
++ }
++ /* If we are this far, then we are nearly commited to this device.
++ * If the super_block doesn't exist, or doesn't match others,
++ * then we probably cannot continue
++ * However if one of the arrays is for the homehost, and
++ * the other isn't that can disambiguate.
++ */
++
++ if (!super) {
++ fprintf(stderr, Name ": %s has no superblock - assembly aborted\n",
++ devname);
++ free(first_super);
++ return 1;
++ }
++
++ if (st == NULL)
++ st = tst;
++ if (st->ss != tst->ss ||
++ st->minor_version != tst->minor_version ||
++ st->ss->compare_super(&first_super, super) != 0) {
++ /* Some mismatch. If exactly one array matches this host,
++ * we can resolve on that one.
++ * Or, if we are auto assembling, we just ignore the second
++ * for now.
++ */
++ if (mdfd < 0)
++ continue;
++ if (homehost) {
++ int first = st->ss->match_home(first_super, homehost);
++ int last = tst->ss->match_home(super, homehost);
++ if (first+last == 1) {
++ /* We can do something */
++ if (first) {/* just ignore this one */
++ if ((inargv && verbose >= 0) || verbose > 0)
++ fprintf(stderr, Name ": %s misses out due to wrong homehost\n",
++ devname);
++ continue;
++ } else { /* reject all those sofar */
++ mddev_dev_t td;
++ if ((inargv && verbose >= 0) || verbose > 0)
++ fprintf(stderr, Name ": %s overrides previous devices due to good homehost\n",
++ devname);
++ for (td=devlist; td != tmpdev; td=td->next)
++ if (td->used == 1)
++ td->used = 0;
++ tmpdev->used = 1;
++ continue;
++ }
++ }
++ }
++ fprintf(stderr, Name ": superblock on %s doesn't match others - assembly aborted\n",
++ devname);
++ free(super);
++ free(first_super);
++ return 1;
++ }
++
++ tmpdev->used = 1;
++ }
++
++ /* Ok, no bad inconsistancy, we can try updating etc */
++ bitmap_done = 0;
++ for (tmpdev = devlist; tmpdev; tmpdev=tmpdev->next) if (tmpdev->used == 1) {
++ char *devname = tmpdev->devname;
++ struct stat stb;
++ /* looks like a good enough match to update the super block if needed */
++ {
++ int dfd;
++ dfd = dev_open(devname, O_RDWR|O_EXCL);
++
++ remove_partitions(dfd);
++
++ if (super) {
++ free(super);
++ super = NULL;
++ }
++
++ st->ss->load_super(st, dfd, &super, NULL);
++ st->ss->getinfo_super(&info, super);
++ close(dfd);
++ }
++
++ stat(devname, &stb);
++
++ if (verbose > 0)
++ fprintf(stderr, Name ": %s is identified as a member of %s, slot %d.\n",
++ devname, mddev, info.disk.raid_disk);
++ devices[devcnt].devname = devname;
++ devices[devcnt].major = major(stb.st_rdev);
++ devices[devcnt].minor = minor(stb.st_rdev);
++ devices[devcnt].oldmajor = info.disk.major;
++ devices[devcnt].oldminor = info.disk.minor;
++ devices[devcnt].events = info.events;
++ devices[devcnt].raid_disk = info.disk.raid_disk;
++ devices[devcnt].disk_nr = info.disk.number;
++ devices[devcnt].uptodate = 0;
++ devices[devcnt].state = info.disk.state;
++ if (most_recent < devcnt) {
++ if (devices[devcnt].events
++ > devices[most_recent].events)
++ most_recent = devcnt;
++ }
++ if (info.array.level == -4)
++ /* with multipath, the raid_disk from the superblock is meaningless */
++ i = devcnt;
++ else
++ i = devices[devcnt].raid_disk;
++ if (i+1 == 0) {
++ if (nextspare < info.array.raid_disks)
++ nextspare = info.array.raid_disks;
++ i = nextspare++;
++ } else {
++ if (i >= info.array.raid_disks &&
++ i >= nextspare)
++ nextspare = i+1;
++ }
++ if (i < 10000) {
++ if (i >= bestcnt) {
++ unsigned int newbestcnt = i+10;
++ int *newbest = malloc(sizeof(int)*newbestcnt);
++ unsigned int c;
++ for (c=0; c < newbestcnt; c++)
++ if (c < bestcnt)
++ newbest[c] = best[c];
++ else
++ newbest[c] = -1;
++ if (best)free(best);
++ best = newbest;
++ bestcnt = newbestcnt;
++ }
++ if (best[i] >=0 &&
++ devices[best[i]].events == devices[devcnt].events &&
++ devices[best[i]].minor != devices[devcnt].minor &&
++ st->ss->major == 0 &&
++ info.array.level != -4) {
++ /* two different devices with identical superblock.
++ * Could be a mis-detection caused by overlapping
++ * partitions. fail-safe.
++ */
++ fprintf(stderr, Name ": WARNING %s and %s appear"
++ " to have very similar superblocks.\n"
++ " If they are really different, "
++ "please --zero the superblock on one\n"
++ " If they are the same or overlap,"
++ " please remove one from %s.\n",
++ devices[best[i]].devname, devname,
++ inargv ? "the list" :
++ "the\n DEVICE list in mdadm.conf"
++ );
++ return 1;
++ }
++ if (best[i] == -1
++ || devices[best[i]].events < devices[devcnt].events)
++ best[i] = devcnt;
++ }
++ devcnt++;
++ }
++
++ if (super)
++ free(super);
++ super = NULL;
++
++ if (update && strcmp(update, "byteorder")==0)
++ st->minor_version = 90;
++
++ if (devcnt == 0) {
++ fprintf(stderr, Name ": no devices found for %s\n",
++ mddev);
++ free(first_super);
++ return 1;
++ }
++
++ st->ss->getinfo_super(&info, first_super);
++ clean = info.array.state & 1;
++
++ /* now we have some devices that might be suitable.
++ * I wonder how many
++ */
++ avail = malloc(info.array.raid_disks);
++ memset(avail, 0, info.array.raid_disks);
++ okcnt = 0;
++ sparecnt=0;
++ for (i=0; i< bestcnt ;i++) {
++ int j = best[i];
++ int event_margin = 1; /* always allow a difference of '1'
++ * like the kernel does
++ */
++ if (j < 0) continue;
++ /* note: we ignore error flags in multipath arrays
++ * as they don't make sense
++ */
++ if (info.array.level != -4)
++ if (!(devices[j].state & (1<<MD_DISK_SYNC))) {
++ if (!(devices[j].state & (1<<MD_DISK_FAULTY)))
++ sparecnt++;
++ continue;
++ }
++ if (devices[j].events+event_margin >=
++ devices[most_recent].events) {
++ devices[j].uptodate = 1;
++ if (i < info.array.raid_disks) {
++ okcnt++;
++ avail[i]=1;
++ } else
++ sparecnt++;
++ }
++ }
++ while (force && !enough(info.array.level, info.array.raid_disks,
++ info.array.layout, 1,
++ avail, okcnt)) {
++ /* Choose the newest best drive which is
++ * not up-to-date, update the superblock
++ * and add it.
++ */
++ int fd;
++ long long current_events;
++ chosen_drive = -1;
++ for (i=0; i<info.array.raid_disks && i < bestcnt; i++) {
++ int j = best[i];
++ if (j>=0 &&
++ !devices[j].uptodate &&
++ devices[j].events > 0 &&
++ (chosen_drive < 0 ||
++ devices[j].events > devices[chosen_drive].events))
++ chosen_drive = j;
++ }
++ if (chosen_drive < 0)
++ break;
++ current_events = devices[chosen_drive].events;
++ add_another:
++ if (verbose >= 0)
++ fprintf(stderr, Name ": forcing event count in %s(%d) from %d upto %d\n",
++ devices[chosen_drive].devname, devices[chosen_drive].raid_disk,
++ (int)(devices[chosen_drive].events),
++ (int)(devices[most_recent].events));
++ fd = dev_open(devices[chosen_drive].devname, O_RDWR|O_EXCL);
++ if (fd < 0) {
++ fprintf(stderr, Name ": Couldn't open %s for write - not updating\n",
++ devices[chosen_drive].devname);
++ devices[chosen_drive].events = 0;
++ continue;
++ }
++ if (st->ss->load_super(st,fd, &super, NULL)) {
++ close(fd);
++ fprintf(stderr, Name ": RAID superblock disappeared from %s - not updating.\n",
++ devices[chosen_drive].devname);
++ devices[chosen_drive].events = 0;
++ continue;
++ }
++ info.events = devices[most_recent].events;
++ st->ss->update_super(&info, super, "force-one",
++ devices[chosen_drive].devname, verbose,
++ 0, NULL);
++
++ if (st->ss->store_super(st, fd, super)) {
++ close(fd);
++ fprintf(stderr, Name ": Could not re-write superblock on %s\n",
++ devices[chosen_drive].devname);
++ devices[chosen_drive].events = 0;
++ free(super);
++ continue;
++ }
++ close(fd);
++ devices[chosen_drive].events = devices[most_recent].events;
++ devices[chosen_drive].uptodate = 1;
++ avail[chosen_drive] = 1;
++ okcnt++;
++ free(super);
++
++ /* If there are any other drives of the same vintage,
++ * add them in as well. We can't lose and we might gain
++ */
++ for (i=0; i<info.array.raid_disks && i < bestcnt ; i++) {
++ int j = best[i];
++ if (j >= 0 &&
++ !devices[j].uptodate &&
++ devices[j].events > 0 &&
++ devices[j].events == current_events) {
++ chosen_drive = j;
++ goto add_another;
++ }
++ }
++ }
++
++ /* Now we want to look at the superblock which the kernel will base things on
++ * and compare the devices that we think are working with the devices that the
++ * superblock thinks are working.
++ * If there are differences and --force is given, then update this chosen
++ * superblock.
++ */
++ chosen_drive = -1;
++ super = NULL;
++ for (i=0; chosen_drive < 0 && i<bestcnt; i++) {
++ int j = best[i];
++ int fd;
++
++ if (j<0)
++ continue;
++ if (!devices[j].uptodate)
++ continue;
++ chosen_drive = j;
++ if ((fd=dev_open(devices[j].devname, O_RDONLY|O_EXCL))< 0) {
++ fprintf(stderr, Name ": Cannot open %s: %s\n",
++ devices[j].devname, strerror(errno));
++ return 1;
++ }
++ if (st->ss->load_super(st,fd, &super, NULL)) {
++ close(fd);
++ fprintf(stderr, Name ": RAID superblock has disappeared from %s\n",
++ devices[j].devname);
++ return 1;
++ }
++ close(fd);
++ }
++ if (super == NULL) {
++ fprintf(stderr, Name ": No suitable drives found for %s\n", mddev);
++ return 1;
++ }
++ st->ss->getinfo_super(&info, super);
++ for (i=0; i<bestcnt; i++) {
++ int j = best[i];
++ unsigned int desired_state;
++
++ if (i < info.array.raid_disks)
++ desired_state = (1<<MD_DISK_ACTIVE) | (1<<MD_DISK_SYNC);
++ else
++ desired_state = 0;
++
++ if (j<0)
++ continue;
++ if (!devices[j].uptodate)
++ continue;
++ info.disk.number = devices[j].disk_nr;
++ info.disk.raid_disk = i;
++ info.disk.state = desired_state;
++
++ if (devices[j].uptodate &&
++ st->ss->update_super(&info, super, "assemble", NULL, verbose, 0, NULL)) {
++ if (force) {
++ if (verbose >= 0)
++ fprintf(stderr, Name ": "
++ "clearing FAULTY flag for device %d in %s for %s\n",
++ j, mddev, devices[j].devname);
++ change = 1;
++ } else {
++ if (verbose >= -1)
++ fprintf(stderr, Name ": "
++ "device %d in %s has wrong state in superblock, but %s seems ok\n",
++ i, mddev, devices[j].devname);
++ }
++ }
++#if 0
++ if (!devices[j].uptodate &&
++ !(super.disks[i].state & (1 << MD_DISK_FAULTY))) {
++ fprintf(stderr, Name ": devices %d of %s is not marked FAULTY in superblock, but cannot be found\n",
++ i, mddev);
++ }
++#endif
++ }
++ if (force && !clean &&
++ !enough(info.array.level, info.array.raid_disks,
++ info.array.layout, clean,
++ avail, okcnt)) {
++ change += st->ss->update_super(&info, super, "force-array",
++ devices[chosen_drive].devname, verbose,
++ 0, NULL);
++ clean = 1;
++ }
++
++ if (change) {
++ int fd;
++ fd = dev_open(devices[chosen_drive].devname, O_RDWR|O_EXCL);
++ if (fd < 0) {
++ fprintf(stderr, Name ": Could not open %s for write - cannot Assemble array.\n",
++ devices[chosen_drive].devname);
++ return 1;
++ }
++ if (st->ss->store_super(st, fd, super)) {
++ close(fd);
++ fprintf(stderr, Name ": Could not re-write superblock on %s\n",
++ devices[chosen_drive].devname);
++ return 1;
++ }
++ close(fd);
++ }
++
++ /* count number of in-sync devices according to the superblock.
++ * We must have this number to start the array without -s or -R
++ */
++ req_cnt = info.array.working_disks;
++
++ /* Almost ready to actually *do* something */
++ if (!old_linux) {
++ int rv;
++ if ((vers % 100) >= 1) { /* can use different versions */
++ mdu_array_info_t inf;
++ memset(&inf, 0, sizeof(inf));
++ inf.major_version = st->ss->major;
++ inf.minor_version = st->minor_version;
++ rv = ioctl(mdfd, SET_ARRAY_INFO, &inf);
++ } else
++ rv = ioctl(mdfd, SET_ARRAY_INFO, NULL);
++
++ if (rv) {
++ fprintf(stderr, Name ": SET_ARRAY_INFO failed for %s: %s\n",
++ mddev, strerror(errno));
++ return 1;
++ }
++ if (ident->bitmap_fd >= 0) {
++ if (ioctl(mdfd, SET_BITMAP_FILE, ident->bitmap_fd) != 0) {
++ fprintf(stderr, Name ": SET_BITMAP_FILE failed.\n");
++ return 1;
++ }
++ } else if (ident->bitmap_file) {
++ /* From config file */
++ int bmfd = open(ident->bitmap_file, O_RDWR);
++ if (bmfd < 0) {
++ fprintf(stderr, Name ": Could not open bitmap file %s\n",
++ ident->bitmap_file);
++ return 1;
++ }
++ if (ioctl(mdfd, SET_BITMAP_FILE, bmfd) != 0) {
++ fprintf(stderr, Name ": Failed to set bitmapfile for %s\n", mddev);
++ close(bmfd);
++ return 1;
++ }
++ close(bmfd);
++ }
++
++ /* First, add the raid disks, but add the chosen one last */
++ for (i=0; i<= bestcnt; i++) {
++ int j;
++ if (i < bestcnt) {
++ j = best[i];
++ if (j == chosen_drive)
++ continue;
++ } else
++ j = chosen_drive;
++
++ if (j >= 0 /* && devices[j].uptodate */) {
++ mdu_disk_info_t disk;
++ memset(&disk, 0, sizeof(disk));
++ disk.major = devices[j].major;
++ disk.minor = devices[j].minor;
++ if (ioctl(mdfd, ADD_NEW_DISK, &disk)!=0) {
++ fprintf(stderr, Name ": failed to add %s to %s: %s\n",
++ devices[j].devname,
++ mddev,
++ strerror(errno));
++ if (i < info.array.raid_disks || i == bestcnt)
++ okcnt--;
++ else
++ sparecnt--;
++ } else if (verbose > 0)
++ fprintf(stderr, Name ": added %s to %s as %d\n",
++ devices[j].devname, mddev, devices[j].raid_disk);
++ } else if (verbose > 0 && i < info.array.raid_disks)
++ fprintf(stderr, Name ": no uptodate device for slot %d of %s\n",
++ i, mddev);
++ }
++
++ if (runstop == 1 ||
++ (runstop <= 0 &&
++ ( enough(info.array.level, info.array.raid_disks,
++ info.array.layout, clean, avail, okcnt) &&
++ (okcnt >= req_cnt || start_partial_ok)
++ ))) {
++ if (ioctl(mdfd, RUN_ARRAY, NULL)==0) {
++ if (verbose >= 0) {
++ fprintf(stderr, Name ": %s has been started with %d drive%s",
++ mddev, okcnt, okcnt==1?"":"s");
++ if (okcnt < info.array.raid_disks)
++ fprintf(stderr, " (out of %d)", info.array.raid_disks);
++ if (sparecnt)
++ fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s");
++ fprintf(stderr, ".\n");
++ }
++ return 0;
++ }
++ fprintf(stderr, Name ": failed to RUN_ARRAY %s: %s\n",
++ mddev, strerror(errno));
++
++ if (!enough(info.array.level, info.array.raid_disks,
++ info.array.layout, 1, avail, okcnt))
++ fprintf(stderr, Name ": Not enough devices to "
++ "start the array.\n");
++ else if (!enough(info.array.level,
++ info.array.raid_disks,
++ info.array.layout, clean,
++ avail, okcnt))
++ fprintf(stderr, Name ": Not enough devices to "
++ "start the array while not clean "
++ "- consider --force.\n");
++
++ return 1;
++ }
++ if (runstop == -1) {
++ fprintf(stderr, Name ": %s assembled from %d drive%s",
++ mddev, okcnt, okcnt==1?"":"s");
++ if (okcnt != info.array.raid_disks)
++ fprintf(stderr, " (out of %d)", info.array.raid_disks);
++ fprintf(stderr, ", but not started.\n");
++ return 0;
++ }
++ if (verbose >= -1) {
++ fprintf(stderr, Name ": %s assembled from %d drive%s", mddev, okcnt, okcnt==1?"":"s");
++ if (sparecnt)
++ fprintf(stderr, " and %d spare%s", sparecnt, sparecnt==1?"":"s");
++ if (!enough(info.array.level, info.array.raid_disks,
++ info.array.layout, 1, avail, okcnt))
++ fprintf(stderr, " - not enough to start the array.\n");
++ else if (!enough(info.array.level,
++ info.array.raid_disks,
++ info.array.layout, clean,
++ avail, okcnt))
++ fprintf(stderr, " - not enough to start the "
++ "array while not clean - consider "
++ "--force.\n");
++ else {
++ if (req_cnt == info.array.raid_disks)
++ fprintf(stderr, " - need all %d to start it", req_cnt);
++ else
++ fprintf(stderr, " - need %d of %d to start", req_cnt, info.array.raid_disks);
++ fprintf(stderr, " (use --run to insist).\n");
++ }
++ }
++ return 1;
++ } else {
++ /* The "chosen_drive" is a good choice, and if necessary, the superblock has
++ * been updated to point to the current locations of devices.
++ * so we can just start the array
++ */
++ unsigned long dev;
++ dev = makedev(devices[chosen_drive].major,
++ devices[chosen_drive].minor);
++ if (ioctl(mdfd, START_ARRAY, dev)) {
++ fprintf(stderr, Name ": Cannot start array: %s\n",
++ strerror(errno));
++ }
++
++ }
++ return 0;
++}
++
++int mdfd = -1;
++int runstop = 0;
++int readonly = 0;
++int verbose = 0;
++int force = 0;
++
++int mdassemble_main(int argc, char **argv) {
++ mddev_ident_t array_list = conf_get_ident(NULL);
++ int minor;
++ if (!array_list) {
++ fprintf(stderr, Name ": No arrays found in config file\n");
++ return 1;
++ } else {
++ for (; array_list; array_list = array_list->next) {
++ mdu_array_info_t array;
++ if (!strncmp("/dev/md", array_list->devname, 7)) {
++ errno = 0;
++ minor = strtoul(array_list->devname + 7, NULL, 0);
++ if (!errno) {
++ mknod(array_list->devname, S_IFBLK|0600, makedev(MD_MAJOR, minor));
++ }
++ }
++ mdfd = open_mddev(array_list->devname, array_list->autof);
++ if (mdfd < 0) {
++
++ fprintf(stderr, Name ": failed to open array\n");
++ continue;
++ }
++ if (ioctl(mdfd, GET_ARRAY_INFO, &array) < 0) {
++ Assemble(array_list->st, array_list->devname, mdfd,
++ array_list, NULL, NULL,
++ readonly, runstop, NULL, NULL, verbose, force);
++ }
++ close(mdfd);
++ }
++ }
++ return 0;
++}
++
+--- a/mdadm/mdexamine.c 1970-01-01 03:00:00.000000000 +0300
++++ mdadm/mdadm/mdexamine.c 2011-01-12 21:33:01.000000000 +0200
+@@ -0,0 +1,157 @@
++/*
++ * mdadm - manage Linux "md" devices aka RAID arrays.
++ *
++ * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * Author: Neil Brown
++ * Email: <neilb@cse.unsw.edu.au>
++ * Paper: Neil Brown
++ * School of Computer Science and Engineering
++ * The University of New South Wales
++ * Sydney, 2052
++ * Australia
++ */
++
++#include "mdadm.h"
++#include "dlink.h"
++
++#if ! defined(__BIG_ENDIAN) && ! defined(__LITTLE_ENDIAN)
++#error no endian defined
++#endif
++#include "md_u.h"
++#include "md_p.h"
++
++static int Examine(mddev_dev_t devlist, int brief, int scan,
++ int SparcAdjust, struct supertype *forcest,
++ char *homehost)
++{
++
++ /* Read the raid superblock from a device and
++ * display important content.
++ *
++ * If cannot be found, print reason: too small, bad magic
++ *
++ * Print:
++ * version, ctime, level, size, raid+spare+
++ * prefered minor
++ * uuid
++ *
++ * utime, state etc
++ *
++ * If (brief) gather devices for same array and just print a mdadm.conf line including devices=
++ * if devlist==NULL, use conf_get_devs()
++ */
++ int fd;
++ void *super = NULL;
++ int rv = 0;
++ int err = 0;
++
++ struct array {
++ void *super;
++ struct supertype *st;
++ struct mdinfo info;
++ void *devs;
++ struct array *next;
++ int spares;
++ } *arrays = NULL;
++
++ for (; devlist ; devlist=devlist->next) {
++ struct supertype *st = forcest;
++
++ fd = dev_open(devlist->devname, O_RDONLY);
++ if (fd < 0) {
++ if (!scan) {
++ fprintf(stderr,Name ": cannot open %s: %s\n",
++ devlist->devname, strerror(errno));
++ rv = 1;
++ }
++ err = 1;
++ }
++ else {
++ if (!st)
++ st = guess_super(fd);
++ if (st)
++ err = st->ss->load_super(st, fd, &super, (brief||scan)?NULL:devlist->devname);
++ else {
++ if (!brief) {
++ fprintf(stderr, Name ": No md superblock detected on %s.\n", devlist->devname);
++ rv = 1;
++ }
++ err = 1;
++ }
++ close(fd);
++ }
++ if (err)
++ continue;
++
++ if (SparcAdjust)
++ st->ss->update_super(NULL, super, "sparc2.2", devlist->devname, 0, 0, NULL);
++ /* Ok, its good enough to try, though the checksum could be wrong */
++ if (brief) {
++ struct array *ap;
++ char *d;
++ for (ap=arrays; ap; ap=ap->next) {
++ if (st->ss == ap->st->ss && st->ss->compare_super(&ap->super, super)==0)
++ break;
++ }
++ if (!ap) {
++ ap = malloc(sizeof(*ap));
++ ap->super = super;
++ ap->devs = dl_head();
++ ap->next = arrays;
++ ap->spares = 0;
++ ap->st = st;
++ arrays = ap;
++ st->ss->getinfo_super(&ap->info, super);
++ } else {
++ st->ss->getinfo_super(&ap->info, super);
++ free(super);
++ }
++ if (!(ap->info.disk.state & MD_DISK_SYNC))
++ ap->spares++;
++ d = dl_strdup(devlist->devname);
++ dl_add(ap->devs, d);
++ }
++ }
++ if (brief) {
++ struct array *ap;
++ for (ap=arrays; ap; ap=ap->next) {
++ char sep='=';
++ char *d;
++ ap->st->ss->brief_examine_super(ap->super);
++ if (ap->spares) printf(" spares=%d", ap->spares);
++ if (brief > 1) {
++ printf(" devices");
++ for (d=dl_next(ap->devs); d!= ap->devs; d=dl_next(d)) {
++ printf("%c%s", sep, d);
++ sep=',';
++ }
++ }
++ free(ap->super);
++ /* FIXME free ap */
++ if (ap->spares || brief > 1)
++ printf("\n");
++ }
++ }
++ return rv;
++}
++
++int mdexamine_main(int argc, char **argv) {
++ return Examine(conf_get_devs(), 1, 0, 0, NULL, NULL);
++}
++
+--- a/mdadm/md_p.h 1970-01-01 03:00:00.000000000 +0300
++++ mdadm/mdadm/md_p.h 2011-01-12 21:33:01.000000000 +0200
+@@ -0,0 +1,194 @@
++/*
++ md_p.h : physical layout of Linux RAID devices
++ Copyright (C) 1996-98 Ingo Molnar, Gadi Oxman
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2, or (at your option)
++ any later version.
++
++ You should have received a copy of the GNU General Public License
++ (for example /usr/src/linux/COPYING); if not, write to the Free
++ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++*/
++
++#ifndef _MD_P_H
++#define _MD_P_H
++
++/*
++ * RAID superblock.
++ *
++ * The RAID superblock maintains some statistics on each RAID configuration.
++ * Each real device in the RAID set contains it near the end of the device.
++ * Some of the ideas are copied from the ext2fs implementation.
++ *
++ * We currently use 4096 bytes as follows:
++ *
++ * word offset function
++ *
++ * 0 - 31 Constant generic RAID device information.
++ * 32 - 63 Generic state information.
++ * 64 - 127 Personality specific information.
++ * 128 - 511 12 32-words descriptors of the disks in the raid set.
++ * 512 - 911 Reserved.
++ * 912 - 1023 Disk specific descriptor.
++ */
++
++/*
++ * If x is the real device size in bytes, we return an apparent size of:
++ *
++ * y = (x & ~(MD_RESERVED_BYTES - 1)) - MD_RESERVED_BYTES
++ *
++ * and place the 4kB superblock at offset y.
++ */
++#define MD_RESERVED_BYTES (64 * 1024)
++#define MD_RESERVED_SECTORS (MD_RESERVED_BYTES / 512)
++#define MD_RESERVED_BLOCKS (MD_RESERVED_BYTES / BLOCK_SIZE)
++
++#define MD_NEW_SIZE_SECTORS(x) ((x & ~(MD_RESERVED_SECTORS - 1)) - MD_RESERVED_SECTORS)
++#define MD_NEW_SIZE_BLOCKS(x) ((x & ~(MD_RESERVED_BLOCKS - 1)) - MD_RESERVED_BLOCKS)
++
++#define MD_SB_BYTES 4096
++#define MD_SB_WORDS (MD_SB_BYTES / 4)
++#define MD_SB_BLOCKS (MD_SB_BYTES / BLOCK_SIZE)
++#define MD_SB_SECTORS (MD_SB_BYTES / 512)
++
++/*
++ * The following are counted in 32-bit words
++ */
++#define MD_SB_GENERIC_OFFSET 0
++#define MD_SB_PERSONALITY_OFFSET 64
++#define MD_SB_DISKS_OFFSET 128
++#define MD_SB_DESCRIPTOR_OFFSET 992
++
++#define MD_SB_GENERIC_CONSTANT_WORDS 32
++#define MD_SB_GENERIC_STATE_WORDS 32
++#define MD_SB_GENERIC_WORDS (MD_SB_GENERIC_CONSTANT_WORDS + MD_SB_GENERIC_STATE_WORDS)
++#define MD_SB_PERSONALITY_WORDS 64
++#define MD_SB_DESCRIPTOR_WORDS 32
++#define MD_SB_DISKS 27
++#define MD_SB_DISKS_WORDS (MD_SB_DISKS*MD_SB_DESCRIPTOR_WORDS)
++#define MD_SB_RESERVED_WORDS (1024 - MD_SB_GENERIC_WORDS - MD_SB_PERSONALITY_WORDS - MD_SB_DISKS_WORDS - MD_SB_DESCRIPTOR_WORDS)
++#define MD_SB_EQUAL_WORDS (MD_SB_GENERIC_WORDS + MD_SB_PERSONALITY_WORDS + MD_SB_DISKS_WORDS)
++
++/*
++ * Device "operational" state bits
++ */
++#define MD_DISK_FAULTY 0 /* disk is faulty / operational */
++#define MD_DISK_ACTIVE 1 /* disk is running or spare disk */
++#define MD_DISK_SYNC 2 /* disk is in sync with the raid set */
++#define MD_DISK_REMOVED 3 /* disk is in sync with the raid set */
++
++#define MD_DISK_WRITEMOSTLY 9 /* disk is "write-mostly" is RAID1 config.
++ * read requests will only be sent here in
++ * dire need
++ */
++
++typedef struct mdp_device_descriptor_s {
++ __u32 number; /* 0 Device number in the entire set */
++ __u32 major; /* 1 Device major number */
++ __u32 minor; /* 2 Device minor number */
++ __u32 raid_disk; /* 3 The role of the device in the raid set */
++ __u32 state; /* 4 Operational state */
++ __u32 reserved[MD_SB_DESCRIPTOR_WORDS - 5];
++} mdp_disk_t;
++
++#define MD_SB_MAGIC 0xa92b4efc
++
++/*
++ * Superblock state bits
++ */
++#define MD_SB_CLEAN 0
++#define MD_SB_ERRORS 1
++
++#define MD_SB_BITMAP_PRESENT 8 /* bitmap may be present nearby */
++
++typedef struct mdp_superblock_s {
++ /*
++ * Constant generic information
++ */
++ __u32 md_magic; /* 0 MD identifier */
++ __u32 major_version; /* 1 major version to which the set conforms */
++ __u32 minor_version; /* 2 minor version ... */
++ __u32 patch_version; /* 3 patchlevel version ... */
++ __u32 gvalid_words; /* 4 Number of used words in this section */
++ __u32 set_uuid0; /* 5 Raid set identifier */
++ __u32 ctime; /* 6 Creation time */
++ __u32 level; /* 7 Raid personality */
++ __u32 size; /* 8 Apparent size of each individual disk */
++ __u32 nr_disks; /* 9 total disks in the raid set */
++ __u32 raid_disks; /* 10 disks in a fully functional raid set */
++ __u32 md_minor; /* 11 preferred MD minor device number */
++ __u32 not_persistent; /* 12 does it have a persistent superblock */
++ __u32 set_uuid1; /* 13 Raid set identifier #2 */
++ __u32 set_uuid2; /* 14 Raid set identifier #3 */
++ __u32 set_uuid3; /* 15 Raid set identifier #4 */
++ __u32 gstate_creserved[MD_SB_GENERIC_CONSTANT_WORDS - 16];
++
++ /*
++ * Generic state information
++ */
++ __u32 utime; /* 0 Superblock update time */
++ __u32 state; /* 1 State bits (clean, ...) */
++ __u32 active_disks; /* 2 Number of currently active disks */
++ __u32 working_disks; /* 3 Number of working disks */
++ __u32 failed_disks; /* 4 Number of failed disks */
++ __u32 spare_disks; /* 5 Number of spare disks */
++ __u32 sb_csum; /* 6 checksum of the whole superblock */
++#if __BYTE_ORDER == __BIG_ENDIAN
++ __u32 events_hi; /* 7 high-order of superblock update count */
++ __u32 events_lo; /* 8 low-order of superblock update count */
++ __u32 cp_events_hi; /* 9 high-order of checkpoint update count */
++ __u32 cp_events_lo; /* 10 low-order of checkpoint update count */
++#else
++ __u32 events_lo; /* 7 low-order of superblock update count */
++ __u32 events_hi; /* 8 high-order of superblock update count */
++ __u32 cp_events_lo; /* 9 low-order of checkpoint update count */
++ __u32 cp_events_hi; /* 10 high-order of checkpoint update count */
++#endif
++ __u32 recovery_cp; /* 11 recovery checkpoint sector count */
++ /* There are only valid for minor_version > 90 */
++ __u64 reshape_position; /* 12,13 next address in array-space for reshape */
++ __u32 new_level; /* 14 new level we are reshaping to */
++ __u32 delta_disks; /* 15 change in number of raid_disks */
++ __u32 new_layout; /* 16 new layout */
++ __u32 new_chunk; /* 17 new chunk size (bytes) */
++ __u32 gstate_sreserved[MD_SB_GENERIC_STATE_WORDS - 18];
++
++ /*
++ * Personality information
++ */
++ __u32 layout; /* 0 the array's physical layout */
++ __u32 chunk_size; /* 1 chunk size in bytes */
++ __u32 root_pv; /* 2 LV root PV */
++ __u32 root_block; /* 3 LV root block */
++ __u32 pstate_reserved[MD_SB_PERSONALITY_WORDS - 4];
++
++ /*
++ * Disks information
++ */
++ mdp_disk_t disks[MD_SB_DISKS];
++
++ /*
++ * Reserved
++ */
++ __u32 reserved[MD_SB_RESERVED_WORDS];
++
++ /*
++ * Active descriptor
++ */
++ mdp_disk_t this_disk;
++
++} mdp_super_t;
++
++#ifdef __TINYC__
++typedef unsigned long long __u64;
++#endif
++
++static inline __u64 md_event(mdp_super_t *sb) {
++ __u64 ev = sb->events_hi;
++ return (ev<<32)| sb->events_lo;
++}
++
++#endif
++
+--- a/mdadm/md_u.h 1970-01-01 03:00:00.000000000 +0300
++++ mdadm/mdadm/md_u.h 2011-01-12 21:33:01.000000000 +0200
+@@ -0,0 +1,123 @@
++/*
++ md_u.h : user <=> kernel API between Linux raidtools and RAID drivers
++ Copyright (C) 1998 Ingo Molnar
++
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2, or (at your option)
++ any later version.
++
++ You should have received a copy of the GNU General Public License
++ (for example /usr/src/linux/COPYING); if not, write to the Free
++ Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++*/
++
++#ifndef _MD_U_H
++#define _MD_U_H
++
++/* ioctls */
++
++/* status */
++#define RAID_VERSION _IOR (MD_MAJOR, 0x10, mdu_version_t)
++#define GET_ARRAY_INFO _IOR (MD_MAJOR, 0x11, mdu_array_info_t)
++#define GET_DISK_INFO _IOR (MD_MAJOR, 0x12, mdu_disk_info_t)
++#define PRINT_RAID_DEBUG _IO (MD_MAJOR, 0x13)
++#define RAID_AUTORUN _IO (MD_MAJOR, 0x14)
++#define GET_BITMAP_FILE _IOR (MD_MAJOR, 0x15, mdu_bitmap_file_t)
++
++/* configuration */
++#define CLEAR_ARRAY _IO (MD_MAJOR, 0x20)
++#define ADD_NEW_DISK _IOW (MD_MAJOR, 0x21, mdu_disk_info_t)
++#define HOT_REMOVE_DISK _IO (MD_MAJOR, 0x22)
++#define SET_ARRAY_INFO _IOW (MD_MAJOR, 0x23, mdu_array_info_t)
++#define SET_DISK_INFO _IO (MD_MAJOR, 0x24)
++#define WRITE_RAID_INFO _IO (MD_MAJOR, 0x25)
++#define UNPROTECT_ARRAY _IO (MD_MAJOR, 0x26)
++#define PROTECT_ARRAY _IO (MD_MAJOR, 0x27)
++#define HOT_ADD_DISK _IO (MD_MAJOR, 0x28)
++#define SET_DISK_FAULTY _IO (MD_MAJOR, 0x29)
++#define SET_BITMAP_FILE _IOW (MD_MAJOR, 0x2b, int)
++
++/* usage */
++#define RUN_ARRAY _IOW (MD_MAJOR, 0x30, mdu_param_t)
++#define START_ARRAY _IO (MD_MAJOR, 0x31)
++#define STOP_ARRAY _IO (MD_MAJOR, 0x32)
++#define STOP_ARRAY_RO _IO (MD_MAJOR, 0x33)
++#define RESTART_ARRAY_RW _IO (MD_MAJOR, 0x34)
++
++typedef struct mdu_version_s {
++ int major;
++ int minor;
++ int patchlevel;
++} mdu_version_t;
++
++typedef struct mdu_array_info_s {
++ /*
++ * Generic constant information
++ */
++ int major_version;
++ int minor_version;
++ int patch_version;
++ int ctime;
++ int level;
++ int size;
++ int nr_disks;
++ int raid_disks;
++ int md_minor;
++ int not_persistent;
++
++ /*
++ * Generic state information
++ */
++ int utime; /* 0 Superblock update time */
++ int state; /* 1 State bits (clean, ...) */
++ int active_disks; /* 2 Number of currently active disks */
++ int working_disks; /* 3 Number of working disks */
++ int failed_disks; /* 4 Number of failed disks */
++ int spare_disks; /* 5 Number of spare disks */
++
++ /*
++ * Personality information
++ */
++ int layout; /* 0 the array's physical layout */
++ int chunk_size; /* 1 chunk size in bytes */
++
++} mdu_array_info_t;
++
++typedef struct mdu_disk_info_s {
++ /*
++ * configuration/status of one particular disk
++ */
++ int number;
++ int major;
++ int minor;
++ int raid_disk;
++ int state;
++
++} mdu_disk_info_t;
++
++typedef struct mdu_start_info_s {
++ /*
++ * configuration/status of one particular disk
++ */
++ int major;
++ int minor;
++ int raid_disk;
++ int state;
++
++} mdu_start_info_t;
++
++typedef struct mdu_bitmap_file_s
++{
++ char pathname[4096];
++} mdu_bitmap_file_t;
++
++typedef struct mdu_param_s
++{
++ int personality; /* 1,2,3,4 */
++ int chunk_size; /* in bytes */
++ int max_fault; /* unused for now */
++} mdu_param_t;
++
++#endif
++
+--- a/mdadm/sha1.c 1970-01-01 03:00:00.000000000 +0300
++++ mdadm/mdadm/sha1.c 2011-01-12 21:33:01.000000000 +0200
+@@ -0,0 +1,423 @@
++/* sha1.c - Functions to compute SHA1 message digest of files or
++ memory blocks according to the NIST specification FIPS-180-1.
++
++ Copyright (C) 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
++
++ This program is free software; you can redistribute it and/or modify it
++ under the terms of the GNU General Public License as published by the
++ Free Software Foundation; either version 2, or (at your option) any
++ later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software Foundation,
++ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
++
++/* Written by Scott G. Miller
++ Credits:
++ Robert Klep <robert@ilse.nl> -- Expansion function fix
++*/
++
++#ifdef HAVE_CONFIG_H
++# include <config.h>
++#endif
++
++#include "sha1.h"
++
++#include <stddef.h>
++#include <string.h>
++
++#if USE_UNLOCKED_IO
++# include "unlocked-io.h"
++#endif
++
++/* SWAP does an endian swap on architectures that are little-endian,
++ as SHA1 needs some data in a big-endian form. */
++
++#ifdef WORDS_BIGENDIAN
++# define SWAP(n) (n)
++#else
++# define SWAP(n) \
++ (((n) << 24) | (((n) & 0xff00) << 8) | (((n) >> 8) & 0xff00) | ((n) >> 24))
++#endif
++
++#define BLOCKSIZE 4096
++#if BLOCKSIZE % 64 != 0
++# error "invalid BLOCKSIZE"
++#endif
++
++/* This array contains the bytes used to pad the buffer to the next
++ 64-byte boundary. (RFC 1321, 3.1: Step 1) */
++static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ };
++
++
++/*
++ Takes a pointer to a 160 bit block of data (five 32 bit ints) and
++ intializes it to the start constants of the SHA1 algorithm. This
++ must be called before using hash in the call to sha1_hash.
++*/
++void
++sha1_init_ctx (struct sha1_ctx *ctx)
++{
++ ctx->A = 0x67452301;
++ ctx->B = 0xefcdab89;
++ ctx->C = 0x98badcfe;
++ ctx->D = 0x10325476;
++ ctx->E = 0xc3d2e1f0;
++
++ ctx->total[0] = ctx->total[1] = 0;
++ ctx->buflen = 0;
++}
++
++/* Put result from CTX in first 20 bytes following RESBUF. The result
++ must be in little endian byte order.
++
++ IMPORTANT: On some systems it is required that RESBUF is correctly
++ aligned for a 32 bits value. */
++void *
++sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf)
++{
++ ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A);
++ ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B);
++ ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C);
++ ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D);
++ ((md5_uint32 *) resbuf)[4] = SWAP (ctx->E);
++
++ return resbuf;
++}
++
++/* Process the remaining bytes in the internal buffer and the usual
++ prolog according to the standard and write the result to RESBUF.
++
++ IMPORTANT: On some systems it is required that RESBUF is correctly
++ aligned for a 32 bits value. */
++void *
++sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf)
++{
++ /* Take yet unprocessed bytes into account. */
++ md5_uint32 bytes = ctx->buflen;
++ size_t pad;
++
++ /* Now count remaining bytes. */
++ ctx->total[0] += bytes;
++ if (ctx->total[0] < bytes)
++ ++ctx->total[1];
++
++ pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
++ memcpy (&ctx->buffer[bytes], fillbuf, pad);
++
++ /* Put the 64-bit file length in *bits* at the end of the buffer. */
++ *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP (ctx->total[0] << 3);
++ *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP ((ctx->total[1] << 3) |
++ (ctx->total[0] >> 29));
++
++ /* Process last bytes. */
++ sha1_process_block (ctx->buffer, bytes + pad + 8, ctx);
++
++ return sha1_read_ctx (ctx, resbuf);
++}
++
++/* Compute SHA1 message digest for bytes read from STREAM. The
++ resulting message digest number will be written into the 16 bytes
++ beginning at RESBLOCK. */
++int
++sha1_stream (FILE *stream, void *resblock)
++{
++ struct sha1_ctx ctx;
++ char buffer[BLOCKSIZE + 72];
++ size_t sum;
++
++ /* Initialize the computation context. */
++ sha1_init_ctx (&ctx);
++
++ /* Iterate over full file contents. */
++ while (1)
++ {
++ /* We read the file in blocks of BLOCKSIZE bytes. One call of the
++ computation function processes the whole buffer so that with the
++ next round of the loop another block can be read. */
++ size_t n;
++ sum = 0;
++
++ /* Read block. Take care for partial reads. */
++ while (1)
++ {
++ n = fread (buffer + sum, 1, BLOCKSIZE - sum, stream);
++
++ sum += n;
++
++ if (sum == BLOCKSIZE)
++ break;
++
++ if (n == 0)
++ {
++ /* Check for the error flag IFF N == 0, so that we don't
++ exit the loop after a partial read due to e.g., EAGAIN
++ or EWOULDBLOCK. */
++ if (ferror (stream))
++ return 1;
++ goto process_partial_block;
++ }
++
++ /* We've read at least one byte, so ignore errors. But always
++ check for EOF, since feof may be true even though N > 0.
++ Otherwise, we could end up calling fread after EOF. */
++ if (feof (stream))
++ goto process_partial_block;
++ }
++
++ /* Process buffer with BLOCKSIZE bytes. Note that
++ BLOCKSIZE % 64 == 0
++ */
++ sha1_process_block (buffer, BLOCKSIZE, &ctx);
++ }
++
++ process_partial_block:;
++
++ /* Process any remaining bytes. */
++ if (sum > 0)
++ sha1_process_bytes (buffer, sum, &ctx);
++
++ /* Construct result in desired memory. */
++ sha1_finish_ctx (&ctx, resblock);
++ return 0;
++}
++
++/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The
++ result is always in little endian byte order, so that a byte-wise
++ output yields to the wanted ASCII representation of the message
++ digest. */
++void *
++sha1_buffer (const char *buffer, size_t len, void *resblock)
++{
++ struct sha1_ctx ctx;
++
++ /* Initialize the computation context. */
++ sha1_init_ctx (&ctx);
++
++ /* Process whole buffer but last len % 64 bytes. */
++ sha1_process_bytes (buffer, len, &ctx);
++
++ /* Put result in desired memory area. */
++ return sha1_finish_ctx (&ctx, resblock);
++}
++
++void
++sha1_process_bytes (const void *buffer, size_t len, struct sha1_ctx *ctx)
++{
++ /* When we already have some bits in our internal buffer concatenate
++ both inputs first. */
++ if (ctx->buflen != 0)
++ {
++ size_t left_over = ctx->buflen;
++ size_t add = 128 - left_over > len ? len : 128 - left_over;
++
++ memcpy (&ctx->buffer[left_over], buffer, add);
++ ctx->buflen += add;
++
++ if (ctx->buflen > 64)
++ {
++ sha1_process_block (ctx->buffer, ctx->buflen & ~63, ctx);
++
++ ctx->buflen &= 63;
++ /* The regions in the following copy operation cannot overlap. */
++ memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
++ ctx->buflen);
++ }
++
++ buffer = (const char *) buffer + add;
++ len -= add;
++ }
++
++ /* Process available complete blocks. */
++ if (len >= 64)
++ {
++#if !_STRING_ARCH_unaligned
++# define alignof(type) offsetof (struct { char c; type x; }, x)
++# define UNALIGNED_P(p) (((size_t) p) % alignof (md5_uint32) != 0)
++ if (UNALIGNED_P (buffer))
++ while (len > 64)
++ {
++ sha1_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx);
++ buffer = (const char *) buffer + 64;
++ len -= 64;
++ }
++ else
++#endif
++ {
++ sha1_process_block (buffer, len & ~63, ctx);
++ buffer = (const char *) buffer + (len & ~63);
++ len &= 63;
++ }
++ }
++
++ /* Move remaining bytes in internal buffer. */
++ if (len > 0)
++ {
++ size_t left_over = ctx->buflen;
++
++ memcpy (&ctx->buffer[left_over], buffer, len);
++ left_over += len;
++ if (left_over >= 64)
++ {
++ sha1_process_block (ctx->buffer, 64, ctx);
++ left_over -= 64;
++ memcpy (ctx->buffer, &ctx->buffer[64], left_over);
++ }
++ ctx->buflen = left_over;
++ }
++}
++
++/* --- Code below is the primary difference between md5.c and sha1.c --- */
++
++/* SHA1 round constants */
++#define K1 0x5a827999L
++#define K2 0x6ed9eba1L
++#define K3 0x8f1bbcdcL
++#define K4 0xca62c1d6L
++
++/* Round functions. Note that F2 is the same as F4. */
++#define F1(B,C,D) ( D ^ ( B & ( C ^ D ) ) )
++#define F2(B,C,D) (B ^ C ^ D)
++#define F3(B,C,D) ( ( B & C ) | ( D & ( B | C ) ) )
++#define F4(B,C,D) (B ^ C ^ D)
++
++/* Process LEN bytes of BUFFER, accumulating context into CTX.
++ It is assumed that LEN % 64 == 0.
++ Most of this code comes from GnuPG's cipher/sha1.c. */
++
++void
++sha1_process_block (const void *buffer, size_t len, struct sha1_ctx *ctx)
++{
++ const md5_uint32 *words = buffer;
++ size_t nwords = len / sizeof (md5_uint32);
++ const md5_uint32 *endp = words + nwords;
++ md5_uint32 x[16];
++ md5_uint32 a = ctx->A;
++ md5_uint32 b = ctx->B;
++ md5_uint32 c = ctx->C;
++ md5_uint32 d = ctx->D;
++ md5_uint32 e = ctx->E;
++
++ /* First increment the byte count. RFC 1321 specifies the possible
++ length of the file up to 2^64 bits. Here we only compute the
++ number of bytes. Do a double word increment. */
++ ctx->total[0] += len;
++ if (ctx->total[0] < len)
++ ++ctx->total[1];
++
++#define rol(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
++
++#define M(I) ( tm = x[I&0x0f] ^ x[(I-14)&0x0f] \
++ ^ x[(I-8)&0x0f] ^ x[(I-3)&0x0f] \
++ , (x[I&0x0f] = rol(tm, 1)) )
++
++#define R(A,B,C,D,E,F,K,M) do { E += rol( A, 5 ) \
++ + F( B, C, D ) \
++ + K \
++ + M; \
++ B = rol( B, 30 ); \
++ } while(0)
++
++ while (words < endp)
++ {
++ md5_uint32 tm;
++ int t;
++ for (t = 0; t < 16; t++)
++ {
++ x[t] = SWAP (*words);
++ words++;
++ }
++
++ R( a, b, c, d, e, F1, K1, x[ 0] );
++ R( e, a, b, c, d, F1, K1, x[ 1] );
++ R( d, e, a, b, c, F1, K1, x[ 2] );
++ R( c, d, e, a, b, F1, K1, x[ 3] );
++ R( b, c, d, e, a, F1, K1, x[ 4] );
++ R( a, b, c, d, e, F1, K1, x[ 5] );
++ R( e, a, b, c, d, F1, K1, x[ 6] );
++ R( d, e, a, b, c, F1, K1, x[ 7] );
++ R( c, d, e, a, b, F1, K1, x[ 8] );
++ R( b, c, d, e, a, F1, K1, x[ 9] );
++ R( a, b, c, d, e, F1, K1, x[10] );
++ R( e, a, b, c, d, F1, K1, x[11] );
++ R( d, e, a, b, c, F1, K1, x[12] );
++ R( c, d, e, a, b, F1, K1, x[13] );
++ R( b, c, d, e, a, F1, K1, x[14] );
++ R( a, b, c, d, e, F1, K1, x[15] );
++ R( e, a, b, c, d, F1, K1, M(16) );
++ R( d, e, a, b, c, F1, K1, M(17) );
++ R( c, d, e, a, b, F1, K1, M(18) );
++ R( b, c, d, e, a, F1, K1, M(19) );
++ R( a, b, c, d, e, F2, K2, M(20) );
++ R( e, a, b, c, d, F2, K2, M(21) );
++ R( d, e, a, b, c, F2, K2, M(22) );
++ R( c, d, e, a, b, F2, K2, M(23) );
++ R( b, c, d, e, a, F2, K2, M(24) );
++ R( a, b, c, d, e, F2, K2, M(25) );
++ R( e, a, b, c, d, F2, K2, M(26) );
++ R( d, e, a, b, c, F2, K2, M(27) );
++ R( c, d, e, a, b, F2, K2, M(28) );
++ R( b, c, d, e, a, F2, K2, M(29) );
++ R( a, b, c, d, e, F2, K2, M(30) );
++ R( e, a, b, c, d, F2, K2, M(31) );
++ R( d, e, a, b, c, F2, K2, M(32) );
++ R( c, d, e, a, b, F2, K2, M(33) );
++ R( b, c, d, e, a, F2, K2, M(34) );
++ R( a, b, c, d, e, F2, K2, M(35) );
++ R( e, a, b, c, d, F2, K2, M(36) );
++ R( d, e, a, b, c, F2, K2, M(37) );
++ R( c, d, e, a, b, F2, K2, M(38) );
++ R( b, c, d, e, a, F2, K2, M(39) );
++ R( a, b, c, d, e, F3, K3, M(40) );
++ R( e, a, b, c, d, F3, K3, M(41) );
++ R( d, e, a, b, c, F3, K3, M(42) );
++ R( c, d, e, a, b, F3, K3, M(43) );
++ R( b, c, d, e, a, F3, K3, M(44) );
++ R( a, b, c, d, e, F3, K3, M(45) );
++ R( e, a, b, c, d, F3, K3, M(46) );
++ R( d, e, a, b, c, F3, K3, M(47) );
++ R( c, d, e, a, b, F3, K3, M(48) );
++ R( b, c, d, e, a, F3, K3, M(49) );
++ R( a, b, c, d, e, F3, K3, M(50) );
++ R( e, a, b, c, d, F3, K3, M(51) );
++ R( d, e, a, b, c, F3, K3, M(52) );
++ R( c, d, e, a, b, F3, K3, M(53) );
++ R( b, c, d, e, a, F3, K3, M(54) );
++ R( a, b, c, d, e, F3, K3, M(55) );
++ R( e, a, b, c, d, F3, K3, M(56) );
++ R( d, e, a, b, c, F3, K3, M(57) );
++ R( c, d, e, a, b, F3, K3, M(58) );
++ R( b, c, d, e, a, F3, K3, M(59) );
++ R( a, b, c, d, e, F4, K4, M(60) );
++ R( e, a, b, c, d, F4, K4, M(61) );
++ R( d, e, a, b, c, F4, K4, M(62) );
++ R( c, d, e, a, b, F4, K4, M(63) );
++ R( b, c, d, e, a, F4, K4, M(64) );
++ R( a, b, c, d, e, F4, K4, M(65) );
++ R( e, a, b, c, d, F4, K4, M(66) );
++ R( d, e, a, b, c, F4, K4, M(67) );
++ R( c, d, e, a, b, F4, K4, M(68) );
++ R( b, c, d, e, a, F4, K4, M(69) );
++ R( a, b, c, d, e, F4, K4, M(70) );
++ R( e, a, b, c, d, F4, K4, M(71) );
++ R( d, e, a, b, c, F4, K4, M(72) );
++ R( c, d, e, a, b, F4, K4, M(73) );
++ R( b, c, d, e, a, F4, K4, M(74) );
++ R( a, b, c, d, e, F4, K4, M(75) );
++ R( e, a, b, c, d, F4, K4, M(76) );
++ R( d, e, a, b, c, F4, K4, M(77) );
++ R( c, d, e, a, b, F4, K4, M(78) );
++ R( b, c, d, e, a, F4, K4, M(79) );
++
++ a = ctx->A += a;
++ b = ctx->B += b;
++ c = ctx->C += c;
++ d = ctx->D += d;
++ e = ctx->E += e;
++ }
++}
+--- a/mdadm/sha1.h 1970-01-01 03:00:00.000000000 +0300
++++ mdadm/mdadm/sha1.h 2011-01-12 21:33:01.000000000 +0200
+@@ -0,0 +1,87 @@
++/* Declarations of functions and data types used for SHA1 sum
++ library functions.
++ Copyright (C) 2000, 2001, 2003, 2005 Free Software Foundation, Inc.
++
++ This program is free software; you can redistribute it and/or modify it
++ under the terms of the GNU General Public License as published by the
++ Free Software Foundation; either version 2, or (at your option) any
++ later version.
++
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software Foundation,
++ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
++
++#ifndef SHA1_H
++# define SHA1_H 1
++
++# include <stdio.h>
++# include "md5.h"
++
++/* Structure to save state of computation between the single steps. */
++struct sha1_ctx
++{
++ md5_uint32 A;
++ md5_uint32 B;
++ md5_uint32 C;
++ md5_uint32 D;
++ md5_uint32 E;
++
++ md5_uint32 total[2];
++ md5_uint32 buflen;
++ char buffer[128] __attribute__ ((__aligned__ (__alignof__ (md5_uint32))));
++};
++
++
++/* Initialize structure containing state of computation. */
++extern void sha1_init_ctx (struct sha1_ctx *ctx);
++
++/* Starting with the result of former calls of this function (or the
++ initialization function update the context for the next LEN bytes
++ starting at BUFFER.
++ It is necessary that LEN is a multiple of 64!!! */
++extern void sha1_process_block (const void *buffer, size_t len,
++ struct sha1_ctx *ctx);
++
++/* Starting with the result of former calls of this function (or the
++ initialization function update the context for the next LEN bytes
++ starting at BUFFER.
++ It is NOT required that LEN is a multiple of 64. */
++extern void sha1_process_bytes (const void *buffer, size_t len,
++ struct sha1_ctx *ctx);
++
++/* Process the remaining bytes in the buffer and put result from CTX
++ in first 20 bytes following RESBUF. The result is always in little
++ endian byte order, so that a byte-wise output yields to the wanted
++ ASCII representation of the message digest.
++
++ IMPORTANT: On some systems it is required that RESBUF be correctly
++ aligned for a 32 bits value. */
++extern void *sha1_finish_ctx (struct sha1_ctx *ctx, void *resbuf);
++
++
++/* Put result from CTX in first 20 bytes following RESBUF. The result is
++ always in little endian byte order, so that a byte-wise output yields
++ to the wanted ASCII representation of the message digest.
++
++ IMPORTANT: On some systems it is required that RESBUF is correctly
++ aligned for a 32 bits value. */
++extern void *sha1_read_ctx (const struct sha1_ctx *ctx, void *resbuf);
++
++
++/* Compute SHA1 message digest for bytes read from STREAM. The
++ resulting message digest number will be written into the 20 bytes
++ beginning at RESBLOCK. */
++extern int sha1_stream (FILE *stream, void *resblock);
++
++/* Compute SHA1 message digest for LEN bytes beginning at BUFFER. The
++ result is always in little endian byte order, so that a byte-wise
++ output yields to the wanted ASCII representation of the message
++ digest. */
++extern void *sha1_buffer (const char *buffer, size_t len, void *resblock);
++
++#endif
+--- a/mdadm/super0.c 1970-01-01 03:00:00.000000000 +0300
++++ mdadm/mdadm/super0.c 2011-01-12 21:33:01.000000000 +0200
+@@ -0,0 +1,562 @@
++/*
++ * mdadm - manage Linux "md" devices aka RAID arrays.
++ *
++ * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * Author: Neil Brown
++ * Email: <neilb@cse.unsw.edu.au>
++ * Paper: Neil Brown
++ * School of Computer Science and Engineering
++ * The University of New South Wales
++ * Sydney, 2052
++ * Australia
++ */
++
++#define HAVE_STDINT_H 1
++#include "mdadm.h"
++/*
++ * All handling for the 0.90.0 version superblock is in
++ * this file.
++ * This includes:
++ * - finding, loading, and writing the superblock.
++ * - initialising a new superblock
++ * - printing the superblock for --examine
++ * - printing part of the superblock for --detail
++ * .. other stuff
++ */
++
++
++static unsigned long calc_sb0_csum(mdp_super_t *super)
++{
++ unsigned long csum = super->sb_csum;
++ unsigned long newcsum;
++ super->sb_csum= 0 ;
++ newcsum = calc_csum(super, MD_SB_BYTES);
++ super->sb_csum = csum;
++ return newcsum;
++}
++
++
++void super0_swap_endian(struct mdp_superblock_s *sb)
++{
++ /* as super0 superblocks are host-endian, it is sometimes
++ * useful to be able to swap the endianness
++ * as (almost) everything is u32's we byte-swap every 4byte
++ * number.
++ * We then also have to swap the events_hi and events_lo
++ */
++ char *sbc = (char *)sb;
++ __u32 t32;
++ int i;
++
++ for (i=0; i < MD_SB_BYTES ; i+=4) {
++ char t = sbc[i];
++ sbc[i] = sbc[i+3];
++ sbc[i+3] = t;
++ t=sbc[i+1];
++ sbc[i+1]=sbc[i+2];
++ sbc[i+2]=t;
++ }
++ t32 = sb->events_hi;
++ sb->events_hi = sb->events_lo;
++ sb->events_lo = t32;
++
++ t32 = sb->cp_events_hi;
++ sb->cp_events_hi = sb->cp_events_lo;
++ sb->cp_events_lo = t32;
++
++}
++
++static void brief_examine_super0(void *sbv)
++{
++ mdp_super_t *sb = sbv;
++ char *c=map_num(pers, sb->level);
++ char devname[20];
++
++ sprintf(devname, "/dev/md%d", sb->md_minor);
++
++ printf("ARRAY %s level=%s num-devices=%d UUID=",
++ devname,
++ c?c:"-unknown-", sb->raid_disks);
++ if (sb->minor_version >= 90)
++ printf("%08x:%08x:%08x:%08x", sb->set_uuid0, sb->set_uuid1,
++ sb->set_uuid2, sb->set_uuid3);
++ else
++ printf("%08x", sb->set_uuid0);
++ printf("\n");
++}
++
++static int match_home0(void *sbv, char *homehost)
++{
++ mdp_super_t *sb = sbv;
++ char buf[20];
++ char *hash = sha1_buffer(homehost,
++ strlen(homehost),
++ buf);
++
++ return (memcmp(&sb->set_uuid2, hash, 8)==0);
++}
++
++static void uuid_from_super0(int uuid[4], void * sbv)
++{
++ mdp_super_t *super = sbv;
++ uuid[0] = super->set_uuid0;
++ if (super->minor_version >= 90) {
++ uuid[1] = super->set_uuid1;
++ uuid[2] = super->set_uuid2;
++ uuid[3] = super->set_uuid3;
++ } else {
++ uuid[1] = 0;
++ uuid[2] = 0;
++ uuid[3] = 0;
++ }
++}
++
++static void getinfo_super0(struct mdinfo *info, void *sbv)
++{
++ mdp_super_t *sb = sbv;
++ int working = 0;
++ int i;
++
++ info->array.major_version = sb->major_version;
++ info->array.minor_version = sb->minor_version;
++ info->array.patch_version = sb->patch_version;
++ info->array.raid_disks = sb->raid_disks;
++ info->array.level = sb->level;
++ info->array.layout = sb->layout;
++ info->array.md_minor = sb->md_minor;
++ info->array.ctime = sb->ctime;
++ info->array.utime = sb->utime;
++ info->array.chunk_size = sb->chunk_size;
++ info->array.state = sb->state;
++ info->component_size = sb->size*2;
++
++ info->disk.state = sb->this_disk.state;
++ info->disk.major = sb->this_disk.major;
++ info->disk.minor = sb->this_disk.minor;
++ info->disk.raid_disk = sb->this_disk.raid_disk;
++ info->disk.number = sb->this_disk.number;
++
++ info->events = md_event(sb);
++ info->data_offset = 0;
++
++ uuid_from_super0(info->uuid, sbv);
++
++ if (sb->minor_version > 90 && (sb->reshape_position+1) != 0) {
++ info->reshape_active = 1;
++ info->reshape_progress = sb->reshape_position;
++ info->new_level = sb->new_level;
++ info->delta_disks = sb->delta_disks;
++ info->new_layout = sb->new_layout;
++ info->new_chunk = sb->new_chunk;
++ } else
++ info->reshape_active = 0;
++
++ sprintf(info->name, "%d", sb->md_minor);
++ /* work_disks is calculated rather than read directly */
++ for (i=0; i < MD_SB_DISKS; i++)
++ if ((sb->disks[i].state & (1<<MD_DISK_SYNC)) &&
++ (sb->disks[i].raid_disk < info->array.raid_disks) &&
++ (sb->disks[i].state & (1<<MD_DISK_ACTIVE)) &&
++ !(sb->disks[i].state & (1<<MD_DISK_FAULTY)))
++ working ++;
++ info->array.working_disks = working;
++}
++
++
++static int update_super0(struct mdinfo *info, void *sbv, char *update,
++ char *devname, int verbose,
++ int uuid_set, char *homehost)
++{
++ /* NOTE: for 'assemble' and 'force' we need to return non-zero if any change was made.
++ * For others, the return value is ignored.
++ */
++ int rv = 0;
++ mdp_super_t *sb = sbv;
++ if (strcmp(update, "sparc2.2")==0 ) {
++ /* 2.2 sparc put the events in the wrong place
++ * So we copy the tail of the superblock
++ * up 4 bytes before continuing
++ */
++ __u32 *sb32 = (__u32*)sb;
++ memcpy(sb32+MD_SB_GENERIC_CONSTANT_WORDS+7,
++ sb32+MD_SB_GENERIC_CONSTANT_WORDS+7+1,
++ (MD_SB_WORDS - (MD_SB_GENERIC_CONSTANT_WORDS+7+1))*4);
++ if (verbose >= 0)
++ fprintf (stderr, Name ": adjusting superblock of %s for 2.2/sparc compatability.\n",
++ devname);
++ }
++ if (strcmp(update, "super-minor") ==0) {
++ sb->md_minor = info->array.md_minor;
++ if (verbose > 0)
++ fprintf(stderr, Name ": updating superblock of %s with minor number %d\n",
++ devname, info->array.md_minor);
++ }
++ if (strcmp(update, "summaries") == 0) {
++ int i;
++ /* set nr_disks, active_disks, working_disks,
++ * failed_disks, spare_disks based on disks[]
++ * array in superblock.
++ * Also make sure extra slots aren't 'failed'
++ */
++ sb->nr_disks = sb->active_disks =
++ sb->working_disks = sb->failed_disks =
++ sb->spare_disks = 0;
++ for (i=0; i < MD_SB_DISKS ; i++)
++ if (sb->disks[i].major ||
++ sb->disks[i].minor) {
++ int state = sb->disks[i].state;
++ if (state & (1<<MD_DISK_REMOVED))
++ continue;
++ sb->nr_disks++;
++ if (state & (1<<MD_DISK_ACTIVE))
++ sb->active_disks++;
++ if (state & (1<<MD_DISK_FAULTY))
++ sb->failed_disks++;
++ else
++ sb->working_disks++;
++ if (state == 0)
++ sb->spare_disks++;
++ } else if (i >= sb->raid_disks && sb->disks[i].number == 0)
++ sb->disks[i].state = 0;
++ }
++ if (strcmp(update, "force-one")==0) {
++ /* Not enough devices for a working array, so
++ * bring this one up-to-date.
++ */
++ __u32 ehi = sb->events_hi, elo = sb->events_lo;
++ sb->events_hi = (info->events>>32) & 0xFFFFFFFF;
++ sb->events_lo = (info->events) & 0xFFFFFFFF;
++ if (sb->events_hi != ehi ||
++ sb->events_lo != elo)
++ rv = 1;
++ }
++ if (strcmp(update, "force-array")==0) {
++ /* degraded array and 'force' requested, so
++ * maybe need to mark it 'clean'
++ */
++ if ((sb->level == 5 || sb->level == 4 || sb->level == 6) &&
++ (sb->state & (1 << MD_SB_CLEAN)) == 0) {
++ /* need to force clean */
++ sb->state |= (1 << MD_SB_CLEAN);
++ rv = 1;
++ }
++ }
++ if (strcmp(update, "assemble")==0) {
++ int d = info->disk.number;
++ int wonly = sb->disks[d].state & (1<<MD_DISK_WRITEMOSTLY);
++ if ((sb->disks[d].state & ~(1<<MD_DISK_WRITEMOSTLY))
++ != info->disk.state) {
++ sb->disks[d].state = info->disk.state | wonly;
++ rv = 1;
++ }
++ }
++ if (strcmp(update, "linear-grow-new") == 0) {
++ memset(&sb->disks[info->disk.number], 0, sizeof(sb->disks[0]));
++ sb->disks[info->disk.number].number = info->disk.number;
++ sb->disks[info->disk.number].major = info->disk.major;
++ sb->disks[info->disk.number].minor = info->disk.minor;
++ sb->disks[info->disk.number].raid_disk = info->disk.raid_disk;
++ sb->disks[info->disk.number].state = info->disk.state;
++ sb->this_disk = sb->disks[info->disk.number];
++ }
++ if (strcmp(update, "linear-grow-update") == 0) {
++ sb->raid_disks = info->array.raid_disks;
++ sb->nr_disks = info->array.nr_disks;
++ sb->active_disks = info->array.active_disks;
++ sb->working_disks = info->array.working_disks;
++ memset(&sb->disks[info->disk.number], 0, sizeof(sb->disks[0]));
++ sb->disks[info->disk.number].number = info->disk.number;
++ sb->disks[info->disk.number].major = info->disk.major;
++ sb->disks[info->disk.number].minor = info->disk.minor;
++ sb->disks[info->disk.number].raid_disk = info->disk.raid_disk;
++ sb->disks[info->disk.number].state = info->disk.state;
++ }
++ if (strcmp(update, "resync") == 0) {
++ /* make sure resync happens */
++ sb->state &= ~(1<<MD_SB_CLEAN);
++ sb->recovery_cp = 0;
++ }
++ if (strcmp(update, "homehost") == 0 &&
++ homehost) {
++ uuid_set = 0;
++ update = "uuid";
++ info->uuid[0] = sb->set_uuid0;
++ info->uuid[1] = sb->set_uuid1;
++ }
++ if (strcmp(update, "uuid") == 0) {
++ if (!uuid_set && homehost) {
++ char buf[20];
++ char *hash = sha1_buffer(homehost,
++ strlen(homehost),
++ buf);
++ memcpy(info->uuid+2, hash, 8);
++ }
++ sb->set_uuid0 = info->uuid[0];
++ sb->set_uuid1 = info->uuid[1];
++ sb->set_uuid2 = info->uuid[2];
++ sb->set_uuid3 = info->uuid[3];
++ if (sb->state & (1<<MD_SB_BITMAP_PRESENT)) {
++ struct bitmap_super_s *bm;
++ bm = (struct bitmap_super_s*)(sb+1);
++ uuid_from_super0((int*)bm->uuid, sbv);
++ }
++ }
++ if (strcmp(update, "_reshape_progress")==0)
++ sb->reshape_position = info->reshape_progress;
++
++ sb->sb_csum = calc_sb0_csum(sb);
++ return rv;
++}
++
++static int store_super0(struct supertype *st, int fd, void *sbv)
++{
++ unsigned long long dsize;
++ unsigned long long offset;
++ mdp_super_t *super = sbv;
++
++ if (!get_dev_size(fd, NULL, &dsize))
++ return 1;
++
++ if (dsize < MD_RESERVED_SECTORS*2*512)
++ return 2;
++
++ offset = MD_NEW_SIZE_SECTORS(dsize>>9);
++
++ offset *= 512;
++
++ if (lseek64(fd, offset, 0)< 0LL)
++ return 3;
++
++ if (write(fd, super, sizeof(*super)) != sizeof(*super))
++ return 4;
++
++ if (super->state & (1<<MD_SB_BITMAP_PRESENT)) {
++ struct bitmap_super_s * bm = (struct bitmap_super_s*)(super+1);
++ if (__le32_to_cpu(bm->magic) == BITMAP_MAGIC)
++ if (write(fd, bm, sizeof(*bm)) != sizeof(*bm))
++ return 5;
++ }
++
++ fsync(fd);
++ return 0;
++}
++
++static int compare_super0(void **firstp, void *secondv)
++{
++ /*
++ * return:
++ * 0 same, or first was empty, and second was copied
++ * 1 second had wrong number
++ * 2 wrong uuid
++ * 3 wrong other info
++ */
++ mdp_super_t *first = *firstp;
++ mdp_super_t *second = secondv;
++
++ int uuid1[4], uuid2[4];
++ if (second->md_magic != MD_SB_MAGIC)
++ return 1;
++ if (!first) {
++ first = malloc(MD_SB_BYTES + sizeof(struct bitmap_super_s));
++ memcpy(first, second, MD_SB_BYTES + sizeof(struct bitmap_super_s));
++ *firstp = first;
++ return 0;
++ }
++
++ uuid_from_super0(uuid1, first);
++ uuid_from_super0(uuid2, second);
++ if (!same_uuid(uuid1, uuid2, 0))
++ return 2;
++ if (first->major_version != second->major_version ||
++ first->minor_version != second->minor_version ||
++ first->patch_version != second->patch_version ||
++ first->gvalid_words != second->gvalid_words ||
++ first->ctime != second->ctime ||
++ first->level != second->level ||
++ first->size != second->size ||
++ first->raid_disks != second->raid_disks )
++ return 3;
++
++ return 0;
++}
++
++
++static int load_super0(struct supertype *st, int fd, void **sbp, char *devname)
++{
++ /* try to read in the superblock
++ * Return:
++ * 0 on success
++ * 1 on cannot get superblock
++ * 2 on superblock meaningless
++ */
++ unsigned long long dsize;
++ unsigned long long offset;
++ mdp_super_t *super;
++ int uuid[4];
++ struct bitmap_super_s *bsb;
++
++ if (!get_dev_size(fd, devname, &dsize))
++ return 1;
++
++ if (dsize < MD_RESERVED_SECTORS*512 * 2) {
++ if (devname)
++ fprintf(stderr, Name
++ ": %s is too small for md: size is %llu sectors.\n",
++ devname, dsize);
++ return 1;
++ }
++
++ offset = MD_NEW_SIZE_SECTORS(dsize>>9);
++
++ offset *= 512;
++
++ ioctl(fd, BLKFLSBUF, 0); /* make sure we read current data */
++
++ if (lseek64(fd, offset, 0)< 0LL) {
++ if (devname)
++ fprintf(stderr, Name ": Cannot seek to superblock on %s: %s\n",
++ devname, strerror(errno));
++ return 1;
++ }
++
++ super = malloc(MD_SB_BYTES + sizeof(bitmap_super_t));
++
++ if (read(fd, super, sizeof(*super)) != MD_SB_BYTES) {
++ if (devname)
++ fprintf(stderr, Name ": Cannot read superblock on %s\n",
++ devname);
++ free(super);
++ return 1;
++ }
++
++ if (st->ss && st->minor_version == 9)
++ super0_swap_endian(super);
++
++ if (super->md_magic != MD_SB_MAGIC) {
++ if (devname)
++ fprintf(stderr, Name ": No super block found on %s (Expected magic %08x, got %08x)\n",
++ devname, MD_SB_MAGIC, super->md_magic);
++ free(super);
++ return 2;
++ }
++
++ if (super->major_version != 0) {
++ if (devname)
++ fprintf(stderr, Name ": Cannot interpret superblock on %s - version is %d\n",
++ devname, super->major_version);
++ free(super);
++ return 2;
++ }
++ *sbp = super;
++ if (st->ss == NULL) {
++ st->ss = &super0;
++ st->minor_version = 90;
++ st->max_devs = MD_SB_DISKS;
++ }
++
++ /* Now check on the bitmap superblock */
++ if ((super->state & (1<<MD_SB_BITMAP_PRESENT)) == 0)
++ return 0;
++ /* Read the bitmap superblock and make sure it looks
++ * valid. If it doesn't clear the bit. An --assemble --force
++ * should get that written out.
++ */
++ if (read(fd, super+1, sizeof(struct bitmap_super_s))
++ != sizeof(struct bitmap_super_s))
++ goto no_bitmap;
++
++ uuid_from_super0(uuid, super);
++ bsb = (struct bitmap_super_s *)(super+1);
++ if (__le32_to_cpu(bsb->magic) != BITMAP_MAGIC ||
++ memcmp(bsb->uuid, uuid, 16) != 0)
++ goto no_bitmap;
++ return 0;
++
++ no_bitmap:
++ super->state &= ~(1<<MD_SB_BITMAP_PRESENT);
++
++ return 0;
++}
++
++static struct supertype *match_metadata_desc0(char *arg)
++{
++ struct supertype *st = malloc(sizeof(*st));
++ if (!st) return st;
++
++ st->ss = &super0;
++ st->minor_version = 90;
++ st->max_devs = MD_SB_DISKS;
++ if (strcmp(arg, "0") == 0 ||
++ strcmp(arg, "0.90") == 0 ||
++ strcmp(arg, "default") == 0
++ )
++ return st;
++
++ st->minor_version = 9; /* flag for 'byte-swapped' */
++ if (strcmp(arg, "0.swap")==0)
++ return st;
++
++ free(st);
++ return NULL;
++}
++
++void locate_bitmap0(struct supertype *st, int fd, void *sbv)
++{
++ unsigned long long dsize;
++ unsigned long long offset;
++
++ if (!get_dev_size(fd, NULL, &dsize))
++ return;
++
++ if (dsize < MD_RESERVED_SECTORS*512 * 2)
++ return;
++
++ offset = MD_NEW_SIZE_SECTORS(dsize>>9);
++
++ offset *= 512;
++
++ offset += MD_SB_BYTES;
++
++ lseek64(fd, offset, 0);
++}
++
++struct superswitch super0 = {
++ .examine_super = NULL,
++ .brief_examine_super = brief_examine_super0,
++ .detail_super = NULL,
++ .brief_detail_super = NULL,
++ .export_super = NULL,
++ .match_home = match_home0,
++ .uuid_from_super = uuid_from_super0,
++ .getinfo_super = getinfo_super0,
++ .update_super = update_super0,
++ .init_super = NULL,
++ .add_to_super = NULL,
++ .store_super = store_super0,
++ .write_init_super = NULL,
++ .compare_super = compare_super0,
++ .load_super = load_super0,
++ .match_metadata_desc = match_metadata_desc0,
++ .avail_size = NULL,
++ .add_internal_bitmap = NULL,
++ .locate_bitmap = locate_bitmap0,
++ .write_bitmap = NULL,
++ .major = 0,
++ .swapuuid = 0,
++};
+--- a/mdadm/super1.c 1970-01-01 03:00:00.000000000 +0300
++++ mdadm/mdadm/super1.c 2011-01-12 21:33:01.000000000 +0200
+@@ -0,0 +1,731 @@
++/*
++ * mdadm - manage Linux "md" devices aka RAID arrays.
++ *
++ * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * Author: Neil Brown
++ * Email: <neilb@cse.unsw.edu.au>
++ * Paper: Neil Brown
++ * School of Computer Science and Engineering
++ * The University of New South Wales
++ * Sydney, 2052
++ * Australia
++ */
++
++#include "mdadm.h"
++/*
++ * The version-1 superblock :
++ * All numeric fields are little-endian.
++ *
++ * total size: 256 bytes plus 2 per device.
++ * 1K allows 384 devices.
++ */
++struct mdp_superblock_1 {
++ /* constant array information - 128 bytes */
++ __u32 magic; /* MD_SB_MAGIC: 0xa92b4efc - little endian */
++ __u32 major_version; /* 1 */
++ __u32 feature_map; /* 0 for now */
++ __u32 pad0; /* always set to 0 when writing */
++
++ __u8 set_uuid[16]; /* user-space generated. */
++ char set_name[32]; /* set and interpreted by user-space */
++
++ __u64 ctime; /* lo 40 bits are seconds, top 24 are microseconds or 0*/
++ __u32 level; /* -4 (multipath), -1 (linear), 0,1,4,5 */
++ __u32 layout; /* only for raid5 currently */
++ __u64 size; /* used size of component devices, in 512byte sectors */
++
++ __u32 chunksize; /* in 512byte sectors */
++ __u32 raid_disks;
++ __u32 bitmap_offset; /* sectors after start of superblock that bitmap starts
++ * NOTE: signed, so bitmap can be before superblock
++ * only meaningful of feature_map[0] is set.
++ */
++
++ /* These are only valid with feature bit '4' */
++ __u32 new_level; /* new level we are reshaping to */
++ __u64 reshape_position; /* next address in array-space for reshape */
++ __u32 delta_disks; /* change in number of raid_disks */
++ __u32 new_layout; /* new layout */
++ __u32 new_chunk; /* new chunk size (bytes) */
++ __u8 pad1[128-124]; /* set to 0 when written */
++
++ /* constant this-device information - 64 bytes */
++ __u64 data_offset; /* sector start of data, often 0 */
++ __u64 data_size; /* sectors in this device that can be used for data */
++ __u64 super_offset; /* sector start of this superblock */
++ __u64 recovery_offset;/* sectors before this offset (from data_offset) have been recovered */
++ __u32 dev_number; /* permanent identifier of this device - not role in raid */
++ __u32 cnt_corrected_read; /* number of read errors that were corrected by re-writing */
++ __u8 device_uuid[16]; /* user-space setable, ignored by kernel */
++ __u8 devflags; /* per-device flags. Only one defined...*/
++#define WriteMostly1 1 /* mask for writemostly flag in above */
++ __u8 pad2[64-57]; /* set to 0 when writing */
++
++ /* array state information - 64 bytes */
++ __u64 utime; /* 40 bits second, 24 btes microseconds */
++ __u64 events; /* incremented when superblock updated */
++ __u64 resync_offset; /* data before this offset (from data_offset) known to be in sync */
++ __u32 sb_csum; /* checksum upto devs[max_dev] */
++ __u32 max_dev; /* size of devs[] array to consider */
++ __u8 pad3[64-32]; /* set to 0 when writing */
++
++ /* device state information. Indexed by dev_number.
++ * 2 bytes per device
++ * Note there are no per-device state flags. State information is rolled
++ * into the 'roles' value. If a device is spare or faulty, then it doesn't
++ * have a meaningful role.
++ */
++ __u16 dev_roles[0]; /* role in array, or 0xffff for a spare, or 0xfffe for faulty */
++};
++
++struct misc_dev_info {
++ __u64 device_size;
++};
++
++/* feature_map bits */
++#define MD_FEATURE_BITMAP_OFFSET 1
++#define MD_FEATURE_RECOVERY_OFFSET 2 /* recovery_offset is present and
++ * must be honoured
++ */
++#define MD_FEATURE_RESHAPE_ACTIVE 4
++
++#define MD_FEATURE_ALL (1|2|4)
++
++#ifndef offsetof
++#define offsetof(t,f) ((size_t)&(((t*)0)->f))
++#endif
++static unsigned int calc_sb_1_csum(struct mdp_superblock_1 * sb)
++{
++ unsigned int disk_csum, csum;
++ unsigned long long newcsum;
++ int size = sizeof(*sb) + __le32_to_cpu(sb->max_dev)*2;
++ unsigned int *isuper = (unsigned int*)sb;
++ int i;
++
++/* make sure I can count... */
++ if (offsetof(struct mdp_superblock_1,data_offset) != 128 ||
++ offsetof(struct mdp_superblock_1, utime) != 192 ||
++ sizeof(struct mdp_superblock_1) != 256) {
++ fprintf(stderr, "WARNING - superblock isn't sized correctly\n");
++ }
++
++ disk_csum = sb->sb_csum;
++ sb->sb_csum = 0;
++ newcsum = 0;
++ for (i=0; size>=4; size -= 4 ) {
++ newcsum += __le32_to_cpu(*isuper);
++ isuper++;
++ }
++
++ if (size == 2)
++ newcsum += __le16_to_cpu(*(unsigned short*) isuper);
++
++ csum = (newcsum & 0xffffffff) + (newcsum >> 32);
++ sb->sb_csum = disk_csum;
++ return __cpu_to_le32(csum);
++}
++
++static void brief_examine_super1(void *sbv)
++{
++ struct mdp_superblock_1 *sb = sbv;
++ int i;
++ unsigned long long sb_offset;
++ char *nm;
++ char *c=map_num(pers, __le32_to_cpu(sb->level));
++
++ nm = strchr(sb->set_name, ':');
++ if (nm)
++ nm++;
++ else if (sb->set_name[0])
++ nm = sb->set_name;
++ else
++ nm = "??";
++
++ printf("ARRAY /dev/md%s level=%s ", nm, c?c:"-unknown-");
++ sb_offset = __le64_to_cpu(sb->super_offset);
++ if (sb_offset <= 4)
++ printf("metadata=1.1 ");
++ else if (sb_offset <= 8)
++ printf("metadata=1.2 ");
++ else
++ printf("metadata=1.0 ");
++ printf("num-devices=%d UUID=", __le32_to_cpu(sb->raid_disks));
++ for (i=0; i<16; i++) {
++ if ((i&3)==0 && i != 0) printf(":");
++ printf("%02x", sb->set_uuid[i]);
++ }
++ if (sb->set_name[0])
++ printf(" name=%.32s", sb->set_name);
++ printf("\n");
++}
++
++static int match_home1(void *sbv, char *homehost)
++{
++ struct mdp_superblock_1 *sb = sbv;
++ int l = homehost ? strlen(homehost) : 0;
++
++ return (l > 0 && l < 32 &&
++ sb->set_name[l] == ':' &&
++ strncmp(sb->set_name, homehost, l) == 0);
++}
++
++static void uuid_from_super1(int uuid[4], void * sbv)
++{
++ struct mdp_superblock_1 *super = sbv;
++ char *cuuid = (char*)uuid;
++ int i;
++ for (i=0; i<16; i++)
++ cuuid[i] = super->set_uuid[i];
++}
++
++static void getinfo_super1(struct mdinfo *info, void *sbv)
++{
++ struct mdp_superblock_1 *sb = sbv;
++ int working = 0;
++ int i;
++ int role;
++
++ info->array.major_version = 1;
++ info->array.minor_version = __le32_to_cpu(sb->feature_map);
++ info->array.patch_version = 0;
++ info->array.raid_disks = __le32_to_cpu(sb->raid_disks);
++ info->array.level = __le32_to_cpu(sb->level);
++ info->array.layout = __le32_to_cpu(sb->layout);
++ info->array.md_minor = -1;
++ info->array.ctime = __le64_to_cpu(sb->ctime);
++ info->array.utime = __le64_to_cpu(sb->utime);
++ info->array.chunk_size = __le32_to_cpu(sb->chunksize)*512;
++ info->array.state =
++ (__le64_to_cpu(sb->resync_offset) >= __le64_to_cpu(sb->size))
++ ? 1 : 0;
++
++ info->data_offset = __le64_to_cpu(sb->data_offset);
++ info->component_size = __le64_to_cpu(sb->size);
++
++ info->disk.major = 0;
++ info->disk.minor = 0;
++ info->disk.number = __le32_to_cpu(sb->dev_number);
++ if (__le32_to_cpu(sb->dev_number) >= __le32_to_cpu(sb->max_dev) ||
++ __le32_to_cpu(sb->max_dev) > 512)
++ role = 0xfffe;
++ else
++ role = __le16_to_cpu(sb->dev_roles[__le32_to_cpu(sb->dev_number)]);
++
++ info->disk.raid_disk = -1;
++ switch(role) {
++ case 0xFFFF:
++ info->disk.state = 2; /* spare: ACTIVE, not sync, not faulty */
++ break;
++ case 0xFFFE:
++ info->disk.state = 1; /* faulty */
++ break;
++ default:
++ info->disk.state = 6; /* active and in sync */
++ info->disk.raid_disk = role;
++ }
++ info->events = __le64_to_cpu(sb->events);
++
++ memcpy(info->uuid, sb->set_uuid, 16);
++
++ strncpy(info->name, sb->set_name, 32);
++ info->name[32] = 0;
++
++ if (sb->feature_map & __le32_to_cpu(MD_FEATURE_RESHAPE_ACTIVE)) {
++ info->reshape_active = 1;
++ info->reshape_progress = __le64_to_cpu(sb->reshape_position);
++ info->new_level = __le32_to_cpu(sb->new_level);
++ info->delta_disks = __le32_to_cpu(sb->delta_disks);
++ info->new_layout = __le32_to_cpu(sb->new_layout);
++ info->new_chunk = __le32_to_cpu(sb->new_chunk)<<9;
++ } else
++ info->reshape_active = 0;
++
++ for (i=0; i< __le32_to_cpu(sb->max_dev); i++) {
++ role = __le16_to_cpu(sb->dev_roles[i]);
++ if (/*role == 0xFFFF || */role < info->array.raid_disks)
++ working++;
++ }
++
++ info->array.working_disks = working;
++}
++
++static int update_super1(struct mdinfo *info, void *sbv, char *update,
++ char *devname, int verbose,
++ int uuid_set, char *homehost)
++{
++ /* NOTE: for 'assemble' and 'force' we need to return non-zero if any change was made.
++ * For others, the return value is ignored.
++ */
++ int rv = 0;
++ struct mdp_superblock_1 *sb = sbv;
++
++ if (strcmp(update, "force-one")==0) {
++ /* Not enough devices for a working array,
++ * so bring this one up-to-date
++ */
++ if (sb->events != __cpu_to_le64(info->events))
++ rv = 1;
++ sb->events = __cpu_to_le64(info->events);
++ }
++ if (strcmp(update, "force-array")==0) {
++ /* Degraded array and 'force' requests to
++ * maybe need to mark it 'clean'.
++ */
++ switch(__le32_to_cpu(sb->level)) {
++ case 5: case 4: case 6:
++ /* need to force clean */
++ if (sb->resync_offset != ~0ULL)
++ rv = 1;
++ sb->resync_offset = ~0ULL;
++ }
++ }
++ if (strcmp(update, "assemble")==0) {
++ int d = info->disk.number;
++ int want;
++ if (info->disk.state == 6)
++ want = __cpu_to_le32(info->disk.raid_disk);
++ else
++ want = 0xFFFF;
++ if (sb->dev_roles[d] != want) {
++ sb->dev_roles[d] = want;
++ rv = 1;
++ }
++ }
++ if (strcmp(update, "linear-grow-new") == 0) {
++ int i;
++ int rfd;
++ int max = __le32_to_cpu(sb->max_dev);
++
++ for (i=0 ; i < max ; i++)
++ if (__le16_to_cpu(sb->dev_roles[i]) >= 0xfffe)
++ break;
++ sb->dev_number = __cpu_to_le32(i);
++ info->disk.number = i;
++ if (max >= __le32_to_cpu(sb->max_dev))
++ sb->max_dev = __cpu_to_le32(max+1);
++
++ if ((rfd = open("/dev/urandom", O_RDONLY)) < 0 ||
++ read(rfd, sb->device_uuid, 16) != 16) {
++ *(__u32*)(sb->device_uuid) = random();
++ *(__u32*)(sb->device_uuid+4) = random();
++ *(__u32*)(sb->device_uuid+8) = random();
++ *(__u32*)(sb->device_uuid+12) = random();
++ }
++
++ sb->dev_roles[i] =
++ __cpu_to_le16(info->disk.raid_disk);
++ }
++ if (strcmp(update, "linear-grow-update") == 0) {
++ sb->raid_disks = __cpu_to_le32(info->array.raid_disks);
++ sb->dev_roles[info->disk.number] =
++ __cpu_to_le16(info->disk.raid_disk);
++ }
++ if (strcmp(update, "resync") == 0) {
++ /* make sure resync happens */
++ sb->resync_offset = 0ULL;
++ }
++ if (strcmp(update, "uuid") == 0) {
++ copy_uuid(sb->set_uuid, info->uuid, super1.swapuuid);
++
++ if (__le32_to_cpu(sb->feature_map)&MD_FEATURE_BITMAP_OFFSET) {
++ struct bitmap_super_s *bm;
++ bm = (struct bitmap_super_s*)(sbv+1024);
++ memcpy(bm->uuid, sb->set_uuid, 16);
++ }
++ }
++ if (strcmp(update, "homehost") == 0 &&
++ homehost) {
++ char *c;
++ update = "name";
++ c = strchr(sb->set_name, ':');
++ if (c)
++ strncpy(info->name, c+1, 31 - (c-sb->set_name));
++ else
++ strncpy(info->name, sb->set_name, 32);
++ info->name[32] = 0;
++ }
++ if (strcmp(update, "name") == 0) {
++ if (info->name[0] == 0)
++ sprintf(info->name, "%d", info->array.md_minor);
++ memset(sb->set_name, 0, sizeof(sb->set_name));
++ if (homehost &&
++ strchr(info->name, ':') == NULL &&
++ strlen(homehost)+1+strlen(info->name) < 32) {
++ strcpy(sb->set_name, homehost);
++ strcat(sb->set_name, ":");
++ strcat(sb->set_name, info->name);
++ } else
++ strcpy(sb->set_name, info->name);
++ }
++ if (strcmp(update, "devicesize") == 0 &&
++ __le64_to_cpu(sb->super_offset) <
++ __le64_to_cpu(sb->data_offset)) {
++ /* set data_size to device size less data_offset */
++ struct misc_dev_info *misc = (struct misc_dev_info*)
++ (sbv + 1024 + sizeof(struct bitmap_super_s));
++ printf("Size was %llu\n", (unsigned long long)
++ __le64_to_cpu(sb->data_size));
++ sb->data_size = __cpu_to_le64(
++ misc->device_size - __le64_to_cpu(sb->data_offset));
++ printf("Size is %llu\n", (unsigned long long)
++ __le64_to_cpu(sb->data_size));
++ }
++ if (strcmp(update, "_reshape_progress")==0)
++ sb->reshape_position = __cpu_to_le64(info->reshape_progress);
++
++ sb->sb_csum = calc_sb_1_csum(sb);
++ return rv;
++}
++
++static void locate_bitmap1(struct supertype *st, int fd, void *sbv);
++
++static int store_super1(struct supertype *st, int fd, void *sbv)
++{
++ struct mdp_superblock_1 *sb = sbv;
++ unsigned long long sb_offset;
++ int sbsize;
++ unsigned long long dsize;
++
++ if (!get_dev_size(fd, NULL, &dsize))
++ return 1;
++
++ dsize >>= 9;
++
++ if (dsize < 24)
++ return 2;
++
++ /*
++ * Calculate the position of the superblock.
++ * It is always aligned to a 4K boundary and
++ * depending on minor_version, it can be:
++ * 0: At least 8K, but less than 12K, from end of device
++ * 1: At start of device
++ * 2: 4K from start of device.
++ */
++ switch(st->minor_version) {
++ case 0:
++ sb_offset = dsize;
++ sb_offset -= 8*2;
++ sb_offset &= ~(4*2-1);
++ break;
++ case 1:
++ sb_offset = 0;
++ break;
++ case 2:
++ sb_offset = 4*2;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++
++
++ if (sb_offset != __le64_to_cpu(sb->super_offset) &&
++ 0 != __le64_to_cpu(sb->super_offset)
++ ) {
++ fprintf(stderr, Name ": internal error - sb_offset is wrong\n");
++ abort();
++ }
++
++ if (lseek64(fd, sb_offset << 9, 0)< 0LL)
++ return 3;
++
++ sbsize = sizeof(*sb) + 2 * __le32_to_cpu(sb->max_dev);
++
++ if (write(fd, sb, sbsize) != sbsize)
++ return 4;
++
++ if (sb->feature_map & __cpu_to_le32(MD_FEATURE_BITMAP_OFFSET)) {
++ struct bitmap_super_s *bm = (struct bitmap_super_s*)
++ (((char*)sb)+1024);
++ if (__le32_to_cpu(bm->magic) == BITMAP_MAGIC) {
++ locate_bitmap1(st, fd, sbv);
++ if (write(fd, bm, sizeof(*bm)) != sizeof(*bm))
++ return 5;
++ }
++ }
++ fsync(fd);
++ return 0;
++}
++
++static int load_super1(struct supertype *st, int fd, void **sbp, char *devname);
++
++static int compare_super1(void **firstp, void *secondv)
++{
++ /*
++ * return:
++ * 0 same, or first was empty, and second was copied
++ * 1 second had wrong number
++ * 2 wrong uuid
++ * 3 wrong other info
++ */
++ struct mdp_superblock_1 *first = *firstp;
++ struct mdp_superblock_1 *second = secondv;
++
++ if (second->magic != __cpu_to_le32(MD_SB_MAGIC))
++ return 1;
++ if (second->major_version != __cpu_to_le32(1))
++ return 1;
++
++ if (!first) {
++ first = malloc(1024+sizeof(bitmap_super_t) +
++ sizeof(struct misc_dev_info));
++ memcpy(first, second, 1024+sizeof(bitmap_super_t) +
++ sizeof(struct misc_dev_info));
++ *firstp = first;
++ return 0;
++ }
++ if (memcmp(first->set_uuid, second->set_uuid, 16)!= 0)
++ return 2;
++
++ if (first->ctime != second->ctime ||
++ first->level != second->level ||
++ first->layout != second->layout ||
++ first->size != second->size ||
++ first->chunksize != second->chunksize ||
++ first->raid_disks != second->raid_disks)
++ return 3;
++ return 0;
++}
++
++static int load_super1(struct supertype *st, int fd, void **sbp, char *devname)
++{
++ unsigned long long dsize;
++ unsigned long long sb_offset;
++ struct mdp_superblock_1 *super;
++ int uuid[4];
++ struct bitmap_super_s *bsb;
++ struct misc_dev_info *misc;
++
++
++ if (st->ss == NULL) {
++ int bestvers = -1;
++ __u64 bestctime = 0;
++ /* guess... choose latest ctime */
++ st->ss = &super1;
++ for (st->minor_version = 0; st->minor_version <= 2 ; st->minor_version++) {
++ switch(load_super1(st, fd, sbp, devname)) {
++ case 0: super = *sbp;
++ if (bestvers == -1 ||
++ bestctime < __le64_to_cpu(super->ctime)) {
++ bestvers = st->minor_version;
++ bestctime = __le64_to_cpu(super->ctime);
++ }
++ free(super);
++ *sbp = NULL;
++ break;
++ case 1: st->ss = NULL; return 1; /*bad device */
++ case 2: break; /* bad, try next */
++ }
++ }
++ if (bestvers != -1) {
++ int rv;
++ st->minor_version = bestvers;
++ st->ss = &super1;
++ st->max_devs = 384;
++ rv = load_super1(st, fd, sbp, devname);
++ if (rv) st->ss = NULL;
++ return rv;
++ }
++ st->ss = NULL;
++ return 2;
++ }
++ if (!get_dev_size(fd, devname, &dsize))
++ return 1;
++ dsize >>= 9;
++
++ if (dsize < 24) {
++ if (devname)
++ fprintf(stderr, Name ": %s is too small for md: size is %llu sectors.\n",
++ devname, dsize);
++ return 1;
++ }
++
++ /*
++ * Calculate the position of the superblock.
++ * It is always aligned to a 4K boundary and
++ * depending on minor_version, it can be:
++ * 0: At least 8K, but less than 12K, from end of device
++ * 1: At start of device
++ * 2: 4K from start of device.
++ */
++ switch(st->minor_version) {
++ case 0:
++ sb_offset = dsize;
++ sb_offset -= 8*2;
++ sb_offset &= ~(4*2-1);
++ break;
++ case 1:
++ sb_offset = 0;
++ break;
++ case 2:
++ sb_offset = 4*2;
++ break;
++ default:
++ return -EINVAL;
++ }
++
++ ioctl(fd, BLKFLSBUF, 0); /* make sure we read current data */
++
++
++ if (lseek64(fd, sb_offset << 9, 0)< 0LL) {
++ if (devname)
++ fprintf(stderr, Name ": Cannot seek to superblock on %s: %s\n",
++ devname, strerror(errno));
++ return 1;
++ }
++
++ super = malloc(1024 + sizeof(bitmap_super_t) +
++ sizeof(struct misc_dev_info));
++
++ if (read(fd, super, 1024) != 1024) {
++ if (devname)
++ fprintf(stderr, Name ": Cannot read superblock on %s\n",
++ devname);
++ free(super);
++ return 1;
++ }
++
++ if (__le32_to_cpu(super->magic) != MD_SB_MAGIC) {
++ if (devname)
++ fprintf(stderr, Name ": No super block found on %s (Expected magic %08x, got %08x)\n",
++ devname, MD_SB_MAGIC, __le32_to_cpu(super->magic));
++ free(super);
++ return 2;
++ }
++
++ if (__le32_to_cpu(super->major_version) != 1) {
++ if (devname)
++ fprintf(stderr, Name ": Cannot interpret superblock on %s - version is %d\n",
++ devname, __le32_to_cpu(super->major_version));
++ free(super);
++ return 2;
++ }
++ if (__le64_to_cpu(super->super_offset) != sb_offset) {
++ if (devname)
++ fprintf(stderr, Name ": No superblock found on %s (super_offset is wrong)\n",
++ devname);
++ free(super);
++ return 2;
++ }
++ *sbp = super;
++
++ bsb = (struct bitmap_super_s *)(((char*)super)+1024);
++
++ misc = (struct misc_dev_info*) (bsb+1);
++ misc->device_size = dsize;
++
++ /* Now check on the bitmap superblock */
++ if ((__le32_to_cpu(super->feature_map)&MD_FEATURE_BITMAP_OFFSET) == 0)
++ return 0;
++ /* Read the bitmap superblock and make sure it looks
++ * valid. If it doesn't clear the bit. An --assemble --force
++ * should get that written out.
++ */
++ locate_bitmap1(st, fd, super);
++ if (read(fd, ((char*)super)+1024, sizeof(struct bitmap_super_s))
++ != sizeof(struct bitmap_super_s))
++ goto no_bitmap;
++
++ uuid_from_super1(uuid, super);
++ if (__le32_to_cpu(bsb->magic) != BITMAP_MAGIC ||
++ memcmp(bsb->uuid, uuid, 16) != 0)
++ goto no_bitmap;
++ return 0;
++
++ no_bitmap:
++ super->feature_map = __cpu_to_le32(__le32_to_cpu(super->feature_map) & ~1);
++ return 0;
++}
++
++
++static struct supertype *match_metadata_desc1(char *arg)
++{
++ struct supertype *st = malloc(sizeof(*st));
++ if (!st) return st;
++
++ st->ss = &super1;
++ st->max_devs = 384;
++ if (strcmp(arg, "1") == 0 ||
++ strcmp(arg, "1.0") == 0 ||
++ strcmp(arg, "default/large") == 0) {
++ st->minor_version = 0;
++ return st;
++ }
++ if (strcmp(arg, "1.1") == 0) {
++ st->minor_version = 1;
++ return st;
++ }
++ if (strcmp(arg, "1.2") == 0) {
++ st->minor_version = 2;
++ return st;
++ }
++
++ free(st);
++ return NULL;
++}
++
++static void locate_bitmap1(struct supertype *st, int fd, void *sbv)
++{
++ unsigned long long offset;
++ struct mdp_superblock_1 *sb;
++ int mustfree = 0;
++
++ if (!sbv) {
++ if (st->ss->load_super(st, fd, &sbv, NULL))
++ return; /* no error I hope... */
++ mustfree = 1;
++ }
++ sb = sbv;
++
++ offset = __le64_to_cpu(sb->super_offset);
++ offset += (int32_t) __le32_to_cpu(sb->bitmap_offset);
++ if (mustfree)
++ free(sb);
++ lseek64(fd, offset<<9, 0);
++}
++
++struct superswitch super1 = {
++ .examine_super = NULL,
++ .brief_examine_super = brief_examine_super1,
++ .detail_super = NULL,
++ .brief_detail_super = NULL,
++ .export_super = NULL,
++ .match_home = match_home1,
++ .uuid_from_super = uuid_from_super1,
++ .getinfo_super = getinfo_super1,
++ .update_super = update_super1,
++ .init_super = NULL,
++ .add_to_super = NULL,
++ .store_super = store_super1,
++ .write_init_super = NULL,
++ .compare_super = compare_super1,
++ .load_super = load_super1,
++ .match_metadata_desc = match_metadata_desc1,
++ .avail_size = NULL,
++ .add_internal_bitmap = NULL,
++ .locate_bitmap = locate_bitmap1,
++ .write_bitmap = NULL,
++ .major = 1,
++#if __BYTE_ORDER == BIG_ENDIAN
++ .swapuuid = 0,
++#else
++ .swapuuid = 1,
++#endif
++};
+--- a/mdadm/util.c 1970-01-01 03:00:00.000000000 +0300
++++ mdadm/mdadm/util.c 2011-01-12 21:33:01.000000000 +0200
+@@ -0,0 +1,652 @@
++/*
++ * mdadm - manage Linux "md" devices aka RAID arrays.
++ *
++ * Copyright (C) 2001-2006 Neil Brown <neilb@suse.de>
++ *
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++ *
++ * Author: Neil Brown
++ * Email: <neilb@cse.unsw.edu.au>
++ * Paper: Neil Brown
++ * School of Computer Science and Engineering
++ * The University of New South Wales
++ * Sydney, 2052
++ * Australia
++ */
++
++#include "mdadm.h"
++#include "md_p.h"
++#include <sys/utsname.h>
++#include <ctype.h>
++
++/*
++ * following taken from linux/blkpg.h because they aren't
++ * anywhere else and it isn't safe to #include linux/ * stuff.
++ */
++
++#define BLKPG _IO(0x12,105)
++
++/* The argument structure */
++struct blkpg_ioctl_arg {
++ int op;
++ int flags;
++ int datalen;
++ void *data;
++};
++
++/* The subfunctions (for the op field) */
++#define BLKPG_ADD_PARTITION 1
++#define BLKPG_DEL_PARTITION 2
++
++/* Sizes of name fields. Unused at present. */
++#define BLKPG_DEVNAMELTH 64
++#define BLKPG_VOLNAMELTH 64
++
++/* The data structure for ADD_PARTITION and DEL_PARTITION */
++struct blkpg_partition {
++ long long start; /* starting offset in bytes */
++ long long length; /* length in bytes */
++ int pno; /* partition number */
++ char devname[BLKPG_DEVNAMELTH]; /* partition name, like sda5 or c0d1p2,
++ to be used in kernel messages */
++ char volname[BLKPG_VOLNAMELTH]; /* volume label */
++};
++
++/*
++ * Parse a 128 bit uuid in 4 integers
++ * format is 32 hexx nibbles with options :.<space> separator
++ * If not exactly 32 hex digits are found, return 0
++ * else return 1
++ */
++int parse_uuid(char *str, int uuid[4])
++{
++ int hit = 0; /* number of Hex digIT */
++ int i;
++ char c;
++ for (i=0; i<4; i++) uuid[i]=0;
++
++ while ((c= *str++)) {
++ int n;
++ if (c>='0' && c<='9')
++ n = c-'0';
++ else if (c>='a' && c <= 'f')
++ n = 10 + c - 'a';
++ else if (c>='A' && c <= 'F')
++ n = 10 + c - 'A';
++ else if (strchr(":. -", c))
++ continue;
++ else return 0;
++
++ if (hit<32) {
++ uuid[hit/8] <<= 4;
++ uuid[hit/8] += n;
++ }
++ hit++;
++ }
++ if (hit == 32)
++ return 1;
++ return 0;
++
++}
++
++
++/*
++ * Get the md version number.
++ * We use the RAID_VERSION ioctl if it is supported
++ * If not, but we have a block device with major '9', we assume
++ * 0.36.0
++ *
++ * Return version number as 24 but number - assume version parts
++ * always < 255
++ */
++
++int md_get_version(int fd)
++{
++ struct stat stb;
++ mdu_version_t vers;
++
++ if (fstat(fd, &stb)<0)
++ return -1;
++ if ((S_IFMT&stb.st_mode) != S_IFBLK)
++ return -1;
++
++ if (ioctl(fd, RAID_VERSION, &vers) == 0)
++ return (vers.major*10000) + (vers.minor*100) + vers.patchlevel;
++ if (errno == EACCES)
++ return -1;
++ if (major(stb.st_rdev) == MD_MAJOR)
++ return (3600);
++ return -1;
++}
++
++
++int get_linux_version()
++{
++ struct utsname name;
++ char *cp;
++ int a,b,c;
++ if (uname(&name) <0)
++ return -1;
++
++ cp = name.release;
++ a = strtoul(cp, &cp, 10);
++ if (*cp != '.') return -1;
++ b = strtoul(cp+1, &cp, 10);
++ if (*cp != '.') return -1;
++ c = strtoul(cp+1, NULL, 10);
++
++ return (a*1000000)+(b*1000)+c;
++}
++
++void remove_partitions(int fd)
++{
++ /* remove partitions from this block devices.
++ * This is used for components added to an array
++ */
++#ifdef BLKPG_DEL_PARTITION
++ struct blkpg_ioctl_arg a;
++ struct blkpg_partition p;
++
++ a.op = BLKPG_DEL_PARTITION;
++ a.data = (void*)&p;
++ a.datalen = sizeof(p);
++ a.flags = 0;
++ memset(a.data, 0, a.datalen);
++ for (p.pno=0; p.pno < 16; p.pno++)
++ ioctl(fd, BLKPG, &a);
++#endif
++}
++
++int enough(int level, int raid_disks, int layout, int clean,
++ char *avail, int avail_disks)
++{
++ int copies, first;
++ switch (level) {
++ case 10:
++ /* This is the tricky one - we need to check
++ * which actual disks are present.
++ */
++ copies = (layout&255)* ((layout>>8) & 255);
++ first=0;
++ do {
++ /* there must be one of the 'copies' form 'first' */
++ int n = copies;
++ int cnt=0;
++ while (n--) {
++ if (avail[first])
++ cnt++;
++ first = (first+1) % raid_disks;
++ }
++ if (cnt == 0)
++ return 0;
++
++ } while (first != 0);
++ return 1;
++
++ case -4:
++ return avail_disks>= 1;
++ case -1:
++ case 0:
++ return avail_disks == raid_disks;
++ case 1:
++ return avail_disks >= 1;
++ case 4:
++ case 5:
++ if (clean)
++ return avail_disks >= raid_disks-1;
++ else
++ return avail_disks >= raid_disks;
++ case 6:
++ if (clean)
++ return avail_disks >= raid_disks-2;
++ else
++ return avail_disks >= raid_disks;
++ default:
++ return 0;
++ }
++}
++
++int same_uuid(int a[4], int b[4], int swapuuid)
++{
++ if (swapuuid) {
++ /* parse uuids are hostendian.
++ * uuid's from some superblocks are big-ending
++ * if there is a difference, we need to swap..
++ */
++ unsigned char *ac = (unsigned char *)a;
++ unsigned char *bc = (unsigned char *)b;
++ int i;
++ for (i=0; i<16; i+= 4) {
++ if (ac[i+0] != bc[i+3] ||
++ ac[i+1] != bc[i+2] ||
++ ac[i+2] != bc[i+1] ||
++ ac[i+3] != bc[i+0])
++ return 0;
++ }
++ return 1;
++ } else {
++ if (a[0]==b[0] &&
++ a[1]==b[1] &&
++ a[2]==b[2] &&
++ a[3]==b[3])
++ return 1;
++ return 0;
++ }
++}
++void copy_uuid(void *a, int b[4], int swapuuid)
++{
++ if (swapuuid) {
++ /* parse uuids are hostendian.
++ * uuid's from some superblocks are big-ending
++ * if there is a difference, we need to swap..
++ */
++ unsigned char *ac = (unsigned char *)a;
++ unsigned char *bc = (unsigned char *)b;
++ int i;
++ for (i=0; i<16; i+= 4) {
++ ac[i+0] = bc[i+3];
++ ac[i+1] = bc[i+2];
++ ac[i+2] = bc[i+1];
++ ac[i+3] = bc[i+0];
++ }
++ } else
++ memcpy(a, b, 16);
++}
++
++char *map_num(mapping_t *map, int num)
++{
++ while (map->name) {
++ if (map->num == num)
++ return map->name;
++ map++;
++ }
++ return NULL;
++}
++
++int map_name(mapping_t *map, char *name)
++{
++ while (map->name) {
++ if (strcmp(map->name, name)==0)
++ return map->num;
++ map++;
++ }
++ return UnSet;
++}
++
++
++int is_standard(char *dev, int *nump)
++{
++ /* tests if dev is a "standard" md dev name.
++ * i.e if the last component is "/dNN" or "/mdNN",
++ * where NN is a string of digits
++ */
++ char *d = strrchr(dev, '/');
++ int type=0;
++ int num;
++ if (!d)
++ return 0;
++ if (strncmp(d, "/d",2)==0)
++ d += 2, type=1; /* /dev/md/dN{pM} */
++ else if (strncmp(d, "/md_d", 5)==0)
++ d += 5, type=1; /* /dev/md_dNpM */
++ else if (strncmp(d, "/md", 3)==0)
++ d += 3, type=-1; /* /dev/mdN */
++ else if (d-dev > 3 && strncmp(d-2, "md/", 3)==0)
++ d += 1, type=-1; /* /dev/md/N */
++ else
++ return 0;
++ if (!*d)
++ return 0;
++ num = atoi(d);
++ while (isdigit(*d))
++ d++;
++ if (*d)
++ return 0;
++ if (nump) *nump = num;
++
++ return type;
++}
++
++
++/*
++ * convert a major/minor pair for a block device into a name in /dev, if possible.
++ * On the first call, walk /dev collecting name.
++ * Put them in a simple linked listfor now.
++ */
++struct devmap {
++ int major, minor;
++ char *name;
++ struct devmap *next;
++} *devlist = NULL;
++int devlist_ready = 0;
++
++int add_dev(const char *name, const struct stat *stb, int flag, struct FTW *s)
++{
++ struct stat st;
++ if (S_ISLNK(stb->st_mode)) {
++ stat(name, &st);
++ stb = &st;
++ }
++
++ if ((stb->st_mode&S_IFMT)== S_IFBLK) {
++ char *n = strdup(name);
++ struct devmap *dm = malloc(sizeof(*dm));
++ if (strncmp(n, "/dev/./", 7)==0)
++ strcpy(n+4, name+6);
++ if (dm) {
++ dm->major = major(stb->st_rdev);
++ dm->minor = minor(stb->st_rdev);
++ dm->name = n;
++ dm->next = devlist;
++ devlist = dm;
++ }
++ }
++ return 0;
++}
++
++#ifndef HAVE_NFTW
++#ifdef HAVE_FTW
++int add_dev_1(const char *name, const struct stat *stb, int flag)
++{
++ return add_dev(name, stb, flag, NULL);
++}
++int nftw(const char *path, int (*han)(const char *name, const struct stat *stb, int flag, struct FTW *s), int nopenfd, int flags)
++{
++ return ftw(path, add_dev_1, nopenfd);
++}
++#else
++int nftw(const char *path, int (*han)(const char *name, const struct stat *stb, int flag, struct FTW *s), int nopenfd, int flags)
++{
++ return 0;
++}
++#endif /* HAVE_FTW */
++#endif /* HAVE_NFTW */
++
++/*
++ * Find a block device with the right major/minor number.
++ * If we find multiple names, choose the shortest.
++ * If we find a non-standard name, it is probably there
++ * deliberately so prefer it over a standard name.
++ * This applies only to names for MD devices.
++ */
++char *map_dev(int major, int minor, int create)
++{
++ struct devmap *p;
++ char *std = NULL, *nonstd=NULL;
++ int did_check = 0;
++
++ if (major == 0 && minor == 0)
++ return NULL;
++
++ retry:
++ if (!devlist_ready) {
++ char *dev = "/dev";
++ struct stat stb;
++ while(devlist) {
++ struct devmap *d = devlist;
++ devlist = d->next;
++ free(d->name);
++ free(d);
++ }
++ if (lstat(dev, &stb)==0 &&
++ S_ISLNK(stb.st_mode))
++ dev = "/dev/.";
++ nftw(dev, add_dev, 10, FTW_PHYS);
++ devlist_ready=1;
++ did_check = 1;
++ }
++
++ for (p=devlist; p; p=p->next)
++ if (p->major == major &&
++ p->minor == minor) {
++ if (is_standard(p->name, NULL)) {
++ if (std == NULL ||
++ strlen(p->name) < strlen(std))
++ std = p->name;
++ } else {
++ if (nonstd == NULL ||
++ strlen(p->name) < strlen(nonstd))
++ nonstd = p->name;
++ }
++ }
++ if (!std && !nonstd && !did_check) {
++ devlist_ready = 0;
++ goto retry;
++ }
++ if (create && !std && !nonstd) {
++ static char buf[30];
++ snprintf(buf, sizeof(buf), "%d:%d", major, minor);
++ nonstd = buf;
++ }
++
++ return nonstd ? nonstd : std;
++}
++
++unsigned long calc_csum(void *super, int bytes)
++{
++ unsigned long long newcsum = 0;
++ int i;
++ unsigned int csum;
++ unsigned int *superc = (unsigned int*) super;
++
++ for(i=0; i<bytes/4; i++)
++ newcsum+= superc[i];
++ csum = (newcsum& 0xffffffff) + (newcsum>>32);
++#ifdef __alpha__
++/* The in-kernel checksum calculation is always 16bit on
++ * the alpha, though it is 32 bit on i386...
++ * I wonder what it is elsewhere... (it uses and API in
++ * a way that it shouldn't).
++ */
++ csum = (csum & 0xffff) + (csum >> 16);
++ csum = (csum & 0xffff) + (csum >> 16);
++#endif
++ return csum;
++}
++
++char *human_size(long long bytes)
++{
++ static char buf[30];
++
++ /* We convert bytes to either centi-M{ega,ibi}bytes or
++ * centi-G{igi,ibi}bytes, with appropriate rounding,
++ * and then print 1/100th of those as a decimal.
++ * We allow upto 2048Megabytes before converting to
++ * gigabytes, as that shows more precision and isn't
++ * too large a number.
++ * Terrabytes are not yet handled.
++ */
++
++ if (bytes < 5000*1024)
++ buf[0]=0;
++ else if (bytes < 2*1024LL*1024LL*1024LL) {
++ long cMiB = (bytes / ( (1LL<<20) / 200LL ) +1) /2;
++ long cMB = (bytes / ( 1000000LL / 200LL ) +1) /2;
++ snprintf(buf, sizeof(buf), " (%ld.%02ld MiB %ld.%02ld MB)",
++ cMiB/100 , cMiB % 100,
++ cMB/100, cMB % 100);
++ } else {
++ long cGiB = (bytes / ( (1LL<<30) / 200LL ) +1) /2;
++ long cGB = (bytes / (1000000000LL/200LL ) +1) /2;
++ snprintf(buf, sizeof(buf), " (%ld.%02ld GiB %ld.%02ld GB)",
++ cGiB/100 , cGiB % 100,
++ cGB/100, cGB % 100);
++ }
++ return buf;
++}
++
++char *human_size_brief(long long bytes)
++{
++ static char buf[30];
++
++
++ if (bytes < 5000*1024)
++ snprintf(buf, sizeof(buf), "%ld.%02ldKiB",
++ (long)(bytes>>10), (long)(((bytes&1023)*100+512)/1024)
++ );
++ else if (bytes < 2*1024LL*1024LL*1024LL)
++ snprintf(buf, sizeof(buf), "%ld.%02ldMiB",
++ (long)(bytes>>20),
++ (long)((bytes&0xfffff)+0x100000/200)/(0x100000/100)
++ );
++ else
++ snprintf(buf, sizeof(buf), "%ld.%02ldGiB",
++ (long)(bytes>>30),
++ (long)(((bytes>>10)&0xfffff)+0x100000/200)/(0x100000/100)
++ );
++ return buf;
++}
++
++int get_mdp_major(void)
++{
++static int mdp_major = -1;
++ FILE *fl;
++ char *w;
++ int have_block = 0;
++ int have_devices = 0;
++ int last_num = -1;
++
++ if (mdp_major != -1)
++ return mdp_major;
++ fl = fopen("/proc/devices", "r");
++ if (!fl)
++ return -1;
++ while ((w = conf_word(fl, 1))) {
++ if (have_block && strcmp(w, "devices:")==0)
++ have_devices = 1;
++ have_block = (strcmp(w, "Block")==0);
++ if (isdigit(w[0]))
++ last_num = atoi(w);
++ if (have_devices && strcmp(w, "mdp")==0)
++ mdp_major = last_num;
++ free(w);
++ }
++ fclose(fl);
++ return mdp_major;
++}
++
++int dev_open(char *dev, int flags)
++{
++ /* like 'open', but if 'dev' matches %d:%d, create a temp
++ * block device and open that
++ */
++ char *e;
++ int fd = -1;
++ char devname[32];
++ int major;
++ int minor;
++
++ if (!dev) return -1;
++
++ major = strtoul(dev, &e, 0);
++ if (e > dev && *e == ':' && e[1] &&
++ (minor = strtoul(e+1, &e, 0)) >= 0 &&
++ *e == 0) {
++ snprintf(devname, sizeof(devname), "/dev/.tmp.md.%d:%d", major, minor);
++ if (mknod(devname, S_IFBLK|0600, makedev(major, minor))==0) {
++ fd = open(devname, flags);
++ unlink(devname);
++ }
++ } else
++ fd = open(dev, flags);
++ return fd;
++}
++
++struct superswitch *superlist[] = { &super0, &super1, NULL };
++
++struct supertype *super_by_version(int vers, int minor)
++{
++ struct supertype *st = malloc(sizeof(*st));
++ if (!st) return st;
++ if (vers == 0) {
++ st->ss = &super0;
++ st->max_devs = MD_SB_DISKS;
++ }
++
++ if (vers == 1) {
++ st->ss = &super1;
++ st->max_devs = 384;
++ }
++ st->minor_version = minor;
++ return st;
++}
++
++struct supertype *guess_super(int fd)
++{
++ /* try each load_super to find the best match,
++ * and return the best superswitch
++ */
++ struct superswitch *ss;
++ struct supertype *st;
++ unsigned long besttime = 0;
++ int bestsuper = -1;
++
++ void *sbp = NULL;
++ int i;
++
++ st = malloc(sizeof(*st));
++ memset(st, 0, sizeof(*st));
++ for (i=0 ; superlist[i]; i++) {
++ int rv;
++ ss = superlist[i];
++ st->ss = NULL;
++ rv = ss->load_super(st, fd, &sbp, NULL);
++ if (rv == 0) {
++ struct mdinfo info;
++ ss->getinfo_super(&info, sbp);
++ if (bestsuper == -1 ||
++ besttime < info.array.ctime) {
++ bestsuper = i;
++ besttime = info.array.ctime;
++ }
++ free(sbp);
++ }
++ }
++ if (bestsuper != -1) {
++ int rv;
++ st->ss = NULL;
++ rv = superlist[bestsuper]->load_super(st, fd, &sbp, NULL);
++ if (rv == 0) {
++ free(sbp);
++ return st;
++ }
++ }
++ free(st);
++ return NULL;
++}
++
++/* Return size of device in bytes */
++int get_dev_size(int fd, char *dname, unsigned long long *sizep)
++{
++ unsigned long long ldsize;
++#ifdef BLKGETSIZE64
++ if (ioctl(fd, BLKGETSIZE64, &ldsize) != 0)
++#endif
++ {
++ unsigned long dsize;
++ if (ioctl(fd, BLKGETSIZE, &dsize) == 0) {
++ ldsize = dsize;
++ ldsize <<= 9;
++ } else {
++ if (dname)
++ fprintf(stderr, Name ": Cannot get size of %s: %s\b",
++ dname, strerror(errno));
++ return 0;
++ }
++ }
++ *sizep = ldsize;
++ return 1;
++}
diff --git a/patches/busybox/1.18.1/1.18.1-mdstart.diff b/patches/busybox/1.18.1/1.18.1-mdstart.diff
new file mode 100644
index 0000000..6e4bf3f
--- /dev/null
+++ b/patches/busybox/1.18.1/1.18.1-mdstart.diff
@@ -0,0 +1,122 @@
+Based on:
+
+> Forward-port the old mdstart tool from the Gentoo Busybox-1.1.3.
+> Only fires the RAID_AUTORUN ioctl on existing /dev/md nodes.
+
+diff -pruN a/include/applets.src.h mdstart/include/applets.src.h
+--- a/include/applets.src.h 2011-01-20 01:08:05.470632138 +0100
++++ mdstart/include/applets.src.h 2011-01-20 01:09:13.198003320 +0100
+@@ -235,6 +235,7 @@ IF_MAN(APPLET(man, _BB_DIR_SBIN, _BB_SUI
+ IF_MATCHPATHCON(APPLET(matchpathcon, _BB_DIR_USR_SBIN, _BB_SUID_DROP))
+ IF_MD5SUM(APPLET_NOEXEC(md5sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_DROP, md5sum))
+ IF_MDEV(APPLET(mdev, _BB_DIR_SBIN, _BB_SUID_DROP))
++IF_MDSTART(APPLET(mdstart, _BB_DIR_SBIN, _BB_SUID_DROP))
+ IF_MICROCOM(APPLET(microcom, _BB_DIR_USR_BIN, _BB_SUID_DROP))
+ IF_MKDIR(APPLET_NOFORK(mkdir, mkdir, _BB_DIR_BIN, _BB_SUID_DROP, mkdir))
+ IF_MKFS_VFAT(APPLET_ODDNAME(mkdosfs, mkfs_vfat, _BB_DIR_SBIN, _BB_SUID_DROP, mkfs_vfat))
+diff -pruN a/include/usage.src.h mdstart/include/usage.src.h
+--- a/include/usage.src.h 2010-12-21 06:29:45.000000000 +0200
++++ mdstart/include/usage.src.h 2011-01-12 21:29:47.000000000 +0200
+@@ -847,6 +847,11 @@ INSERT
+ "$ dirname /tmp/foo/\n" \
+ "/tmp\n"
+
++#define mdstart_trivial_usage \
++ "{[PARTITION] MD-NODE}..."
++#define mdstart_full_usage \
++ Run the RAID_AUTORUN ioctl on the given MD number"
++
+ #define dmesg_trivial_usage \
+ "[-c] [-n LEVEL] [-s SIZE]"
+ #define dmesg_full_usage "\n\n" \
+diff -pruN a/util-linux/Config.src mdstart/util-linux/Config.src
+--- a/util-linux/Config.src 2010-12-20 02:41:27.000000000 +0200
++++ mdstart/util-linux/Config.src 2011-01-12 21:30:09.000000000 +0200
+@@ -456,6 +456,13 @@ config FEATURE_MDEV_LOAD_FIRMWARE
+ /lib/firmware/ and if it exists, send it to the kernel for
+ loading into the hardware.
+
++config MDSTART
++ bool "mdstart"
++ default n
++ help
++ Allows you to autostart /dev/md devices if using an initramfs to
++ boot.
++
+ config MKSWAP
+ bool "mkswap"
+ default y
+diff -pruN a/util-linux/Kbuild.src mdstart/util-linux/Kbuild.src
+--- a/util-linux/Kbuild.src 2010-12-20 02:41:27.000000000 +0200
++++ mdstart/util-linux/Kbuild.src 2011-01-12 21:30:09.000000000 +0200
+@@ -24,6 +24,7 @@ lib-$(CONFIG_HWCLOCK) += hwclo
+ lib-$(CONFIG_IPCRM) += ipcrm.o
+ lib-$(CONFIG_IPCS) += ipcs.o
+ lib-$(CONFIG_LOSETUP) += losetup.o
++lib-$(CONFIG_MDSTART) += mdStart.o
+ lib-$(CONFIG_LSPCI) += lspci.o
+ lib-$(CONFIG_LSUSB) += lsusb.o
+ lib-$(CONFIG_MDEV) += mdev.o
+diff -pruN a/util-linux/mdStart.c mdstart/util-linux/mdStart.c
+--- a/util-linux/mdStart.c 1970-01-01 03:00:00.000000000 +0300
++++ mdstart/util-linux/mdStart.c 2011-01-12 21:30:09.000000000 +0200
+@@ -0,0 +1,59 @@
++/*
++ * Linux 2.6(+) RAID Autostarter
++ *
++ * Copyright (C) 2005 by Tim Yamin <plasmaroo@gentoo.org> <plasm@roo.me.uk>
++ *
++ * 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
++ *
++ */
++
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <sys/ioctl.h>
++#include <linux/major.h>
++#include <linux/raid/md_u.h>
++
++extern int
++mdstart_main(int argc, char *argv[])
++{
++ int i, fd, part = 0, retval = 0;
++
++ if(argc < 2)
++ {
++ bb_show_usage();
++ }
++
++ for(i = 1; i < argc; i++)
++ {
++ if(sscanf(argv[i], "%d", &part) == 1)
++ continue;
++
++ fd = open(argv[i], 0, 0);
++ if (fd >= 0)
++ {
++ ioctl(fd, RAID_AUTORUN, part);
++ close(fd);
++ } else
++ {
++ printf("Error: Failed to open %s!\n", argv[i]);
++ retval=1;
++ }
++
++ part = 0;
++ }
++
++ return retval;
++}
diff --git a/patches/busybox/1.18.1/1.18.1-openvt.diff b/patches/busybox/1.18.1/1.18.1-openvt.diff
new file mode 100644
index 0000000..b8a9f8a
--- /dev/null
+++ b/patches/busybox/1.18.1/1.18.1-openvt.diff
@@ -0,0 +1,19 @@
+Based on:
+
+> Allow a slightly wider range of valid vt numbers. Forward-ported from Gentoo
+> Busybox 1.1.3.
+
+> The previous spin of this patch on 1.1.3 had a 'wait(NULL);' right before
+> return EXIT_SUCCESS. I don't think it's needed anymore, so I left it out.
+
+--- a/console-tools/openvt.c 2010-11-22 22:24:58.000000000 +0200
++++ b/console-tools/openvt.c 2010-11-29 15:32:18.000000000 +0200
+@@ -124,7 +124,7 @@ int openvt_main(int argc UNUSED_PARAM, c
+
+ if (flags & OPT_c) {
+ /* Check for illegal vt number: < 1 or > 63 */
+- vtno = xatou_range(str_c, 1, 63);
++ vtno = xatou_range(str_c, 0, 63);
+ } else {
+ vtno = find_free_vtno();
+ }
diff --git a/patches/busybox/1.18.1/README b/patches/busybox/1.18.1/README
new file mode 100644
index 0000000..27c23fe
--- /dev/null
+++ b/patches/busybox/1.18.1/README
@@ -0,0 +1,16 @@
+1.18.1-mdadm.diff:
+This adds a minimal mdadm implementation to busybox for scanning for and
+activating mdraid arrays. You can blame robbat2 for this one :)
+Patch ported from 1.7.4 to 1.18.1 by Denis Kaganovich.
+
+1.18.1-mdstart.diff:
+This adds a 'mdstart' command to busybox, which is used for the activation of
+individual mdraid arrays. It originated with 1.1.3+gentoo or earlier.
+Patch ported from 1.7.4 to 1.18.1 by Denis Kaganovich.
+
+1.18.1-openvt.diff:
+It is unknown what problem this patch fixes. It may no longer be needed.
+Patch ported from 1.7.4 to 1.18.1 by Denis Kaganovich.
+
+busybox-1.7.4-signal-hack.patch:
+It is unknown what this patch does. It may no longer be needed.
diff --git a/patches/busybox/1.18.1/busybox-1.7.4-signal-hack.patch b/patches/busybox/1.18.1/busybox-1.7.4-signal-hack.patch
new file mode 100644
index 0000000..ba11830
--- /dev/null
+++ b/patches/busybox/1.18.1/busybox-1.7.4-signal-hack.patch
@@ -0,0 +1,28 @@
+workaround while we get it fixed upstream
+
+http://bugs.gentoo.org/201114
+
+--- libbb/u_signal_names.c
++++ libbb/u_signal_names.c
+@@ -66,7 +66,7 @@
+ #ifdef SIGTERM
+ [SIGTERM ] = "TERM",
+ #endif
+-#ifdef SIGSTKFLT
++#if defined(SIGSTKFLT) && SIGSTKFLT < 32
+ [SIGSTKFLT] = "STKFLT",
+ #endif
+ #ifdef SIGCHLD
+@@ -90,10 +90,10 @
+ #ifdef SIGURG
+ [SIGURG ] = "URG",
+ #endif
+-#ifdef SIGXCPU
++#if defined(SIGXCPU) && SIGXCPU < 32
+ [SIGXCPU ] = "XCPU",
+ #endif
+-#ifdef SIGXFSZ
++#if defined(SIGXFSZ) && SIGXFSZ < 32
+ [SIGXFSZ ] = "XFSZ",
+ #endif
+ #ifdef SIGVTALRM
diff --git a/patches/busybox/1.7.4/1.7.4-make-3.82.diff b/patches/busybox/1.7.4/1.7.4-make-3.82.diff
new file mode 100644
index 0000000..0559761
--- /dev/null
+++ b/patches/busybox/1.7.4/1.7.4-make-3.82.diff
@@ -0,0 +1,42 @@
+From d508d972c7f808eec5139255f661d37817c79260 Mon Sep 17 00:00:00 2001
+From: Sebastian Pipping <sebastian@pipping.org>
+Date: Mon, 29 Nov 2010 09:52:22 +0100
+Subject: [PATCH] Split implicit and normal rules for make 3.82
+
+---
+ Makefile | 12 ++++++++++--
+ 1 files changed, 10 insertions(+), 2 deletions(-)
+
+diff --git a/Makefile b/Makefile
+index c1fe21b..a2bfe4b 100644
+--- Makefile
++++ Makefile
+@@ -402,7 +402,12 @@ ifeq ($(config-targets),1)
+ -include $(srctree)/arch/$(ARCH)/Makefile
+ export KBUILD_DEFCONFIG
+
+-config %config: scripts_basic outputmakefile FORCE
++config: scripts_basic outputmakefile FORCE
++ $(Q)mkdir -p include
++ $(Q)$(MAKE) $(build)=scripts/kconfig $@
++ $(Q)$(MAKE) -C $(srctree) KBUILD_SRC= .kernelrelease
++
++%config: scripts_basic outputmakefile FORCE
+ $(Q)mkdir -p include
+ $(Q)$(MAKE) $(build)=scripts/kconfig $@
+ $(Q)$(MAKE) -C $(srctree) KBUILD_SRC= .kernelrelease
+@@ -1239,7 +1244,10 @@ endif
+ $(Q)$(MAKE) $(build)=$(build-dir) $(target-dir)$(notdir $@)
+
+ # Modules
+-/ %/: prepare scripts FORCE
++/: prepare scripts FORCE
++ $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
++ $(build)=$(build-dir)
++%/: prepare scripts FORCE
+ $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
+ $(build)=$(build-dir)
+ %.ko: prepare scripts FORCE
+--
+1.7.3.2
+
diff --git a/patches/lvm/2.02.28/filter-sysfs-inc-sys-stat.patch b/patches/lvm/2.02.28/filter-sysfs-inc-sys-stat.patch
new file mode 100644
index 0000000..2988e92
--- /dev/null
+++ b/patches/lvm/2.02.28/filter-sysfs-inc-sys-stat.patch
@@ -0,0 +1,11 @@
+diff -ur LVM2.2.02.28/lib/filters/filter-sysfs.c LVM2.2.02.28.new/lib/filters/filter-sysfs.c
+--- LVM2.2.02.28/lib/filters/filter-sysfs.c 2007-08-22 16:38:16.000000000 +0200
++++ LVM2.2.02.28.new/lib/filters/filter-sysfs.c 2011-01-13 20:45:38.751542669 +0100
+@@ -15,6 +15,7 @@
+ #include "lib.h"
+ #include "filter-sysfs.h"
+ #include "lvm-string.h"
++#include <sys/stat.h>
+
+ #ifdef linux
+
diff --git a/patches/lvm/2.02.28/no-export-dynamic.patch b/patches/lvm/2.02.28/no-export-dynamic.patch
new file mode 100644
index 0000000..19a4e13
--- /dev/null
+++ b/patches/lvm/2.02.28/no-export-dynamic.patch
@@ -0,0 +1,22 @@
+diff -ur LVM2.2.02.28/configure LVM2.2.02.28.new/configure
+--- LVM2.2.02.28/configure 2007-08-14 20:58:30.000000000 +0200
++++ LVM2.2.02.28.new/configure 2011-01-13 20:45:08.429184861 +0100
+@@ -1949,7 +1949,6 @@
+ CLDWHOLEARCHIVE="-Wl,-whole-archive"
+ CLDNOWHOLEARCHIVE="-Wl,-no-whole-archive"
+ LDDEPS="$LDDEPS .export.sym"
+- LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
+ LIB_SUFFIX="so"
+ DEVMAPPER=yes
+ ODIRECT=yes
+diff -ur LVM2.2.02.28/configure.in LVM2.2.02.28.new/configure.in
+--- LVM2.2.02.28/configure.in 2007-08-14 20:58:31.000000000 +0200
++++ LVM2.2.02.28.new/configure.in 2011-01-13 20:45:14.365688659 +0100
+@@ -38,7 +38,6 @@
+ CLDWHOLEARCHIVE="-Wl,-whole-archive"
+ CLDNOWHOLEARCHIVE="-Wl,-no-whole-archive"
+ LDDEPS="$LDDEPS .export.sym"
+- LDFLAGS="$LDFLAGS -Wl,--export-dynamic"
+ LIB_SUFFIX="so"
+ DEVMAPPER=yes
+ ODIRECT=yes
diff --git a/patches/lvm/2.02.74/lvm2-2.02.72-no-export-dynamic.patch b/patches/lvm/2.02.74/lvm2-2.02.72-no-export-dynamic.patch
new file mode 100644
index 0000000..05c7bf3
--- /dev/null
+++ b/patches/lvm/2.02.74/lvm2-2.02.72-no-export-dynamic.patch
@@ -0,0 +1,37 @@
+X-Gentoo-Bug: 332905
+X-Patch-URL: https://bugs.gentoo.org/attachment.cgi?id=243283&action=view
+X-Gentoo-Bug-URL: https://bugs.gentoo.org/show_bug.cgi?id=332905
+
+diff -ur LVM2.2.02.72.orig/daemons/dmeventd/Makefile.in LVM2.2.02.72/daemons/dmeventd/Makefile.in
+--- LVM2.2.02.72.orig/daemons/dmeventd/Makefile.in 2010-05-14 16:36:56.000000000 +0300
++++ LVM2.2.02.72/daemons/dmeventd/Makefile.in 2010-08-17 03:00:24.000000000 +0300
+@@ -61,7 +61,7 @@
+ $(DL_LIBS) $(LVMLIBS) $(LIBS) -rdynamic
+
+ dmeventd.static: $(LIB_STATIC) dmeventd.o $(interfacebuilddir)/libdevmapper.a
+- $(CC) $(CFLAGS) $(LDFLAGS) -static -L. -L$(interfacebuilddir) -o $@ \
++ $(CC) $(CFLAGS) $(LDFLAGS) -Wl,--no-export-dynamic -static -L. -L$(interfacebuilddir) -o $@ \
+ dmeventd.o $(DL_LIBS) $(LVMLIBS) $(LIBS) $(STATIC_LIBS)
+
+ ifeq ("@PKGCONFIG@", "yes")
+diff -ur LVM2.2.02.72.orig/tools/Makefile.in LVM2.2.02.72/tools/Makefile.in
+--- LVM2.2.02.72.orig/tools/Makefile.in 2010-06-25 21:23:10.000000000 +0300
++++ LVM2.2.02.72/tools/Makefile.in 2010-08-17 03:01:07.000000000 +0300
+@@ -126,7 +126,7 @@
+ -o $@ dmsetup.o -ldevmapper $(LIBS)
+
+ dmsetup.static: dmsetup.o $(interfacebuilddir)/libdevmapper.a
+- $(CC) $(CFLAGS) $(LDFLAGS) -static -L$(interfacebuilddir) \
++ $(CC) $(CFLAGS) $(LDFLAGS) -Wl,--no-export-dynamic -static -L$(interfacebuilddir) \
+ -o $@ dmsetup.o -ldevmapper $(STATIC_LIBS) $(LIBS)
+
+ all: device-mapper
+@@ -136,7 +136,7 @@
+ $(LVMLIBS) $(READLINE_LIBS) $(LIBS) -rdynamic
+
+ lvm.static: $(OBJECTS) lvm-static.o $(top_builddir)/lib/liblvm-internal.a $(interfacebuilddir)/libdevmapper.a
+- $(CC) $(CFLAGS) $(LDFLAGS) -static -L$(interfacebuilddir) -o $@ \
++ $(CC) $(CFLAGS) $(LDFLAGS) -Wl,--no-export-dynamic -static -L$(interfacebuilddir) -o $@ \
+ $(OBJECTS) lvm-static.o $(LVMLIBS) $(STATIC_LIBS) $(LIBS)
+
+ liblvm2cmd.a: $(top_builddir)/lib/liblvm-internal.a $(OBJECTS) lvmcmdlib.o lvm2cmd.o