From 3107c60113555dad87a6cb6eb99847ba907fd36a Mon Sep 17 00:00:00 2001 From: Jonathan Lebon Date: Wed, 22 Mar 2023 16:37:44 -0400 Subject: [PATCH] 40ignition-ostree: add autosave-xfs transposefs unit Add a new transposefs unit: `autosave-xfs`. This unit runs after `ignition-disks` and `ignition-ostree-growfs,` but before the `restore` transposefs unit. If the XFS root was grown, it checks if the allocation group count (agcount) is within a reasonable amount (128 is chosen here). If it isn't, it saves the rootfs and reformats the filesystem. The `restore` unit will then restore it as usual. In the case of in-place reprovisioning like LUKS (i.e. where the partition table isn't modified by the Ignition config), the rootfs is still saved only once. Ideally, instead of adding a new transposefs unit, we would make it part of the initial `save` unit. But at that point, there's no way to tell whether we should autosave without gazing even more deeply into the Ignition config. We also don't want to unconditionally save the rootfs when we may not need it. Closes: https://github.com/coreos/fedora-coreos-tracker/issues/1183 --- .../ignition-ostree-growfs.sh | 3 +- ...on-ostree-transposefs-autosave-xfs.service | 19 +++++++++ .../ignition-ostree-transposefs.sh | 40 +++++++++++++++++++ .../40ignition-ostree/module-setup.sh | 4 +- 4 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs-autosave-xfs.service diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-growfs.sh b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-growfs.sh index ca3de25224..862cace7d5 100755 --- a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-growfs.sh +++ b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-growfs.sh @@ -147,5 +147,6 @@ case "${ROOTFS_TYPE}" in btrfs) btrfs filesystem resize max ${path} ;; esac -# this is useful for tests +# The ignition-ostree-transposefs-xfsauto.service unit needs to know if we +# actually run. This is also useful for tests. touch /run/ignition-ostree-growfs.stamp diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs-autosave-xfs.service b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs-autosave-xfs.service new file mode 100644 index 0000000000..b914e98c72 --- /dev/null +++ b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs-autosave-xfs.service @@ -0,0 +1,19 @@ +[Unit] +Description=Ignition OSTree: Autosave XFS Rootfs Partition +DefaultDependencies=false +After=ignition-disks.service +# Avoid racing with UUID regeneration +After=ignition-ostree-uuid-root.service +After=ignition-ostree-growfs.service +Before=ignition-ostree-transposefs-restore.service +OnFailure=emergency.target +OnFailureJobMode=isolate + +ConditionKernelCommandLine=ostree +# only run if ignition-ostree-growfs ran since that's when pathological cases occur +ConditionPathExists=/run/ignition-ostree-growfs.stamp + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/libexec/ignition-ostree-transposefs autosave-xfs diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs.sh b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs.sh index a7976e2c63..244a6a5bc2 100755 --- a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs.sh +++ b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/ignition-ostree-transposefs.sh @@ -129,6 +129,29 @@ mount_and_save_filesystem_by_label() { fi } +# This implements https://github.com/coreos/fedora-coreos-tracker/issues/1183. +should_autosave_rootfs() { + local fstype + fstype=$(lsblk -no FSTYPE "${root_part}") + if [ "$fstype" != xfs ]; then + echo "Filesystem is not XFS (found $fstype); skipping" >&2 + echo 0 + return + fi + local agcount + eval $(xfs_info "${root_part}" | grep -o 'agcount=[0-9]*') + # Semi-arbitrarily chosen: this is roughly ~64G currently (based on initial + # ag sizing at build time) which seems like a good rootfs size at which to + # discriminate between "throwaway/short-lived systems" and "long-running + # workload systems". It's not like XFS performance is way worse at 128. + if [ "$agcount" -lt 128 ]; then + echo "Filesystem agcount is $agcount; skipping" >&2 + echo 0 + return + fi + echo 1 +} + ensure_zram_dev() { if test -d "${saved_data}"; then return 0 @@ -221,6 +244,23 @@ case "${1:-}" in mkdir "${saved_prep}" fi ;; + autosave-xfs) + should_autosave=$(should_autosave_rootfs) + if [ "${should_autosave}" = "1" ]; then + wipes_root=1 + ensure_zram_dev + # in the in-place reprovisioning case, the rootfs was already saved + if [ ! -d "${saved_root}" ]; then + mkdir "${saved_root}" + echo "Moving rootfs to RAM..." + mount_and_save_filesystem_by_label root "${saved_root}" + print_zram_mm_stat + fi + mkfs.xfs "${root_part}" -L root -f + # for tests + touch /run/ignition-ostree-autosaved-xfs.stamp + fi + ;; save) # Mounts happen in a private mount namespace since we're not "offically" mounting if [ -d "${saved_root}" ]; then diff --git a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/module-setup.sh b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/module-setup.sh index d0a4c89a9b..f8450b38c0 100755 --- a/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/module-setup.sh +++ b/overlay.d/05core/usr/lib/dracut/modules.d/40ignition-ostree/module-setup.sh @@ -28,6 +28,8 @@ install() { systemd-sysusers \ systemd-tmpfiles \ sort \ + xfs_info \ + xfs_spaceman \ uniq if [[ $(uname -m) = s390x ]]; then @@ -81,7 +83,7 @@ install() { inst_multiple jq chattr inst_script "$moddir/ignition-ostree-transposefs.sh" "/usr/libexec/ignition-ostree-transposefs" - for x in detect save restore; do + for x in detect save autosave-xfs restore; do install_ignition_unit ignition-ostree-transposefs-${x}.service done