Control: tag -1 patch

Note, this depends on earlier patches sent to
initramfs-to...@packages.debian.org.

Ben.
---
There is no need to parse device names or call utilities to find
device relationships; they are all included in sysfs.

(The generic 'slaves' subdirectory has been present since 2.6.17,
DEVTYPE=partiton since 2.6.25 and /sys/dev/block since 2.6.27.)

This fixes a number of cases where we would wrongly strip a numeric
suffix from a whole-disk device name.  It also allows us to find the
components of a bcache device.

Closes: #747871, #785147, #807004, #807256
Signed-off-by: Ben Hutchings <b...@decadent.org.uk>
---
 hook-functions | 123 ++++++++++++++++-----------------------------------------
 1 file changed, 35 insertions(+), 88 deletions(-)

diff --git a/hook-functions b/hook-functions
index 95f388f..cfd8610 100644
--- a/hook-functions
+++ b/hook-functions
@@ -227,105 +227,52 @@ sys_walk_mod_add()
        done
 }
 
-block_dev_mod_add()
+block_dev_sys_walk_mod_add()
 {
-       local block minor dev_node dev_sys_path
-       dev_node="$1"
+       local dev_sys_path disk_sys_path component
 
-       # lvm or luks device
-       if [ "${dev_node#/dev/mapper/}" != "${dev_node}" ] \
-               || [ "${dev_node#/dev/dm-}" != "${dev_node}" ]; then
-               minor=$((0x$(stat --format "%T" ${dev_node}) % 256))
-               block=$(ls -1 /sys/block/dm-${minor}/slaves | head -n 1)
-               # lvm on luks or luks on lvm, possibly lvm snapshots
-               while [ "${block#dm-}" != "${block}" ]; do
-                       block=$(ls -1 /sys/block/${block}/slaves | head -n 1)
-               done
-               # lvm on md or luks on md
-               if [ "${block#md}" != "${block}" ]; then
-                       block=$(sed -ne 's/multipath/[/' -e 's/linear/[/' -e 
's/raid[0-9][0-9]*/[/' -e 's/\([hs]d[a-z][a-z]*\)[0-9][0-9]*/\1/g' -e 
'/^'${block}' :/s/^[^[]*\[ \([^\[]*\)\[.*$/\1/p' </proc/mdstat)
-               fi
-               # luks or lvm on cciss or ida
-               if [ "${block#cciss}" != "${block}" ] \
-               || [ "${block#ida}" != "${block}" ]; then
-                       block="${block%p*}"
+       while true; do
+               # Resolve symlink so sys_walk_mod_add can walk up the hierarchy
+               dev_sys_path="$(readlink -f "$1")"
+
+               # Find whole disk from partition
+               if grep -q "^DEVTYPE=partition$" "$dev_sys_path/uevent"; then
+                       disk_sys_path="$dev_sys_path/.."
                else
-                       block=${block%%[0-9]*}
+                       disk_sys_path="$dev_sys_path"
                fi
-       # md device new naming scheme /dev/md/X
-       elif [ "${dev_node#/dev/md/}" != "${dev_node}" ]; then
-               dev_node=${dev_node#/dev/md/}
-               # strip partion number
-               dev_node=${dev_node%%p[0-9]*}
-               # drop the partition number only for sdX and hdX devices
-               # and keep it for other devices like loop#, dm-# devices
-               block=$(sed -ne 's/multipath/[/' -e 's/linear/[/' -e 
's/raid[0-9][0-9]*/[/' -e 's/\([hs]d[a-z][a-z]*\)[0-9][0-9]*/\1/g' -e 
'/^md'$dev_node' :/s/^[^[]*\[ \([^\[]*\)\[.*$/\1/p' </proc/mdstat)
-       # md device /dev/mdX
-       elif [ "${dev_node#/dev/md}" != "${dev_node}" ]; then
-               dev_node=${dev_node#/dev/md}
-               # strip partion number
-               dev_node=${dev_node%%p[0-9]*}
-               # drop the partition number only for sdX and hdX devices
-               # and keep it for other devices like loop#, dm-# devices
-               block=$(sed -ne 's/multipath/[/' -e 's/linear/[/' -e 
's/raid[0-9][0-9]*/[/' -e 's/\([hs]d[a-z][a-z]*\)[0-9][0-9]*/\1/g' -e 
'/^md'$dev_node' :/s/^[^[]*\[ \([^\[]*\)\[.*$/\1/p' </proc/mdstat)
-       # cciss device
-       elif [ "${dev_node#/dev/cciss/}" != "${dev_node}" ]; then
-               block=${dev_node#/dev/cciss/*}
-               block="cciss!${block%p*}"
-       # ida device
-       elif [ "${dev_node#/dev/ida/}" != "${dev_node}" ]; then
-               block=${dev_node#/dev/ida/*}
-               block="ida!${block%p*}"
-       # Xen virtual device /dev/xvdX
-       elif [ "${dev_node#/dev/xvd}" != "${dev_node}" ]; then
-               block=${dev_node#/dev/}
-               # Xen has a mode where only the individual partitions are
-               # registered with the kernel as well as the usual full disk
-               # with partition table scheme.
-               if [ ! -e /sys/block/${block} ] ; then
-                       block=${block%%[0-9]*}
+
+               # Find first component of a layered device
+               component="$(ls -1 "$disk_sys_path/slaves" | head -n 1)"
+               if [ -z "$component" ]; then
+                       break
                fi
-       # mmc device /dev/mmcblkXpX
-       elif [ "${dev_node#/dev/mmcblk}" != "${dev_node}" ]; then
-               block=${dev_node#/dev/}
-               block=${block%%p[0-9]*}
-
-       # nbd device /dev/nbdXpX
-       elif [ "${dev_node#/dev/nbd}" != "${dev_node}" ]; then
-               block=${dev_node#/dev/}
-               block=${block%%p[0-9]*}
-
-       # DAC960 - good old mylex raid - device format /dev/rd/cXdXpX
-       elif [ "${dev_node#/dev/rd/c}" != "${dev_node}" ]; then
-               block="rd!c${dev_node#/dev/rd/c}"
-               block=${block%%p[0-9]*}
-
-       # etherd device
-       elif [ "${dev_node#/dev/etherd/}" != "${dev_node}" ]; then
-               block=${dev_node#/dev/etherd/*}
-               block="etherd!${block%p*}"
-       # i2o raid device
-       elif [ "${dev_node#/dev/i2o/}" != "${dev_node}" ]; then
-               block=${dev_node#/dev/i2o/}
-               block=${block%%[0-9]*}
-               block='i2o!'$block
-       # classical block device
-       else
-               block=${dev_node#/dev/}
-               block=${block%%[0-9]*}
-       fi
 
-       # Error out if /sys lack block dev
-       if [ -z "${block}" ] || [ ! -e /sys/block/${block} ]; then
-               echo "mkinitramfs: for device ${dev_node} missing ${block} 
/sys/block/ entry" >&2
+               dev_sys_path="$disk_sys_path/slaves/$component"
+       done
+
+       sys_walk_mod_add ${dev_sys_path}
+}
+
+block_dev_mod_add()
+{
+       local dev_node dev_num dev_sys_path
+       dev_node="$1"
+
+       # Look up device number and convert to decimal as it appears in sysfs
+       dev_num="$(stat -c %t:%T "$dev_node")"
+       dev_num="$((0x${dev_num%:*})):$((0x${dev_num#*:}))"
+
+       # Look up device in sysfs
+       dev_sys_path="/sys/dev/block/$dev_num"
+       if [ ! -d "$dev_sys_path" ]; then
+               echo "mkinitramfs: for device ${dev_node} missing 
${dev_sys_path}" >&2
                echo "mkinitramfs: workaround is MODULES=most" >&2
                echo "mkinitramfs: Error please report the bug" >&2
                exit 1
        fi
 
-       # sys walk ATA
-       dev_sys_path=$(readlink -f /sys/block/${block}/device)
-       sys_walk_mod_add ${dev_sys_path}
+       block_dev_sys_walk_mod_add "$dev_sys_path"
 }
 
 # Copy all loaded or built-in modules matching the given pattern.

-- 
Ben Hutchings
Life would be so much easier if we could look at the source code.

Attachment: signature.asc
Description: This is a digitally signed message part

Reply via email to