]> git.pld-linux.org Git - projects/geninitrd.git/blob - mod-multipath.sh
926e6aec117451d0f14f01d51024b3d5ae72230f
[projects/geninitrd.git] / mod-multipath.sh
1 #!/bin/sh
2 MULTIPATH_RCSID='$Revision$ $Date::                            $'
3
4 # geninitrd mod: dm-multipath
5 USE_MULTIPATH=${USE_MULTIPATH:-yes}
6
7 # if we should init dm-multipath at boot
8 have_multipath=no
9
10 # dm-multipath wwid which is used for rootfs
11 MPATH_WWID=
12
13 # setup geninitrd module
14 # @access       public
15 setup_mod_multipath() {
16         if [ ! -x /sbin/multipath ]; then
17                 USE_MULTIPATH=no
18         fi
19 }
20
21 # return true if node is multipath controlled
22 # @param        string $node device node to be examined
23 # @access       public
24 is_multipath() {
25         local devpath="$1"
26
27         # multipath disabled
28         if is_no "$USE_MULTIPATH"; then
29                 return 1
30         fi
31
32         # multipath nodes are under device mapper
33         if [[ "$devpath" != /dev/mapper/* ]]; then
34                 return 1
35         fi
36
37         DM_NAME=
38         eval $(dm_export "$devpath")
39         if [ -z "$DM_NAME" ]; then
40                 die "Couldn't extract DM_NAME from $devpath"
41         fi
42
43         local MPATH_WWID=${DM_UUID##*-}
44
45         # just check if it is valid.
46         local info=$(multipath -l $MPATH_WWID)
47         if [ -z "$info" ]; then
48                 return 1
49         fi
50
51         return 0
52 }
53
54 # find modules for $devpath
55 # @param        $devpath        device to be examined
56 # @access       public
57 # find dm-multipath modules for $devpath
58 # returns false if $devpath is not dm-multipath
59 find_modules_multipath() {
60         local devpath="$1"
61
62         DM_NAME=
63         eval $(dm_export "$devpath")
64         if [ -z "$DM_NAME" ]; then
65                 die "Couldn't extract DM_NAME from $devpath"
66         fi
67
68         # Partition:
69         #  DM_NAME=LUN-28p1
70         #  DM_UUID=part1-mpath-36006016002c11800a0aa05fbfae0db11
71         # Disk:
72         #  DM_NAME=LUN-28
73         #  DM_UUID=mpath-36006016002c11800a0aa05fbfae0db11
74         MPATH_WWID=${DM_UUID##*-}
75
76         local info=$(multipath -l $MPATH_WWID)
77         if [ -z "$info" ]; then
78                 return 1
79         fi
80
81         verbose "Finding modules for dm-multipath (WWID=$MPATH_WWID)"
82         have_multipath=yes
83
84         local p list
85         list=$(mp_parse_devs "$info")
86         for p in $list; do
87                 find_modules_for_devpath $p
88                 lvm_ignore_devices="$lvm_ignore_devices $p"
89         done
90
91         list=$(mp_parse_hwhandler "$info")
92         for p in $list; do
93                 find_module "$p"
94         done
95
96         list=$(mp_parse_policy "$info")
97         for p in $list; do
98                 find_module "dm-$p"
99         done
100
101         find_module "dm-mod"
102         return 0
103 }
104
105 # generate initrd fragment
106 # @access       public
107 initrd_gen_multipath() {
108         if ! is_yes "$have_multipath"; then
109                 return
110         fi
111
112         inst_d /sbin /lib/udev /etc/multipath
113         inst_exec /sbin/kpartx /sbin
114         inst_exec /sbin/multipath /sbin
115
116         # for udev callouts
117         local scsi_id=$(find_tool /$_lib/udev/scsi_id /lib/udev/scsi_id /sbin/scsi_id)
118         inst_exec $scsi_id /lib/udev
119
120         if [ -d /$_lib/multipath ]; then
121                 inst_d /$_lib/multipath
122                 inst_exec /$_lib/multipath/* /$_lib/multipath
123         else
124                 inst_exec /sbin/mpath* /sbin
125         fi
126
127         grep -Ev '^([   ]*$|#)' /etc/multipath.conf > $DESTDIR/etc/multipath.conf
128
129         if [ -f /etc/multipath/bindings ]; then
130                 grep -Ev '^([   ]*$|#)' /etc/multipath/bindings > $DESTDIR/etc/multipath/bindings
131         else
132                 touch $DESTDIR/etc/multipath/bindings
133         fi
134
135         mount_dev
136         initrd_gen_devices
137
138         mount_sys
139         echo "export MPATH_WWID=$MPATH_WWID" | add_linuxrc
140         add_linuxrc <<-'EOF'
141                 # parse mpath_wwid= from kernel commandline
142                 for arg in $CMDLINE; do
143                         if [ "${arg##mpath_wwid=}" != "${arg}" ]; then
144                                 MPATH_WWID=${arg##mpath_wwid=}
145                                 if [ "$MPATH_WWID" = "*" ]; then
146                                         # '*' would mean activate all WWID-s
147                                         MPATH_WWID=
148                                         echo "multipath: Activating all WWID-s"
149                                 else
150                                         echo "multipath: Activating WWID=$WWID"
151                                 fi
152                         fi
153                 done
154
155                 debugshell
156                 /sbin/multipath -v 0 $MPATH_WWID
157
158                 for a in /dev/mapper/*; do
159                         [ $a = /dev/mapper/control ] && continue
160                         /sbin/kpartx -a -p p $a
161                 done
162                 debugshell
163         EOF
164 }
165
166
167 # PRIVATE METHODS
168 # export info from dmsetup
169 # param can be:
170 # - MAJOR:MINOR
171 # - /dev/dm-MINOR
172 # - /dev/mapper/DM_NAME
173 dm_export() {
174         local arg="$1"
175
176         case "$arg" in
177         *:*)
178                 local maj=${arg%:*} min=${arg#*:}
179                 dmsetup -j $maj -m $min export
180                 ;;
181         /dev/dm-*)
182                 local min=${arg#*dm-}
183                 local maj=$(awk '$2 == "device-mapper" {print $1}' /proc/devices)
184                 dm_export $maj:$min
185                 ;;
186         /dev/mapper/*)
187                 local dm_name=${arg#/dev/mapper/}
188                 dmsetup export $dm_name
189                 ;;
190         *)
191                 die "dm_export: unexpected $arg"
192                 ;;
193         esac
194 }
195
196 # parse blockdevices behind multipath device
197 # takes 'multipath -l' output as input
198 mp_parse_devs() {
199         local info="$1"
200
201         # parse "0:0:1:0 sdf" -> /dev/sdf
202         #
203         # multipath-tools-0.4.8-0.12.amd64
204         # LUN-02 (36006016002c11800ce520d27c6ebda11) dm-0 DGC     ,RAID 10
205         # [size=12G][features=1 queue_if_no_path][hwhandler=1 emc]
206         # \_ round-robin 0 [prio=0][active]
207         #  \_ 0:0:0:0 sda 8:0   [active][undef]
208         # \_ round-robin 0 [prio=0][enabled]
209         #  \_ 0:0:1:0 sdf 8:80  [active][undef]
210         #
211         # multipath-tools-0.4.8-9.x86_64
212         # LUN-14 (36006016002c118006f4f8bccc7fada11) dm-3 ,
213         # size=7.0G features='0' hwhandler='0' wp=rw
214         # |-+- policy='round-robin 0' prio=-1 status=enabled
215         # | `- #:#:#:# sde 8:64 failed undef running
216         # `-+- policy='round-robin 0' prio=-1 status=active
217         #   `- #:#:#:# sdb 8:16 active undef running
218
219         echo "$info" | awk '{
220                 if (match($0, /[#0-9]+:[#0-9]+:[#0-9]+:[#0-9]+ [^ ]+ [0-9]+:[0-9]/)) {
221                         # take whole matched part into "l" variable
222                         l = substr($0, RSTART, RLENGTH);
223                         split(l, a, " ");
224                         printf("/dev/%s\n", a[2])
225                 }
226         }'
227 }
228
229 # parse policy output for each device
230 # takes 'multipath -l' output as input
231 mp_parse_policy() {
232         local info="$1"
233
234         # multipath-tools-0.4.8-0.12.amd64
235         # LUN-02 (36006016002c11800ce520d27c6ebda11) dm-0 DGC     ,RAID 10
236         # [size=12G][features=1 queue_if_no_path][hwhandler=1 emc]
237         # \_ round-robin 0 [prio=0][active]
238         #  \_ 0:0:0:0 sda 8:0   [active][undef]
239         # \_ round-robin 0 [prio=0][enabled]
240         #  \_ 0:0:1:0 sdf 8:80  [active][undef]
241         #
242         # multipath-tools-0.4.8-9.x86_64
243         # LUN-14 (36006016002c118006f4f8bccc7fada11) dm-3 ,
244         # size=7.0G features='0' hwhandler='0' wp=rw
245         # |-+- policy='round-robin 0' prio=-1 status=enabled
246         # | `- #:#:#:# sde 8:64 failed undef running
247         # `-+- policy='round-robin 0' prio=-1 status=active
248         #   `- #:#:#:# sdb 8:16 active undef running
249
250         echo "$info" | awk '
251                 # multipath-tools-0.4.8-0.12.amd64
252                 /\[prio=/{
253                         print $2
254                 }
255                 # multipath-tools-0.4.8-9.x86_64
256                 /policy=/{
257                         if (match($0, /policy=[^ ]+/)) {
258                                 # take whole matched part into "l" variable
259                                 l = substr($0, RSTART, RLENGTH);
260                                 # remove policy= and single quote,
261                                 # which we can not use in this awk inline script, therefore the %c hack
262                                 sub(sprintf("^policy=%c?", 39), "", l);
263                                 print l
264                         }
265                 }
266         ' | sort -u
267 }
268
269 # parse hwhandler from multipath output
270 # takes 'multipath -l' output as input
271 mp_parse_hwhandler() {
272         local info="$1"
273
274         # TODO: actually the dm-emc vs scsi-dh-emc is dependant on kernel version
275         # not version of the tools installed
276
277         # multipath-tools-0.4.8-0.12.amd64
278         # [size=12G][features=1 queue_if_no_path][hwhandler=1 emc]
279         #
280         # multipath-tools-0.4.8-11.x86_64
281         # size=7.0G features='0' hwhandler='0' wp=rw
282         # size=2.0G features='1 queue_if_no_path' hwhandler='1 emc' wp=rw
283         echo "$info" | sed -ne "
284                 # multipath-tools-0.4.8-0.12.amd64
285                 /\[hwhandler=1/{
286                         s,^.*\[hwhandler=1 \([^]]*\)\].*$,dm-\1,
287                         p
288                 }
289                 # multipath-tools-0.4.8-11.x86_64
290                 /hwhandler='1/{
291                         s,^.*hwhandler='1 \([^']*\)'.*$,scsi-dh-\1,
292                         p
293                 }
294         " | sort -u
295 }
This page took 0.211239 seconds and 2 git commands to generate.