#!/bin/sh # # Copyright © 2006-2008 Martin F. Krafft , # 2012 Michael Tokarev # based on the scripts in the initramfs-tools package. # released under the terms of the Artistic Licence. # set -eu PREREQ= prereqs() { echo "$PREREQ" } case "${1:-}" in prereqs) prereqs exit 0 ;; esac is_true() { case "${1:-}" in [Yy]es|[Yy]|1|[Tt]rue|[Tt]) return 0;; *) return 1;; esac } write() { local PREFIX; PREFIX=$1; shift echo "${PREFIX}: mdadm: $@" >&2 } info() { is_true ${VERBOSE:-false} && write I "$@" || : } warn() { write W "$@" } err() { write E "$@" } MDADM=/sbin/mdadm MDMON=/sbin/mdmon [ -x "$MDADM" ] || exit 0 [ -r /usr/share/initramfs-tools/hook-functions ] || exit 0 . /usr/share/initramfs-tools/hook-functions # copy the binary as early as possible copy_exec $MDADM /sbin copy_exec $MDMON /sbin # copy all modules into the initramfs, just for safety. # we copy raid456 / raid5+raid6 because the hook script just won't do # anything when the module cannot be found. modules="linear multipath raid0 raid1 raid456 raid5 raid6 raid10" for mod in $modules; do manual_add_modules $mod; done # read in the configuration CONFIG=/etc/mdadm/mdadm.conf ALTCONFIG=/etc/mdadm.conf [ ! -f $CONFIG ] && [ -f $ALTCONFIG ] && CONFIG=$ALTCONFIG || : DEBIANCONFIG=/etc/default/mdadm INITRDSTART=all [ -s $DEBIANCONFIG ] && . $DEBIANCONFIG [ -z "$INITRDSTART" ] && INITRDSTART=none DESTMDADMCONF=$DESTDIR/etc/mdadm/mdadm.conf DESTCONFIG=$DESTDIR/conf/mdadm if [ -f $CONFIG ]; then homehost="$(sed -ne 's,^[[:space:]]*HOMEHOST[[:space:]]*,,p' $CONFIG)" fi if [ -z "${homehost:-}" ] || [ "${homehost:-}" = '' ]; then echo "MD_HOMEHOST='$(hostname)'" > $DESTCONFIG fi install_config() { # install the configuration file mkdir -p ${2%/*} # only copy ARRAY/DEVICE/HOMEHOST lines, and merge continuation lines into one if [ -f "$1" ] ; then sed -e :a -re '$!N;s/\n[[:space:]]+/ /;ta' -ne '/^(ARRAY|DEVICE|HOMEHOST)/P;D' $1 > $2 fi } if [ ! -f $CONFIG ]; then # there is no configuration file, so let's create one if /usr/share/mdadm/mkconf generate $CONFIG; then # all is well install_config $CONFIG $DESTMDADMCONF info "auto-generated the mdadm.conf configuration file." else # we failed to auto-generate, so let the emergency procedure take over warn "failed to auto-generate the mdadm.conf file." fi else if grep -q '^ARRAY' $CONFIG; then # this is the ideal case install_config $CONFIG $DESTMDADMCONF info "using configuration file: $CONFIG" else # the file defines no ARRAYs. We better create a temporary file to be sure. warn "$CONFIG defines no arrays." mkdir --parents ${DESTMDADMCONF%/*} tmpfile="${DESTMDADMCONF}.tmp" if /usr/share/mdadm/mkconf > $tmpfile; then # all is well, we now have a temporary configuration file info "auto-generated temporary mdadm.conf configuration file." install_config $tmpfile $DESTMDADMCONF else # stuff's really broke, as we failed to generate a temporary file. # let's hope the unchecked file works, provided it contains at least one # ARRAY statement... warn "failed to auto-generate temporary mdadm.conf file." if grep -q '^ARRAY' $CONFIG; then warn "using the unchecked file and hoping for the best..." install_config $CONFIG $DESTMDADMCONF fi fi rm -f $tmpfile fi fi # if at this point, $DESTMDADMCONF does not exist or it does not contain any # ARRAY statements, we must let the initramfs handle stuff. if [ ! -f $DESTMDADMCONF ]; then warn "no configuration file available." info "letting initramfs assemble auto-detected arrays." exit 0 elif ! grep -q '^ARRAY' $DESTMDADMCONF; then warn "no arrays defined in configuration file." info "letting initramfs assemble auto-detected arrays." exit 0 else # obtain devices list from config file, honouring multiline entries devices="$( dev= while read line; do case "$line" in (ARRAY*) :;; (*) continue;; esac for atom in $line; do case "$atom" in (/dev*) dev=$atom;; esac done # /dev/mdX and /dev/md/X are the same, really case "$dev" in "") continue ;; (/dev/md/*) alt=/dev/md${dev##*/};; (/dev/md*) alt=/dev/md/${dev#/dev/md};; (*) err "unknown device encountered: $dev" warn_emergency exit 0 ;; esac if [ ! -b "$dev" ] && [ -b "$alt" ]; then dev="$alt" fi echo "$dev" done < $DESTMDADMCONF)" || exit $? fi if [ "$INITRDSTART" != none ] && [ -n "$devices" ]; then devs= for dev in $devices; do case "$INITRDSTART " in all|*${dev}[[:space:]]*) case "$devs " in # uniquiness (*${dev}\ *) :;; (*) devs="${devs:+$devs }$dev" ;; esac ;; *) :;; esac done # make sure the configuration file knows about all running devices $MDADM --detail --scan | while read array device params; do uuid=${params#*UUID=}; uuid=${uuid%% *} if ! grep -qi "uuid=$uuid" $DESTMDADMCONF; then warn "the array $device with UUID $uuid" warn "is currently active, but it is not listed in mdadm.conf. if" warn "it is needed for boot, then YOUR SYSTEM IS NOW UNBOOTABLE!" warn "please inspect the output of /usr/share/mdadm/mkconf, compare" warn "it to $CONFIG, and make the necessary changes." fi done for i in $INITRDSTART; do case "$INITRDSTART" in all) break;; *) :;; esac case "$devs" in *${i}*) continue;; *) :;; esac warn "I am supposed to start $i from the initial ramdisk," warn "yet I cannot find the array in the configuration file." warn "I am thus reverting to starting all arrays." INITRDSTART=all break done if [ "$INITRDSTART" = all ]; then echo "MD_DEVS=all" >> $DESTCONFIG else echo "MD_DEVS='$devs'" >> $DESTCONFIG fi if [ "$INITRDSTART" = all ]; then info "will start all available MD arrays from the initial ramdisk." else for i in $devs; do info "will start MD array $i from the initial ramdisk." done fi # Copy udev rules, which udev no longer does for rules_file in 63-md-raid-arrays.rules 64-md-raid-assembly.rules do for rules_folder in /lib/udev/rules.d /etc/udev/rules.d; do if [ -f $rules_folder/$rules_file ]; then mkdir -p $DESTDIR$rules_folder cp $rules_folder/$rules_file $DESTDIR$rules_folder/$rules_file fi done done else echo "MD_DEVS=none" >> $DESTCONFIG info "no MD arrays will be started from the initial ramdisk." fi # only output this on Debian systems [ -s /etc/default/mdadm ] && \ info 'use `dpkg-reconfigure --priority=low mdadm` to change this.' exit 0