]> git.pld-linux.org Git - projects/geninitrd.git/blob - mod-lvm.sh
drop rcsid stuff; not functional with git
[projects/geninitrd.git] / mod-lvm.sh
1 #!/bin/sh
2 # geninitrd mod: LVM
3 USE_LVM=${USE_LVM:-yes}
4
5 # if we should init LVM at boot
6 have_lvm=no
7
8 # LVM volumes that are needed to activate
9 # VG for root dev
10 # @internal
11 LVM_ROOTVG=""
12
13 # VG for suspend resume dev
14 LVM_SUSPENDVG=""
15
16 LVM_VGVOLUMES=""
17
18 # LVM version. Autodetected if not set.
19 # Values: 1|2
20 LVMTOOLSVERSION=
21
22 # LVM devices that should not be included in vgscan on initrd.
23 # @internal
24 lvm_ignore_devices=''
25
26 # setup geninitrd module
27 # @access       public
28 setup_mod_lvm() {
29         lvm=$(find_tool $initrd_dir/lvm /sbin/initrd-lvm)
30
31         if [ ! -x "$lvm" ]; then
32                 USE_LVM=no
33         fi
34
35         if is_yes "$USE_LVM" && [ -z "$LVMTOOLSVERSION" ]; then
36                 LVMTOOLSVERSION=$(LC_ALL=C $lvm vgchange --version 2>/dev/null | awk '/LVM version:/{if ($3 >= 2) print "2"}')
37                 if [ -z "$LVMTOOLSVERSION" ]; then
38                         die "Can't determine LVM tools version (is /sys mounted?). Please set LVMTOOLSVERSION and rerun $PROGRAM."
39                 fi
40         fi
41 }
42
43 # return true if node is lvm node
44 # @param        string $node device node to be examined
45 # @access       public
46 is_lvm() {
47         local node="$1"
48
49         # LVM not wanted
50         if is_no "$USE_LVM"; then
51                 return 1
52         fi
53
54         if [ ! -e "$node" ]; then
55                 die "check_lvm(): node $node doesn't exist!"
56                 return 1
57         fi
58
59         # block-major-58 is lvm1
60         ls -lL "$node" 2> /dev/null | awk '{if (/^b/) { if ($5 == "58,") { exit 0; } else { exit 1; } } else { exit 1; }}'
61         rc=$?
62
63         if [ $rc = 0 ]; then
64                 # is lvm1
65                 return 0
66         fi
67
68         $lvm lvdisplay "$node" > /dev/null 2>&1
69         rc=$?
70         if [ $rc -gt 127 ]; then
71                 # lvdisplay terminated by signal! most likely it segfaulted.
72                 die "Unexpected exit from 'lvdisplay $node': $rc - are your lvm tools broken?"
73         fi
74
75         return $rc
76 }
77
78 # find modules for $devpath
79 # @param        $devpath        device to be examined
80 # @access       public
81 find_modules_lvm() {
82         local devpath="$1"
83
84         verbose "LVM: $devpath is LVM node"
85
86         local vg=$(find_lvm_vg "$devpath")
87         verbose "LVM VG for $devpath: $vg"
88         LVM_VGVOLUMES=$(echo $LVM_VGVOLUMES $vg | tr ' ' '\n' | sort -u)
89
90         local pv=$(find_lvm_pv "$vg")
91         verbose "LVM PV for $vg: $pv"
92         PVDEVICES=$(echo $PVDEVICES $pv | tr ' ' '\n' | sort -u)
93
94         if [ -n "$PVDEVICES" ]; then
95                 for device in $PVDEVICES; do
96                         find_modules_for_devpath $device
97                 done
98         else
99                 die "I wasn't able to find PV. You can try to set PVDEVICES in /etc/sysconfig/geninitrd."
100         fi
101
102         if [ "$LVMTOOLSVERSION" = "2" ]; then
103                 find_module "-dm-mod"
104         elif [ "$LVMTOOLSVERSION" = "1" ]; then
105                 find_module "-lvm"
106                 find_module "-lvm-mod"
107         else
108                 die "LVM version $LVMTOOLSVERSION is not supported."
109         fi
110
111         verbose "LVM v$LVMTOOLSVERSION enabled"
112         have_lvm=yes
113 }
114
115
116 # generate initrd fragment for lvm
117 # @access       public
118 initrd_gen_lvm() {
119         if ! is_yes "$have_lvm"; then
120                 return
121         fi
122
123         verbose "Adding LVM support to initrd"
124         inst_d /tmp /newroot
125         inst_exec $lvm /bin/lvm.static
126
127         # always make /dev on tmpfs for LVM2
128         if [ "$LVMTOOLSVERSION" = "2" ]; then
129                 mount_dev
130         fi
131
132         if ! is_yes "$dev_mounted"; then
133                 inst_d /dev/mapper
134                 mknod -m 600 $DESTDIR/dev/mapper/control c 10 63
135                 for device in $PVDEVICES; do
136                         # if LVM on RAID then device might be copied already in gen_md
137                         [ -e "$DESTDIR/dev/$(basename $device)" ] && continue
138                         inst $device /dev
139                 done
140         fi
141
142         mount_tmp
143         mount_sys
144         if [ "$LVMTOOLSVERSION" = "1" ]; then
145                 add_linuxrc <<-EOF
146                         lvm vgscan -T
147                         for vg in $LVM_VGVOLUMES; do
148                                 lvm vgchange -T -a y $vg
149                         done
150                 EOF
151         else
152                 cat <<-EOF > "$DESTDIR/etc/lvm.conf"
153                 global {
154                         locking_type = 0
155                         locking_dir = "/tmp"
156                 }
157                 devices {
158                         sysfs_scan=0
159                 EOF
160                 if is_yes "$have_md"; then
161                         echo "  md_component_detection=1" >> "$DESTDIR/etc/lvm.conf"
162                 fi
163                 if is_yes "$have_dmraid" || is_yes "$have_multipath"; then
164                         echo '  types = [ "device-mapper", 254 ]' >> "$DESTDIR/etc/lvm.conf"
165                 fi
166                 if [ "$lvm_ignore_devices" ]; then
167                         # TODO: think of merging with lvm dumpconfig output
168                         echo '  filter = [' >> "$DESTDIR/etc/lvm.conf"
169                         local dev
170                         for dev in $lvm_ignore_devices; do
171                                 verbose "LVM v2: ignore device $dev"
172                                 printf '  "r|^%s.*|",\n' $dev
173                         done >> "$DESTDIR/etc/lvm.conf"
174                         echo ']' >> "$DESTDIR/etc/lvm.conf"
175                 fi
176                 # XXX filter= must be on one line!
177                 $lvm dumpconfig | awk '/filter=/' >> "$DESTDIR/etc/lvm.conf"
178                 echo "}" >> "$DESTDIR/etc/lvm.conf"
179
180                 echo "cat /etc/lvm.conf > /tmp/lvm.conf" | add_linuxrc
181
182                 initrd_gen_devices
183
184                 add_linuxrc <<-EOF
185                         ROOTDEV=$rootdev
186                         LVM_ROOTVG="$LVM_VGVOLUMES"
187                         LVM_SUSPENDVG="$LVM_SUSPENDVG"
188                 EOF
189
190                 # need awk for "s/--/-/g" subst when parsing kernel root commandline
191                 busybox_applet awk
192                 add_linuxrc <<-'EOF'
193                         # parse rootdev from kernel commandline if it begins with /
194                         case "$ROOT" in
195                                 /*)
196
197                                 # rewrite:
198                                 # /dev/mapper/sys-rootfs -> /dev/sys/rootfs
199                                 # /dev/mapper/blodnatt-blah--bleh -> /dev/blodnatt/blah-bleh
200                                 # /dev/mapper/vg--meaw-root -> /dev/vg-meaw/root
201                                 case "$ROOT" in
202                                         /dev/mapper/*-*)
203                                                 # change "--" to / (as "/" is impossible in LV name)
204                                                 local dev=$(awk -vdev="${ROOT#/dev/mapper/}" 'BEGIN{gsub(/--/, "/", dev); print dev}')
205                                                 local VG=$(awk -vdev="$dev" 'BEGIN{split(dev, v, "-"); gsub("/", "-", v[1]); print v[1]}')
206                                                 local LV=$(awk -vdev="$dev" 'BEGIN{split(dev, v, "-"); gsub("/", "-", v[2]); print v[2]}')
207                                                 ROOT=/dev/$VG/$LV
208                                         ;;
209                                 esac
210
211                                 if [ "$ROOT" != "$ROOTDEV" ]; then
212                                         ROOTDEV=$ROOT
213
214                                         echo "LVM: Using 'root=$ROOTDEV' from kernel commandline"
215                                         local tmp=${ROOTDEV#/dev/}
216                                         if [ "$tmp" != "$ROOTDEV" ]; then
217                                                 LVM_ROOTVG=${tmp%/*}
218                                                 echo "LVM: Using Volume Group '$LVM_ROOTVG' for rootfs"
219                                         fi
220                                 fi
221                                 ;;
222                         esac
223
224                         # skip duplicate VG
225                         if [ "$LVM_SUSPENDVG" = "$LVM_ROOTVG" ]; then
226                                 LVM_VGVOLUMES="$LVM_ROOTVG"
227                         else
228                                 LVM_VGVOLUMES="$LVM_SUSPENDVG $LVM_ROOTVG"
229                         fi
230
231                         # disable noise from LVM accessing devices that aren't ready.
232                         read printk < /proc/sys/kernel/printk
233                         if [ ! "$DEBUGINITRD" ]; then
234                                 echo 0 > /proc/sys/kernel/printk
235                         fi
236
237                         export LVM_SYSTEM_DIR=/tmp
238
239                         : 'Scanning for Volume Groups'
240                         lvm.static vgscan --mknodes --ignorelockingfailure
241
242                         : 'Activating Volume Groups'
243                         for vol in $LVM_VGVOLUMES; do
244                                 lvm.static vgchange --ignorelockingfailure -a y $vol --noudevsync
245                         done
246
247                         : 'Extra call to make device nodes for non lvm2-initrd (dynamic lvm2)'
248                         lvm.static vgmknodes --ignorelockingfailure
249
250                         echo "$printk" > /proc/sys/kernel/printk
251
252                         # Find out major/minor
253                         attrs="$(lvm.static lvdisplay --ignorelockingfailure -c $ROOTDEV)"
254                         if [ "$attrs" ]; then
255                                 majmin="${attrs#*$ROOTDEV*:*:*:*:*:*:*:*:*:*:*:*}"
256                                 if [ "$majmin" != "$attrs" ]; then
257                                         major="${majmin%:*}"
258                                         minor="${majmin#*:}"
259                                 fi
260                         fi
261
262                         if [ "$major" -a "$minor" ]; then
263                                 # Pass it to kernel
264                                 echo $((256 * $major + $minor)) > /proc/sys/kernel/real-root-dev
265                         fi
266
267                         debugshell
268                         unset LVM_SYSTEM_DIR
269                 EOF
270         fi
271 }
272
273
274 # PRIVATE METHODS
275
276 # find PV names from given VG name
277 # @param        string $vg Volume Group name
278 # @access       private
279 find_lvm_pv() {
280         local vg="$1"
281
282         local pv=$($lvm vgs --noheadings -o pv_name  "$vg")
283         echo $pv
284 }
285
286 # find VG name from given devnode
287 # @param        string $devnode device node to be examined
288 # @access       private
289 find_lvm_vg() {
290         local devnode="$1"
291
292         local vg=$($lvm lvs --noheadings -o vg_name  "$devnode")
293         echo $vg
294 }
This page took 0.10884 seconds and 4 git commands to generate.