]> git.pld-linux.org Git - projects/geninitrd.git/blobdiff - mod-multipath.sh
Timeout here is not a good idea. rootfs cannot be mounted and kernel oopses due to...
[projects/geninitrd.git] / mod-multipath.sh
index 9af9b6e781e4be3f2d8e8fee50de2d2bb9ccd806..559eb5546ed7c8079fb78fddc62a2a196370e8a5 100644 (file)
@@ -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
+}
This page took 0.222646 seconds and 4 git commands to generate.