]> git.pld-linux.org Git - projects/geninitrd.git/blob - mod-multipath.sh
luks: reword warning about unsupported option
[projects/geninitrd.git] / mod-multipath.sh
1 #!/bin/sh
2 # geninitrd mod: dm-multipath
3 USE_MULTIPATH=${USE_MULTIPATH:-yes}
4
5 # if we should init dm-multipath at boot
6 have_multipath=no
7
8 # dm-multipath wwid which is used for rootfs
9 MPATH_WWID=
10
11 # setup geninitrd module
12 # @access       public
13 setup_mod_multipath() {
14         if [ ! -x /sbin/multipath ]; then
15                 USE_MULTIPATH=no
16         fi
17 }
18
19 # return true if node is multipath controlled
20 # @param        string $node device node to be examined
21 # @access       public
22 is_multipath() {
23         local devpath="$1"
24
25         # multipath disabled
26         if is_no "$USE_MULTIPATH"; then
27                 return 1
28         fi
29
30         # multipath nodes are under device mapper
31         if [[ "$devpath" != /dev/mapper/* ]]; then
32                 return 1
33         fi
34
35         DM_NAME=
36         eval $(dm_export "$devpath")
37         if [ -z "$DM_NAME" ]; then
38                 die "Couldn't extract DM_NAME from $devpath"
39         fi
40
41         local MPATH_WWID=${DM_UUID##*-}
42
43         # just check if it is valid.
44         local info=$(multipath -l $MPATH_WWID)
45         if [ -z "$info" ]; then
46                 return 1
47         fi
48
49         return 0
50 }
51
52 # find modules for $devpath
53 # @param        $devpath        device to be examined
54 # @access       public
55 # find dm-multipath modules for $devpath
56 # returns false if $devpath is not dm-multipath
57 find_modules_multipath() {
58         local devpath="$1"
59
60         DM_NAME=
61         eval $(dm_export "$devpath")
62         if [ -z "$DM_NAME" ]; then
63                 die "Couldn't extract DM_NAME from $devpath"
64         fi
65
66         # Partition:
67         #  DM_NAME=LUN-28p1
68         #  DM_UUID=part1-mpath-36006016002c11800a0aa05fbfae0db11
69         # Disk:
70         #  DM_NAME=LUN-28
71         #  DM_UUID=mpath-36006016002c11800a0aa05fbfae0db11
72         MPATH_WWID=${DM_UUID##*-}
73
74         local info=$(multipath -l $MPATH_WWID)
75         if [ -z "$info" ]; then
76                 return 1
77         fi
78
79         verbose "Finding modules for dm-multipath (WWID=$MPATH_WWID)"
80         have_multipath=yes
81
82         local p list
83         list=$(mp_parse_devs "$info")
84         for p in $list; do
85                 find_modules_for_devpath $p
86                 lvm_ignore_devices="$lvm_ignore_devices $p"
87         done
88
89         list=$(mp_parse_hwhandler "$info")
90         for p in $list; do
91                 find_module "$p"
92         done
93
94         list=$(mp_parse_policy "$info")
95         for p in $list; do
96                 find_module "dm-$p"
97         done
98
99         find_module "dm-mod"
100         return 0
101 }
102
103 # generate initrd fragment
104 # @access       public
105 initrd_gen_multipath() {
106         if ! is_yes "$have_multipath"; then
107                 return
108         fi
109
110         inst_d /sbin /lib/udev /etc/multipath
111         inst_exec /sbin/kpartx /sbin
112         inst_exec /sbin/multipath /sbin
113
114         # for udev callouts
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
117
118         local installed=0
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
123                         installed=1
124                         break
125                 fi
126         done
127         if [ "$installed" -eq 0 ]; then
128                 inst_exec /sbin/mpath* /sbin
129         fi
130
131         grep -Ev '^([   ]*$|#)' /etc/multipath.conf > $DESTDIR/etc/multipath.conf
132
133         if [ -f /etc/multipath/bindings ]; then
134                 grep -Ev '^([   ]*$|#)' /etc/multipath/bindings > $DESTDIR/etc/multipath/bindings
135         else
136                 touch $DESTDIR/etc/multipath/bindings
137         fi
138
139         mount_dev
140         initrd_gen_devices
141
142         mount_sys
143         echo "export MPATH_WWID=$MPATH_WWID" | add_linuxrc
144         add_linuxrc <<-'EOF'
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
151                                         MPATH_WWID=
152                                         echo "multipath: Activating all WWID-s"
153                                 else
154                                         echo "multipath: Activating WWID=$WWID"
155                                 fi
156                         fi
157                 done
158
159                 debugshell
160                 /sbin/multipath -v 0 $MPATH_WWID
161
162                 for a in /dev/mapper/*; do
163                         [ $a = /dev/mapper/control ] && continue
164                         /sbin/kpartx -a -p p $a
165                 done
166                 debugshell
167         EOF
168 }
169
170
171 # PRIVATE METHODS
172 # export info from dmsetup
173 # param can be:
174 # - MAJOR:MINOR
175 # - /dev/dm-MINOR
176 # - /dev/mapper/DM_NAME
177 dm_export() {
178         local arg="$1"
179
180         case "$arg" in
181         *:*)
182                 local maj=${arg%:*} min=${arg#*:}
183                 dmsetup -j $maj -m $min export
184                 ;;
185         /dev/dm-*)
186                 local min=${arg#*dm-}
187                 local maj=$(awk '$2 == "device-mapper" {print $1}' /proc/devices)
188                 dm_export $maj:$min
189                 ;;
190         /dev/mapper/*)
191                 local dm_name=${arg#/dev/mapper/}
192                 dmsetup export $dm_name
193                 ;;
194         *)
195                 die "dm_export: unexpected $arg"
196                 ;;
197         esac
198 }
199
200 # parse blockdevices behind multipath device
201 # takes 'multipath -l' output as input
202 mp_parse_devs() {
203         local info="$1"
204
205         # parse "0:0:1:0 sdf" -> /dev/sdf
206         #
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]
214         #
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
222
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);
227                         split(l, a, " ");
228                         printf("/dev/%s\n", a[2])
229                 }
230         }'
231 }
232
233 # parse policy output for each device
234 # takes 'multipath -l' output as input
235 mp_parse_policy() {
236         local info="$1"
237
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]
245         #
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
253
254         echo "$info" | awk '
255                 # multipath-tools-0.4.8-0.12.amd64
256                 /\[prio=/{
257                         print $2
258                 }
259                 # multipath-tools-0.4.8-9.x86_64
260                 /policy=/{
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);
267                                 print l
268                         }
269                 }
270         ' | sort -u
271 }
272
273 # parse hwhandler from multipath output
274 # takes 'multipath -l' output as input
275 mp_parse_hwhandler() {
276         local info="$1"
277
278         # TODO: actually the dm-emc vs scsi-dh-emc is dependant on kernel version
279         # not version of the tools installed
280
281         # multipath-tools-0.4.8-0.12.amd64
282         # [size=12G][features=1 queue_if_no_path][hwhandler=1 emc]
283         #
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
289                 /\[hwhandler=1/{
290                         s,^.*\[hwhandler=1 \([^]]*\)\].*$,dm-\1,
291                         p
292                 }
293                 # multipath-tools-0.4.8-11.x86_64
294                 /hwhandler='1/{
295                         s,^.*hwhandler='1 \([^']*\)'.*$,scsi-dh-\1,
296                         p
297                 }
298         " | sort -u
299 }
This page took 0.046079 seconds and 3 git commands to generate.