2 # geninitrd mod: dm-multipath
3 USE_MULTIPATH=${USE_MULTIPATH:-yes}
5 # if we should init dm-multipath at boot
8 # dm-multipath wwid which is used for rootfs
11 # setup geninitrd module
13 setup_mod_multipath() {
14 if [ ! -x /sbin/multipath ]; then
19 # return true if node is multipath controlled
20 # @param string $node device node to be examined
26 if is_no "$USE_MULTIPATH"; then
30 # multipath nodes are under device mapper
31 if [[ "$devpath" != /dev/mapper/* ]]; then
36 eval $(dm_export "$devpath")
37 if [ -z "$DM_NAME" ]; then
38 die "Couldn't extract DM_NAME from $devpath"
41 local MPATH_WWID=${DM_UUID##*-}
43 # just check if it is valid.
44 local info=$(multipath -l $MPATH_WWID)
45 if [ -z "$info" ]; then
52 # find modules for $devpath
53 # @param $devpath device to be examined
55 # find dm-multipath modules for $devpath
56 # returns false if $devpath is not dm-multipath
57 find_modules_multipath() {
61 eval $(dm_export "$devpath")
62 if [ -z "$DM_NAME" ]; then
63 die "Couldn't extract DM_NAME from $devpath"
68 # DM_UUID=part1-mpath-36006016002c11800a0aa05fbfae0db11
71 # DM_UUID=mpath-36006016002c11800a0aa05fbfae0db11
72 MPATH_WWID=${DM_UUID##*-}
74 local info=$(multipath -l $MPATH_WWID)
75 if [ -z "$info" ]; then
79 verbose "Finding modules for dm-multipath (WWID=$MPATH_WWID)"
83 list=$(mp_parse_devs "$info")
85 find_modules_for_devpath $p
86 lvm_ignore_devices="$lvm_ignore_devices $p"
89 list=$(mp_parse_hwhandler "$info")
94 list=$(mp_parse_policy "$info")
103 # generate initrd fragment
105 initrd_gen_multipath() {
106 if ! is_yes "$have_multipath"; then
110 inst_d /sbin /lib/udev /etc/multipath
111 inst_exec /sbin/kpartx /sbin
112 inst_exec /sbin/multipath /sbin
115 local scsi_id=$(find_tool $(get_libdir /LIBDIR/udev/scsi_id) /lib/udev/scsi_id /sbin/scsi_id)
116 inst_exec $scsi_id /lib/udev
119 for _lib in $(get_libdir LIBDIR); do
120 if [ -d /$_lib/multipath ]; then
121 inst_d /$_lib/multipath
122 inst_exec /$_lib/multipath/* /$_lib/multipath
127 if [ "$installed" -eq 0 ]; then
128 inst_exec /sbin/mpath* /sbin
131 grep -Ev '^([ ]*$|#)' /etc/multipath.conf > $DESTDIR/etc/multipath.conf
133 if [ -f /etc/multipath/bindings ]; then
134 grep -Ev '^([ ]*$|#)' /etc/multipath/bindings > $DESTDIR/etc/multipath/bindings
136 touch $DESTDIR/etc/multipath/bindings
143 echo "export MPATH_WWID=$MPATH_WWID" | add_linuxrc
145 # parse mpath_wwid= from kernel commandline
146 for arg in $CMDLINE; do
147 if [ "${arg##mpath_wwid=}" != "${arg}" ]; then
148 MPATH_WWID=${arg##mpath_wwid=}
149 if [ "$MPATH_WWID" = "*" ]; then
150 # '*' would mean activate all WWID-s
152 echo "multipath: Activating all WWID-s"
154 echo "multipath: Activating WWID=$WWID"
160 /sbin/multipath -v 0 $MPATH_WWID
162 for a in /dev/mapper/*; do
163 [ $a = /dev/mapper/control ] && continue
164 /sbin/kpartx -a -p p $a
172 # export info from dmsetup
176 # - /dev/mapper/DM_NAME
182 local maj=${arg%:*} min=${arg#*:}
183 dmsetup -j $maj -m $min export
186 local min=${arg#*dm-}
187 local maj=$(awk '$2 == "device-mapper" {print $1}' /proc/devices)
191 local dm_name=${arg#/dev/mapper/}
192 dmsetup export $dm_name
195 die "dm_export: unexpected $arg"
200 # parse blockdevices behind multipath device
201 # takes 'multipath -l' output as input
205 # parse "0:0:1:0 sdf" -> /dev/sdf
207 # multipath-tools-0.4.8-0.12.amd64
208 # LUN-02 (36006016002c11800ce520d27c6ebda11) dm-0 DGC ,RAID 10
209 # [size=12G][features=1 queue_if_no_path][hwhandler=1 emc]
210 # \_ round-robin 0 [prio=0][active]
211 # \_ 0:0:0:0 sda 8:0 [active][undef]
212 # \_ round-robin 0 [prio=0][enabled]
213 # \_ 0:0:1:0 sdf 8:80 [active][undef]
215 # multipath-tools-0.4.8-9.x86_64
216 # LUN-14 (36006016002c118006f4f8bccc7fada11) dm-3 ,
217 # size=7.0G features='0' hwhandler='0' wp=rw
218 # |-+- policy='round-robin 0' prio=-1 status=enabled
219 # | `- #:#:#:# sde 8:64 failed undef running
220 # `-+- policy='round-robin 0' prio=-1 status=active
221 # `- #:#:#:# sdb 8:16 active undef running
223 echo "$info" | awk '{
224 if (match($0, /[#0-9]+:[#0-9]+:[#0-9]+:[#0-9]+ [^ ]+ [0-9]+:[0-9]/)) {
225 # take whole matched part into "l" variable
226 l = substr($0, RSTART, RLENGTH);
228 printf("/dev/%s\n", a[2])
233 # parse policy output for each device
234 # takes 'multipath -l' output as input
238 # multipath-tools-0.4.8-0.12.amd64
239 # LUN-02 (36006016002c11800ce520d27c6ebda11) dm-0 DGC ,RAID 10
240 # [size=12G][features=1 queue_if_no_path][hwhandler=1 emc]
241 # \_ round-robin 0 [prio=0][active]
242 # \_ 0:0:0:0 sda 8:0 [active][undef]
243 # \_ round-robin 0 [prio=0][enabled]
244 # \_ 0:0:1:0 sdf 8:80 [active][undef]
246 # multipath-tools-0.4.8-9.x86_64
247 # LUN-14 (36006016002c118006f4f8bccc7fada11) dm-3 ,
248 # size=7.0G features='0' hwhandler='0' wp=rw
249 # |-+- policy='round-robin 0' prio=-1 status=enabled
250 # | `- #:#:#:# sde 8:64 failed undef running
251 # `-+- policy='round-robin 0' prio=-1 status=active
252 # `- #:#:#:# sdb 8:16 active undef running
255 # multipath-tools-0.4.8-0.12.amd64
259 # multipath-tools-0.4.8-9.x86_64
261 if (match($0, /policy=[^ ]+/)) {
262 # take whole matched part into "l" variable
263 l = substr($0, RSTART, RLENGTH);
264 # remove policy= and single quote,
265 # which we can not use in this awk inline script, therefore the %c hack
266 sub(sprintf("^policy=%c?", 39), "", l);
273 # parse hwhandler from multipath output
274 # takes 'multipath -l' output as input
275 mp_parse_hwhandler() {
278 # TODO: actually the dm-emc vs scsi-dh-emc is dependant on kernel version
279 # not version of the tools installed
281 # multipath-tools-0.4.8-0.12.amd64
282 # [size=12G][features=1 queue_if_no_path][hwhandler=1 emc]
284 # multipath-tools-0.4.8-11.x86_64
285 # size=7.0G features='0' hwhandler='0' wp=rw
286 # size=2.0G features='1 queue_if_no_path' hwhandler='1 emc' wp=rw
287 echo "$info" | sed -ne "
288 # multipath-tools-0.4.8-0.12.amd64
290 s,^.*\[hwhandler=1 \([^]]*\)\].*$,dm-\1,
293 # multipath-tools-0.4.8-11.x86_64
295 s,^.*hwhandler='1 \([^']*\)'.*$,scsi-dh-\1,