Amend Dracut module to export ZFS root on shutdown
Make use of Dracut's ability to restore the initramfs on shutdown and pivot to it, allowing for a clean unmount and export of the ZFS root. No need to force-import on every reboot anymore. Signed-off-by: Lukas Wunner <lukas@wunner.de> Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Issue #2195 Issue #2476 Issue #2498 Issue #2556 Issue #2563 Issue #2575 Issue #2600 Issue #2755 Issue #2766
This commit is contained in:
parent
8ac9b5e6b5
commit
07a3312f17
|
@ -1,3 +1,4 @@
|
||||||
|
export-zfs.sh
|
||||||
module-setup.sh
|
module-setup.sh
|
||||||
mount-zfs.sh
|
mount-zfs.sh
|
||||||
parse-zfs.sh
|
parse-zfs.sh
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
pkgdracutdir = $(dracutdir)/modules.d/90zfs
|
pkgdracutdir = $(dracutdir)/modules.d/90zfs
|
||||||
pkgdracut_SCRIPTS = \
|
pkgdracut_SCRIPTS = \
|
||||||
|
$(top_srcdir)/dracut/90zfs/export-zfs.sh \
|
||||||
$(top_srcdir)/dracut/90zfs/module-setup.sh \
|
$(top_srcdir)/dracut/90zfs/module-setup.sh \
|
||||||
$(top_srcdir)/dracut/90zfs/mount-zfs.sh \
|
$(top_srcdir)/dracut/90zfs/mount-zfs.sh \
|
||||||
$(top_srcdir)/dracut/90zfs/parse-zfs.sh
|
$(top_srcdir)/dracut/90zfs/parse-zfs.sh
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
|
$(top_srcdir)/dracut/90zfs/export-zfs.sh.in \
|
||||||
$(top_srcdir)/dracut/90zfs/module-setup.sh.in \
|
$(top_srcdir)/dracut/90zfs/module-setup.sh.in \
|
||||||
$(top_srcdir)/dracut/90zfs/mount-zfs.sh.in \
|
$(top_srcdir)/dracut/90zfs/mount-zfs.sh.in \
|
||||||
$(top_srcdir)/dracut/90zfs/parse-zfs.sh.in
|
$(top_srcdir)/dracut/90zfs/parse-zfs.sh.in
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
_do_zpool_export() {
|
||||||
|
local ret=0
|
||||||
|
local final=$1
|
||||||
|
local force
|
||||||
|
|
||||||
|
if [ "x$final" != "x" ]; then
|
||||||
|
force="-f"
|
||||||
|
fi
|
||||||
|
|
||||||
|
info "Exporting ZFS storage pools"
|
||||||
|
zpool list -H | while read fs rest ; do
|
||||||
|
zpool export $force "$fs" || ret=$?
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "x$final" != "x" ]; then
|
||||||
|
info "zpool list"
|
||||||
|
zpool list 2>&1 | vinfo
|
||||||
|
fi
|
||||||
|
|
||||||
|
return $ret
|
||||||
|
}
|
||||||
|
|
||||||
|
if command -v zpool >/dev/null; then
|
||||||
|
_do_zpool_export $1
|
||||||
|
else
|
||||||
|
:
|
||||||
|
fi
|
|
@ -39,6 +39,7 @@ install() {
|
||||||
dracut_install hostid
|
dracut_install hostid
|
||||||
inst_hook cmdline 95 "$moddir/parse-zfs.sh"
|
inst_hook cmdline 95 "$moddir/parse-zfs.sh"
|
||||||
inst_hook mount 98 "$moddir/mount-zfs.sh"
|
inst_hook mount 98 "$moddir/mount-zfs.sh"
|
||||||
|
inst_hook shutdown 30 "$moddir/export-zfs.sh"
|
||||||
|
|
||||||
if [ -e @sysconfdir@/zfs/zpool.cache ]; then
|
if [ -e @sysconfdir@/zfs/zpool.cache ]; then
|
||||||
inst @sysconfdir@/zfs/zpool.cache
|
inst @sysconfdir@/zfs/zpool.cache
|
||||||
|
|
|
@ -67,5 +67,7 @@ case "$root" in
|
||||||
else
|
else
|
||||||
mount -o zfsutil -t zfs "$zfsbootfs" "$NEWROOT" && ROOTFS_MOUNTED=yes
|
mount -o zfsutil -t zfs "$zfsbootfs" "$NEWROOT" && ROOTFS_MOUNTED=yes
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
need_shutdown
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
|
@ -77,6 +77,9 @@ command line and determine if ZFS is the active root filesystem.
|
||||||
* `mount-zfs.sh`: Run later in initramfs boot process after udev has settled
|
* `mount-zfs.sh`: Run later in initramfs boot process after udev has settled
|
||||||
to mount the root dataset.
|
to mount the root dataset.
|
||||||
|
|
||||||
|
* `export-zfs.sh`: Run on shutdown after dracut has restored the initramfs
|
||||||
|
and pivoted to it, allowing for a clean unmount and export of the ZFS root.
|
||||||
|
|
||||||
`module-setup.sh`
|
`module-setup.sh`
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
@ -164,3 +167,25 @@ import can lead to serious data corruption and loss of pools, so this option
|
||||||
should be used with extreme caution. Note that even with this flag set, if
|
should be used with extreme caution. Note that even with this flag set, if
|
||||||
the required zpool was auto-imported by the kernel module, no additional
|
the required zpool was auto-imported by the kernel module, no additional
|
||||||
`zpool import` commands are run, so nothing is forced.
|
`zpool import` commands are run, so nothing is forced.
|
||||||
|
|
||||||
|
`export-zfs.sh`
|
||||||
|
-------------
|
||||||
|
|
||||||
|
Normally the zpool containing the root dataset cannot be exported on
|
||||||
|
shutdown as it is still in use by the init process. To work around this,
|
||||||
|
Dracut is able to restore the initramfs on shutdown and pivot to it.
|
||||||
|
All remaining process are then running from a ramdisk, allowing for a
|
||||||
|
clean unmount and export of the ZFS root. The theory of operation is
|
||||||
|
described in detail in the [Dracut manual](https://www.kernel.org/pub/linux/utils/boot/dracut/dracut.html#_dracut_on_shutdown).
|
||||||
|
|
||||||
|
This script will try to export all remaining zpools after Dracut has
|
||||||
|
pivoted to the initramfs. If an initial regular export is not successful,
|
||||||
|
Dracut will call this script once more with the `final` option,
|
||||||
|
in which case a forceful export is attempted.
|
||||||
|
|
||||||
|
Other Dracut modules include similar shutdown scripts and Dracut
|
||||||
|
invokes these scripts round-robin until they succeed. In particular,
|
||||||
|
the `90dm` module installs a script which tries to close and remove
|
||||||
|
all device mapper targets. Thus, if there are ZVOLs containing
|
||||||
|
dm-crypt volumes or if the zpool itself is backed by a dm-crypt
|
||||||
|
volume, the shutdown scripts will try to untangle this.
|
||||||
|
|
Loading…
Reference in New Issue