From 1ed6e614abc1ad56db7faf1b249aa0a40d69114e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Marczykowski-G=C3=B3recki?= Date: Wed, 18 Oct 2017 16:57:39 +0200 Subject: [PATCH] Resize root filesystem at VM startup if needed Check if root device was enlarged while domain was powered off and resize the filesystem in such a case. QubesOS/qubes-issues#3173 QubesOS/qubes-issues#3143 --- debian/qubes-core-agent.install | 2 ++ init/resize-rootfs-if-needed.sh | 26 ++++++++++++++++++++++++++ rpm_spec/core-agent.spec | 2 ++ vm-init.d/qubes-core-early | 5 +++++ vm-systemd/75-qubes-vm.preset | 3 ++- vm-systemd/qubes-rootfs-resize.service | 19 +++++++++++++++++++ 6 files changed, 56 insertions(+), 1 deletion(-) create mode 100755 init/resize-rootfs-if-needed.sh create mode 100644 vm-systemd/qubes-rootfs-resize.service diff --git a/debian/qubes-core-agent.install b/debian/qubes-core-agent.install index 28e3f32..8aaa526 100644 --- a/debian/qubes-core-agent.install +++ b/debian/qubes-core-agent.install @@ -70,6 +70,7 @@ lib/systemd/system/org.cups.cupsd.socket.d/30_qubes.conf lib/systemd/system/qubes-early-vm-config.service lib/systemd/system/qubes-misc-post.service lib/systemd/system/qubes-mount-dirs.service +lib/systemd/system/qubes-rootfs-resize.service lib/systemd/system/qubes-sysinit.service lib/systemd/system/qubes-update-check.service lib/systemd/system/qubes-update-check.timer @@ -110,6 +111,7 @@ usr/lib/qubes/init/mount-dirs.sh usr/lib/qubes/init/qubes-early-vm-config.sh usr/lib/qubes/init/qubes-random-seed.sh usr/lib/qubes/init/qubes-sysinit.sh +usr/lib/qubes/init/resize-rootfs-if-needed.sh usr/lib/qubes/init/setup-rw.sh usr/lib/qubes/init/setup-rwdev.sh usr/lib/qubes/prepare-suspend diff --git a/init/resize-rootfs-if-needed.sh b/init/resize-rootfs-if-needed.sh new file mode 100755 index 0000000..1c01bb1 --- /dev/null +++ b/init/resize-rootfs-if-needed.sh @@ -0,0 +1,26 @@ +#!/bin/sh + +# Possibly resize root device (partition, filesystem), if underlying device was +# enlarged. + +set -e + +# if underlying root device is read-only, don't do anything +if [ "$(blockdev --getro /dev/xvda)" -eq "1" ]; then + echo "xvda is read-only, not resizing" >&2 + exit 0 +fi + +sysfs_root_dev="/sys/dev/block/$(mountpoint -d /)" +sysfs_xvda="/sys/class/block/xvda" + +# if root filesystem use already (almost) the whole dis +non_rootfs_data=$(( 250 * 1024 * 2 )) +if [ "$(cat "$sysfs_xvda/size")" -lt \ + $(( non_rootfs_data + $(cat "$sysfs_root_dev/size") )) ]; then + echo "root filesystem already at the right size" >&2 + exit 0 +fi + +# resize needed, do it +/usr/lib/qubes/resize-rootfs diff --git a/rpm_spec/core-agent.spec b/rpm_spec/core-agent.spec index 6e47467..76251e2 100644 --- a/rpm_spec/core-agent.spec +++ b/rpm_spec/core-agent.spec @@ -617,6 +617,7 @@ rm -f %{name}-%{version} /usr/lib/qubes/init/qubes-early-vm-config.sh /usr/lib/qubes/init/qubes-random-seed.sh /usr/lib/qubes/init/qubes-sysinit.sh +/usr/lib/qubes/init/resize-rootfs-if-needed.sh /usr/lib/qubes/init/setup-rw.sh /usr/lib/qubes/init/setup-rwdev.sh /usr/lib/qubes/init/functions @@ -804,6 +805,7 @@ The Qubes core startup configuration for SystemD init. %defattr(-,root,root,-) /lib/systemd/system/qubes-misc-post.service /lib/systemd/system/qubes-mount-dirs.service +/lib/systemd/system/qubes-rootfs-resize.service /lib/systemd/system/qubes-sysinit.service /lib/systemd/system/qubes-early-vm-config.service /lib/systemd/system/qubes-update-check.service diff --git a/vm-init.d/qubes-core-early b/vm-init.d/qubes-core-early index 6ae5d49..a54bf90 100755 --- a/vm-init.d/qubes-core-early +++ b/vm-init.d/qubes-core-early @@ -15,6 +15,11 @@ start() { have_qubesdb || return + echo -n $"Adjusting root filesystem size:" + # shellcheck disable=SC2015 + /usr/lib/qubes/init/resize-rootfs-if-needed.sh && success || failure + echo + echo -n $"Setting up Qubes persistent file systems:" # shellcheck disable=SC2015 /usr/lib/qubes/init/mount-dirs.sh && success || failure diff --git a/vm-systemd/75-qubes-vm.preset b/vm-systemd/75-qubes-vm.preset index f70313c..bbd9a2e 100644 --- a/vm-systemd/75-qubes-vm.preset +++ b/vm-systemd/75-qubes-vm.preset @@ -85,6 +85,7 @@ enable qubes-updates-proxy.service enable qubes-network.service enable qubes-qrexec-agent.service enable qubes-mount-dirs.service +enable qubes-rootfs-resize.service enable qubes-firewall.service enable qubes-meminfo-writer.service enable qubes-iptables.service @@ -94,4 +95,4 @@ enable chronyd.service enable xendriverdomain.service enable systemd-timesyncd.service enable qubes-sync-time.service -enable qubes-sync-time.timer \ No newline at end of file +enable qubes-sync-time.timer diff --git a/vm-systemd/qubes-rootfs-resize.service b/vm-systemd/qubes-rootfs-resize.service new file mode 100644 index 0000000..10ff386 --- /dev/null +++ b/vm-systemd/qubes-rootfs-resize.service @@ -0,0 +1,19 @@ +[Unit] +Description=Adjust root filesystem size +# There is a dependency on dev-xvdb.device because +# mount-dirs.sh calls setup-rwdev.sh which +# must happen only when /dev/xvdb has appeared. +After=qubes-sysinit.service dev-xvda.device +DefaultDependencies=no +Before=local-fs.target + +[Service] +Type=oneshot +RemainAfterExit=yes +ExecStart=/usr/lib/qubes/init/resize-rootfs-if-needed.sh +# There is no need for an ExecStop because systemd +# cleans up mount units in the right order, killing +# processes as needed. + +[Install] +WantedBy=multi-user.target