X-Git-Url: https://git.pld-linux.org/?a=blobdiff_plain;f=mod-multipath.sh;h=559eb5546ed7c8079fb78fddc62a2a196370e8a5;hb=ad5033d7e704edaf52f2be18d4aa98c378179ede;hp=9af9b6e781e4be3f2d8e8fee50de2d2bb9ccd806;hpb=b02a6b13349bc8400580be9e078668b41876bc6e;p=projects%2Fgeninitrd.git diff --git a/mod-multipath.sh b/mod-multipath.sh index 9af9b6e..559eb55 100644 --- a/mod-multipath.sh +++ b/mod-multipath.sh @@ -1,19 +1,21 @@ #!/bin/sh -# # geninitrd mod: dm-multipath +USE_MULTIPATH=${USE_MULTIPATH:-yes} # if we should init dm-multipath at boot have_multipath=no -if [ -x /sbin/multipath ]; then - USE_MULTIPATH=yes -else - USE_MULTIPATH=no -fi - # dm-multipath wwid which is used for rootfs MPATH_WWID= +# setup geninitrd module +# @access public +setup_mod_multipath() { + if [ ! -x /sbin/multipath ]; then + USE_MULTIPATH=no + fi +} + # return true if node is multipath controlled # @param string $node device node to be examined # @access public @@ -21,7 +23,7 @@ is_multipath() { local devpath="$1" # multipath disabled - if ! is_yes "$USE_MULTIPATH"; then + if is_no "$USE_MULTIPATH"; then return 1 fi @@ -33,10 +35,12 @@ is_multipath() { DM_NAME= eval $(dm_export "$devpath") if [ -z "$DM_NAME" ]; then - die "dm_export failed unexpectedly" + die "Couldn't extract DM_NAME from $devpath" fi local MPATH_WWID=${DM_UUID##*-} + + # just check if it is valid. local info=$(multipath -l $MPATH_WWID) if [ -z "$info" ]; then return 1 @@ -56,7 +60,7 @@ find_modules_multipath() { DM_NAME= eval $(dm_export "$devpath") if [ -z "$DM_NAME" ]; then - die "dm_export failed unexpectedly" + die "Couldn't extract DM_NAME from $devpath" fi # Partition: @@ -72,22 +76,24 @@ find_modules_multipath() { return 1 fi - debug "Finding modules for dm-multipath (WWID=$MPATH_WWID)" + verbose "Finding modules for dm-multipath (WWID=$MPATH_WWID)" have_multipath=yes - local dev phydevs=$(echo "$info" | awk '$2 ~ /^[0-9]+:[0-9]+:[0-9]+:[0-9]+$/{printf("/dev/%s\n", $3)}') - for dev in $phydevs; do - find_modules_for_devpath $dev - lvm_ignore_devices="$lvm_ignore_devices $dev" + + local p list + list=$(mp_parse_devs "$info") + for p in $list; do + find_modules_for_devpath $p + lvm_ignore_devices="$lvm_ignore_devices $p" done - local hw hwhandlers=$(echo "$info" | awk '/hwhandler=1/{sub(/.*hwhandler=1 /, ""); sub(/\]$/, ""); print}') - for hw in $hwhandlers; do - find_module "dm-$hw" + list=$(mp_parse_hwhandler "$info") + for p in $list; do + find_module "$p" done - local target targets=$(echo "$info" | awk '/prio=/{print $2}' | sort -u) - for target in $targets; do - find_module "dm-$target" + list=$(mp_parse_policy "$info") + for p in $list; do + find_module "dm-$p" done find_module "dm-mod" @@ -97,17 +103,35 @@ find_modules_multipath() { # generate initrd fragment # @access public initrd_gen_multipath() { + if ! is_yes "$have_multipath"; then + return + fi + inst_d /sbin /lib/udev /etc/multipath inst_exec /sbin/kpartx /sbin inst_exec /sbin/multipath /sbin # for udev callouts - inst_exec /sbin/scsi_id /lib/udev - inst_exec /sbin/mpath* /sbin - egrep -v '^([ ]*$|#)' /etc/multipath.conf > $DESTDIR/etc/multipath.conf + local scsi_id=$(find_tool $(get_libdir /LIBDIR/udev/scsi_id) /lib/udev/scsi_id /sbin/scsi_id) + inst_exec $scsi_id /lib/udev + + local installed=0 + for _lib in $(get_libdir LIBDIR); do + if [ -d /$_lib/multipath ]; then + inst_d /$_lib/multipath + inst_exec /$_lib/multipath/* /$_lib/multipath + installed=1 + break + fi + done + if [ "$installed" -eq 0 ]; then + inst_exec /sbin/mpath* /sbin + fi + + grep -Ev '^([ ]*$|#)' /etc/multipath.conf > $DESTDIR/etc/multipath.conf if [ -f /etc/multipath/bindings ]; then - egrep -v '^([ ]*$|#)' /etc/multipath/bindings > $DESTDIR/etc/multipath/bindings + grep -Ev '^([ ]*$|#)' /etc/multipath/bindings > $DESTDIR/etc/multipath/bindings else touch $DESTDIR/etc/multipath/bindings fi @@ -173,3 +197,103 @@ dm_export() { esac } +# parse blockdevices behind multipath device +# takes 'multipath -l' output as input +mp_parse_devs() { + local info="$1" + + # parse "0:0:1:0 sdf" -> /dev/sdf + # + # multipath-tools-0.4.8-0.12.amd64 + # LUN-02 (36006016002c11800ce520d27c6ebda11) dm-0 DGC ,RAID 10 + # [size=12G][features=1 queue_if_no_path][hwhandler=1 emc] + # \_ round-robin 0 [prio=0][active] + # \_ 0:0:0:0 sda 8:0 [active][undef] + # \_ round-robin 0 [prio=0][enabled] + # \_ 0:0:1:0 sdf 8:80 [active][undef] + # + # multipath-tools-0.4.8-9.x86_64 + # LUN-14 (36006016002c118006f4f8bccc7fada11) dm-3 , + # size=7.0G features='0' hwhandler='0' wp=rw + # |-+- policy='round-robin 0' prio=-1 status=enabled + # | `- #:#:#:# sde 8:64 failed undef running + # `-+- policy='round-robin 0' prio=-1 status=active + # `- #:#:#:# sdb 8:16 active undef running + + echo "$info" | awk '{ + if (match($0, /[#0-9]+:[#0-9]+:[#0-9]+:[#0-9]+ [^ ]+ [0-9]+:[0-9]/)) { + # take whole matched part into "l" variable + l = substr($0, RSTART, RLENGTH); + split(l, a, " "); + printf("/dev/%s\n", a[2]) + } + }' +} + +# parse policy output for each device +# takes 'multipath -l' output as input +mp_parse_policy() { + local info="$1" + + # multipath-tools-0.4.8-0.12.amd64 + # LUN-02 (36006016002c11800ce520d27c6ebda11) dm-0 DGC ,RAID 10 + # [size=12G][features=1 queue_if_no_path][hwhandler=1 emc] + # \_ round-robin 0 [prio=0][active] + # \_ 0:0:0:0 sda 8:0 [active][undef] + # \_ round-robin 0 [prio=0][enabled] + # \_ 0:0:1:0 sdf 8:80 [active][undef] + # + # multipath-tools-0.4.8-9.x86_64 + # LUN-14 (36006016002c118006f4f8bccc7fada11) dm-3 , + # size=7.0G features='0' hwhandler='0' wp=rw + # |-+- policy='round-robin 0' prio=-1 status=enabled + # | `- #:#:#:# sde 8:64 failed undef running + # `-+- policy='round-robin 0' prio=-1 status=active + # `- #:#:#:# sdb 8:16 active undef running + + echo "$info" | awk ' + # multipath-tools-0.4.8-0.12.amd64 + /\[prio=/{ + print $2 + } + # multipath-tools-0.4.8-9.x86_64 + /policy=/{ + if (match($0, /policy=[^ ]+/)) { + # take whole matched part into "l" variable + l = substr($0, RSTART, RLENGTH); + # remove policy= and single quote, + # which we can not use in this awk inline script, therefore the %c hack + sub(sprintf("^policy=%c?", 39), "", l); + print l + } + } + ' | sort -u +} + +# parse hwhandler from multipath output +# takes 'multipath -l' output as input +mp_parse_hwhandler() { + local info="$1" + + # TODO: actually the dm-emc vs scsi-dh-emc is dependant on kernel version + # not version of the tools installed + + # multipath-tools-0.4.8-0.12.amd64 + # [size=12G][features=1 queue_if_no_path][hwhandler=1 emc] + # + # multipath-tools-0.4.8-11.x86_64 + # size=7.0G features='0' hwhandler='0' wp=rw + # size=2.0G features='1 queue_if_no_path' hwhandler='1 emc' wp=rw + echo "$info" | sed -ne " + # multipath-tools-0.4.8-0.12.amd64 + /\[hwhandler=1/{ + s,^.*\[hwhandler=1 \([^]]*\)\].*$,dm-\1, + p + } + # multipath-tools-0.4.8-11.x86_64 + /hwhandler='1/{ + s,^.*hwhandler='1 \([^']*\)'.*$,scsi-dh-\1, + p + } + " | sort -u +}