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