Comment 65 for bug 872220

Revision history for this message
Simon Bazley (sibaz) wrote :

diff -u -r initramfs-tools/hooks/mdadm initramfs-tools-mdadm-changes/hooks/mdadm
--- initramfs-tools/hooks/mdadm 2012-08-04 07:54:25.000000000 +0100
+++ initramfs-tools-mdadm-changes/hooks/mdadm 2012-10-03 16:24:49.000000000 +0100
@@ -61,12 +61,112 @@
 done

 # copy the mdadm configuration
+FSTAB=/etc/fstab
 CONFIG=/etc/mdadm/mdadm.conf
 ALTCONFIG=/etc/mdadm.conf
 DESTMDADMCONF=$DESTDIR/etc/mdadm/mdadm.conf
+BOOTREQDDRIVES=$DESTDIR/etc/mdadm/boot_required
 [ ! -f $CONFIG ] && [ -f $ALTCONFIG ] && CONFIG=$ALTCONFIG || :
 mkdir -p ${DESTDIR}/etc/mdadm

+is_md_device()
+{
+ # --misc --detail will only return OK for active arrays
+ mdadm --misc --detail $1 >/dev/null 2>&1
+ ACTIVE=$?
+ # --misc --examine will only return OK for inactive arrays
+ mdadm --misc --examine $1 >/dev/null 2>&1
+ INACTIVE=$?
+ return $((${ACTIVE} & ${INACTIVE}))
+}
+
+find_inactive_md_device_uuid_from_scan()
+{
+ # mdadm --misc --scan --examine returns a list including inactives, but uses the form /dev/md/0 instead of /dev/md0
+ scanname=`echo $1 |sed "s/\(\/dev\/md\)\([0-9]*\)/\1\/\2/"`
+ mdadm --misc --scan --examine 2>/dev/null|grep ${scanname} | while read array device params; do
+ uuid=${params#*UUID=}; uuid=${uuid%% *}
+ echo ${uuid}
+ return 0
+ done
+ return 1
+}
+
+log_details_about_required_md_device()
+{
+ #echo "Seems $1 is an md device"
+ mduuid=`mdadm --misc --detail $1 2>/dev/null|grep UUID|sed "s/^.*UUID : \([:a-z0-9]*\).*$/\1/"`
+ if [ "${mduuid}" = "" ] ; then
+ mduuid=`find_inactive_md_device_uuid_from_scan $1`
+ fi
+ if [ "${mduuid}" != "" ] ; then
+ echo "Identified, md device $1, identified by UUID ${mduuid}, as required in fstab. "
+ echo $1 >> ${BOOTREQDDRIVES}
+ echo ${mduuid} >> ${BOOTREQDDRIVES}
+ return 0
+ else
+ #echo "Couldn't work out the uuid for md device $1"
+ return 1
+ fi
+}
+
+
+identify_required_md_device()
+{
+ #echo "Identifying $1"
+ #Device identified as a valid device, so lets see if it is an md device
+ if is_md_device $1; then
+ #echo "$1 is an md_device"
+ # It is an md device, so try to log important details, for next boot
+ if ! log_details_about_required_md_device $1; then
+ # Something went wrong identifying device details, so just log what we can
+ echo "Had issues identifying details for md_device $1"
+ if ! grep -q $1 ${BOOTREQDDRIVES}; then
+ echo $1 ${BOOTREQDDRIVES}
+ fi
+ fi
+# else
+# echo "$1 is not an md_device"
+ fi
+}
+
+# PARSE FSTAB to get a list of md file_systems essential for boot
+rm -f ${BOOTREQDDRIVES}
+touch ${BOOTREQDDRIVES}
+cat ${FSTAB} | grep -v ^\# | while read file_system mount_point type options dump pass; do
+ if [ "${pass}" = "" ] ; then
+ pass=0
+ fi
+ if [ ${pass} != 0 ] ; then
+ # Looks like ${file_system} is one who's failure would halt the boot, so consider it as a required device
+ #echo "Considering ${file_system}"
+ if echo "${file_system}" | grep -q "UUID"; then
+ # Device identified by UUID, so look up the actual device name
+ uuid=${file_system#*UUID=}; uuid=${uuid%% *}
+ mount_source=`readlink -f /dev/disk/by-uuid/${uuid}`
+ # ${mount_source} is the path I'd expect to be the actual device, let's see if that is a valid device
+ if [ -e "/dev/disk/by-uuid/${uuid}" -a "${mount_source}" != "" ] ; then
+ identify_required_md_device ${mount_source}
+ else
+ # Generated device name didn't lookup to something valid, that could be a device mapper issue
+ # This might be a problem with which kernel modules are loaded right now, rather than a problem
+ # So register an error, and log the UUID that we have so far as required, it might be enough
+ echo "Seems readlink couldn't identify /dev/disk/by-uuid/${uuid}. Assuming it's required for boot"
+ if ! grep -q ${uuid} ${BOOTREQDDRIVES}; then
+ echo ${uuid} >> ${BOOTREQDDRIVES}
+ fi
+ fi
+ else
+ # Not a UUID device, so let's look up the device name to double check it isn't an md device anyway
+ identify_required_md_device ${file_system}
+ fi
+ fi
+done
+if [ ! -s ${BOOTREQDDRIVES} ] ; then
+ rm -f ${BOOTREQDDRIVES}
+ echo "Checking /etc/fstab found no md devices are require to boot"
+fi
+
 if [ ! -f $CONFIG ]; then
         # there is no configuration file, so let's create one
         if /usr/share/mdadm/mkconf generate $CONFIG; then
diff -u -r initramfs-tools/scripts/local-premount/mdadm initramfs-tools-mdadm-changes/scripts/local-premount/mdadm
--- initramfs-tools/scripts/local-premount/mdadm 2012-08-04 07:54:25.000000000 +0100
+++ initramfs-tools-mdadm-changes/scripts/local-premount/mdadm 2012-10-03 16:09:27.000000000 +0100
@@ -8,5 +8,7 @@
 . /scripts/functions

 wait_for_udev
-degraded_arrays || exit 0
-mountroot_fail || panic "Dropping to a shell."
+(degraded_arrays && degraded_arrays_needed_for_boot) || exit 0
+sleep 10
+#degraded_arrays || exit 0
+mountroot_fail || panic "Dropping to a shell (type exit to attempt to continue with a normal boot)."
diff -u -r initramfs-tools/scripts/mdadm-functions initramfs-tools-mdadm-changes/scripts/mdadm-functions
--- initramfs-tools/scripts/mdadm-functions 2012-08-04 07:54:25.000000000 +0100
+++ initramfs-tools-mdadm-changes/scripts/mdadm-functions 2012-10-03 16:09:01.000000000 +0100
@@ -1,15 +1,61 @@
 #!/bin/sh

+find_inactive_md_device_uuid_from_scan()
+{
+ # mdadm --misc --scan --examine returns a list including inactives, but uses the form /dev/md/0 instead of /dev/md0
+ scanname=`echo $1 |sed "s/\(\/dev\/md\)\([0-9]*\)/\1\/\2/"`
+ mdadm --misc --scan --examine 2>/dev/null|grep ${scanname} | while read array device params; do
+ uuid=${params#*UUID=}; uuid=${uuid%% *}
+ echo ${uuid}
+ return 0
+ done
+ return 1
+}
+
+degraded_arrays_needed_for_boot()
+{
+ BOOTREQDDRIVES=/etc/mdadm/boot_required
+ if [ ! -s ${BOOTREQDDRIVES} ] ; then
+ echo "There are no md devices required to boot"
+ return 1
+ fi
+ if ! degraded_arrays; then
+ echo "There are no degraded arrays, so no need to check for required devices"
+ return 1
+ fi
+ #cat ${BOOTREQDDRIVES}
+ # --scan --detail will return active arrays on stdout and inactive messages identifying arrays on stderr
+ /sbin/mdadm --misc --scan --detail 2>&1 |grep "does not appear to be active"| while read mdadm md dev device extras; do
+ uuid=`find_inactive_md_device_uuid_from_scan ${device}`
+ echo "Found ${device} aka ${uuid} to be degraded"
+ if grep -q "${device}" ${BOOTREQDDRIVES}; then
+ echo "Found ${device} in list of md devices that are required to boot"
+ return 1
+ fi
+ if grep -q "${uuid}" ${BOOTREQDDRIVES}; then
+ echo "Found ${uuid} in list of md devices that are required to boot"
+ return 1
+ fi
+ done
+ if [ $? = 1 ]; then
+ return 0
+ fi
+ echo "None of the degraded devices were found in list of md devices that are required to boot"
+ return 1
+}

 degraded_arrays()
 {
        mdadm --misc --scan --detail --test >/dev/null 2>&1
        return $((! $?))
+ #RETVAL=$?
+ #echo "Returning $((! ${RETVAL}))"
+ #return $((! ${RETVAL}))
 }

 mountroot_fail()
 {
- if degraded_arrays; then
+ if degraded_arrays && degraded_arrays_needed_for_boot; then
                cat <<EOF
 ** WARNING: There appears to be one or more degraded RAID devices **