diff options
author | gregory-lee-bartholomew <[email protected]> | 2020-05-29 23:16:08 -0500 |
---|---|---|
committer | GitHub <[email protected]> | 2020-05-29 21:16:08 -0700 |
commit | 9052e3d70bacdbcc51cbef8b7f0566b49d2f736b (patch) | |
tree | 3d53dfe8c1457baacb17d340d11446936f3586ea /contrib/dracut | |
parent | 3d93161b0112b0baa4f5483d03105bd77605ff8d (diff) |
Add bootfs.snapshot and bootfs.rollback kernel parameters
Unlike other filesystems, snapshots and rollbacks of bootfs need to be
done from a rescue environment. This patch makes it possible to snap-
shot or rollback the bootfs simply by specifying bootfs.snapshot or
bootfs.rollback on the kernel command line. The operation will be
performed by dracut just before bootfs is mounted.
Reviewed-by: Antonio Russo <[email protected]>
Reviewed-by: Brian Behlendorf <[email protected]>
Signed-off-by: Gregory Bartholomew <[email protected]>
Closes #10198
Diffstat (limited to 'contrib/dracut')
-rw-r--r-- | contrib/dracut/90zfs/.gitignore | 2 | ||||
-rw-r--r-- | contrib/dracut/90zfs/Makefile.am | 8 | ||||
-rwxr-xr-x | contrib/dracut/90zfs/module-setup.sh.in | 6 | ||||
-rw-r--r-- | contrib/dracut/90zfs/zfs-rollback-bootfs.service.in | 14 | ||||
-rw-r--r-- | contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in | 14 | ||||
-rw-r--r-- | contrib/dracut/README.dracut.markdown | 24 |
6 files changed, 66 insertions, 2 deletions
diff --git a/contrib/dracut/90zfs/.gitignore b/contrib/dracut/90zfs/.gitignore index 85c23f75e..dce243934 100644 --- a/contrib/dracut/90zfs/.gitignore +++ b/contrib/dracut/90zfs/.gitignore @@ -7,3 +7,5 @@ zfs-lib.sh zfs-load-key.sh zfs-needshutdown.sh zfs-env-bootfs.service +zfs-snapshot-bootfs.service +zfs-rollback-bootfs.service diff --git a/contrib/dracut/90zfs/Makefile.am b/contrib/dracut/90zfs/Makefile.am index 1680230fa..08667a134 100644 --- a/contrib/dracut/90zfs/Makefile.am +++ b/contrib/dracut/90zfs/Makefile.am @@ -10,7 +10,9 @@ pkgdracut_SCRIPTS = \ zfs-lib.sh pkgdracut_DATA = \ - zfs-env-bootfs.service + zfs-env-bootfs.service \ + zfs-snapshot-bootfs.service \ + zfs-rollback-bootfs.service EXTRA_DIST = \ $(top_srcdir)/contrib/dracut/90zfs/export-zfs.sh.in \ @@ -21,7 +23,9 @@ EXTRA_DIST = \ $(top_srcdir)/contrib/dracut/90zfs/zfs-load-key.sh.in \ $(top_srcdir)/contrib/dracut/90zfs/zfs-needshutdown.sh.in \ $(top_srcdir)/contrib/dracut/90zfs/zfs-lib.sh.in \ - $(top_srcdir)/contrib/dracut/90zfs/zfs-env-bootfs.service.in + $(top_srcdir)/contrib/dracut/90zfs/zfs-env-bootfs.service.in \ + $(top_srcdir)/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in \ + $(top_srcdir)/contrib/dracut/90zfs/zfs-rollback-bootfs.service.in $(pkgdracut_SCRIPTS) $(pkgdracut_DATA) :%:%.in -$(SED) -e 's,@bindir\@,$(bindir),g' \ diff --git a/contrib/dracut/90zfs/module-setup.sh.in b/contrib/dracut/90zfs/module-setup.sh.in index e94f9f2dc..7e7a96d6e 100755 --- a/contrib/dracut/90zfs/module-setup.sh.in +++ b/contrib/dracut/90zfs/module-setup.sh.in @@ -109,5 +109,11 @@ install() { ln -s ../zfs-import.target "${initdir}/$systemdsystemunitdir/initrd.target.wants"/zfs-import.target type mark_hostonly >/dev/null 2>&1 && mark_hostonly @systemdunitdir@/zfs-import.target fi + for _service in zfs-snapshot-bootfs.service zfs-rollback-bootfs.service ; do + inst "${moddir}"/$_service "${systemdsystemunitdir}"/$_service + if ! [ -L "${initdir}/$systemdsystemunitdir/initrd.target.wants"/$_service ]; then + ln -s ../$_service "${initdir}/$systemdsystemunitdir/initrd.target.wants"/$_service + fi + done fi } diff --git a/contrib/dracut/90zfs/zfs-rollback-bootfs.service.in b/contrib/dracut/90zfs/zfs-rollback-bootfs.service.in new file mode 100644 index 000000000..4b058c1b8 --- /dev/null +++ b/contrib/dracut/90zfs/zfs-rollback-bootfs.service.in @@ -0,0 +1,14 @@ +[Unit] +Description=Rollback bootfs just before it is mounted +Requisite=zfs-import.target +After=zfs-import.target zfs-snapshot-bootfs.service +Before=dracut-mount.service +DefaultDependencies=no +ConditionKernelCommandLine=bootfs.rollback + +[Service] +# ${BOOTFS} should have been set by zfs-env-bootfs.service +Type=oneshot +ExecStartPre=/bin/sh -c 'test -n "${BOOTFS}"' +ExecStart=/bin/sh -c '. /lib/dracut-lib.sh; SNAPNAME="$(getarg bootfs.rollback)"; /sbin/zfs rollback -Rf "${BOOTFS}@${SNAPNAME:-%v}"' +RemainAfterExit=yes diff --git a/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in b/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in new file mode 100644 index 000000000..cfd5f7029 --- /dev/null +++ b/contrib/dracut/90zfs/zfs-snapshot-bootfs.service.in @@ -0,0 +1,14 @@ +[Unit] +Description=Snapshot bootfs just before it is mounted +Requisite=zfs-import.target +After=zfs-import.target +Before=dracut-mount.service +DefaultDependencies=no +ConditionKernelCommandLine=bootfs.snapshot + +[Service] +# ${BOOTFS} should have been set by zfs-env-bootfs.service +Type=oneshot +ExecStartPre=/bin/sh -c 'test -n "${BOOTFS}"' +ExecStart=-/bin/sh -c '. /lib/dracut-lib.sh; SNAPNAME="$(getarg bootfs.snapshot)"; /sbin/zfs snapshot "${BOOTFS}@${SNAPNAME:-%v}"' +RemainAfterExit=yes diff --git a/contrib/dracut/README.dracut.markdown b/contrib/dracut/README.dracut.markdown index b5fb288a1..f31543c3c 100644 --- a/contrib/dracut/README.dracut.markdown +++ b/contrib/dracut/README.dracut.markdown @@ -59,6 +59,30 @@ to recover from this, you may use the `zfs_force` option or boot from a different filesystem and `zpool import -f` then `zpool export` the pool before rebooting with the new hostid. +* `bootfs.snapshot`: If listed, enables the zfs-snapshot-bootfs service on a Dracut system. The zfs-snapshot-bootfs service simply runs `zfs snapshot $BOOTFS@%v` after the pool has been imported but before the bootfs is mounted. `$BOOTFS` is substituted with the value of the bootfs setting on the pool. `%v` is substituted with the version string of the kernel currently being booted (e.g. 5.6.6-200.fc31.x86\_64). Failure to create the snapshot (e.g. because one with the same name already exists) will be logged, but will not otherwise interrupt the boot process. + + It is safe to leave the bootfs.snapshot flag set persistently on your kernel command line so that a new snapshot of your bootfs will be created on every kernel update. If you leave bootfs.snapshot set persistently on your kernel command line, you may find the below script helpful for automatically removing old snapshots of the bootfs along with their associated kernel. + + #!/usr/bin/sh + + if [[ "$1" == "remove" ]] && grep -q "\bbootfs.snapshot\b" /proc/cmdline; then + zfs destroy $(findmnt -n -o source /)@$2 &> /dev/null + fi + + exit 0 + + To use the above script place it in a plain text file named /etc/kernel/install.d/99-zfs-cleanup.install and mark it executable with the following command: + + $ chmod +x /etc/kernel/install.d/99-zfs-cleanup.install + + On Red Hat based systems, you can change the value of `installonly_limit` in /etc/dnf/dnf.conf to adjust the number of kernels and their associated snapshots that are kept. + +* `bootfs.snapshot=<snapname>`: Is identical to the bootfs.snapshot parameter explained above except that the value substituted for \<snapname\> will be used when creating the snapshot instead of the version string of the kernel currently being booted. + +* `bootfs.rollback`: If listed, enables the zfs-rollback-bootfs service on a Dracut system. The zfs-rollback-bootfs service simply runs `zfs rollback -Rf $BOOTFS@%v` after the pool has been imported but before the bootfs is mounted. If the rollback operation fails, the boot process will be interrupted with a Dracut rescue shell. __Use this parameter with caution. Intermediate snapshots of the bootfs will be destroyed!__ TIP: Keep your user data (e.g. /home) on separate file systems (it can be in the same pool though). + +* `bootfs.rollback=<snapname>`: Is identical to the bootfs.rollback parameter explained above except that the value substituted for \<snapname\> will be used when rolling back the bootfs instead of the version string of the kernel currently being booted. If you use this form, choose a snapshot that is new enough to contain the needed kernel modules under /lib/modules or use a kernel that has all the needed modules built-in. + How it Works ============ |