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