From 593724c05b62b284dae27be853e082158f3069ce Mon Sep 17 00:00:00 2001 From: AJ Jordan Date: Thu, 7 Feb 2019 14:05:34 -0500 Subject: [PATCH] Use dumpe2fs for filesystem size calculations The previous approach used `df` to get usable space and then added a fixed size to that number in order to account for filesystem overhead. However, at some point that stopped working for me. It appears that ext4 filesystem overhead can vary over time or because of other factors. (Certainly now that I think about it the old code would only work well for people with the exact same filesystem size as me.) So the new approach is to just completely ignore what `df` tells us and instead go directly to the source: the filesystem's internal notion of exactly how much space it takes up. We use `dumpe2fs` to retrieve this information and calculate the on-disk size dynamically from that. Then we add the space that boot data takes up (unchanged), and we add 5MB padding because when I tested this it didn't quite add up otherwise. https://unix.stackexchange.com/a/13551/29146 suggests that this unaccounted-for data may be e.g. additional copies of the superblock. --- init/resize-rootfs-if-needed.sh | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/init/resize-rootfs-if-needed.sh b/init/resize-rootfs-if-needed.sh index b2cef18..1bd5220 100755 --- a/init/resize-rootfs-if-needed.sh +++ b/init/resize-rootfs-if-needed.sh @@ -14,12 +14,20 @@ fi sysfs_xvda="/sys/class/block/xvda" # if root filesystem is already using (almost) the whole disk -# 203M for BIOS and /boot data, 222 for ext4 filesystem overhead -# See QubesOS/qubes-core-agent-linux#146 for more details -size_margin=$(((222 + 203) * 2 * 1024)) -rootfs_size=$(df --block-size=512 --output=size / | tail -n 1 | tr -d ' ') +# 203M for BIOS and /boot data +boot_data_size=$((203 * 2 * 1024)) +# rootfs size is calculated on-the-fly. `df` doesn't work because it doesn't +# include fs overhead, and calculating a static size for overhead doesn't work +# because that can change dynamically over the filesystem's lifetime. +# See QubesOS/qubes-core-agent-linux#146 and QubesOS/qubes-core-agent-linux#152 +# for more details +ext4_block_count=$(dumpe2fs /dev/mapper/dmroot | grep '^Block count:' | sed -E 's/Block count:[[:space:]]+//') +ext4_block_size=$(dumpe2fs /dev/mapper/dmroot | grep '^Block size:' | sed -E 's/Block size:[[:space:]]+//') +rootfs_size=$((ext4_block_count * ext4_block_size / 512)) +# 5 MB in 512-byte units for some random extra bits +size_margin=$((5 * 1024 * 2)) if [ "$(cat $sysfs_xvda/size)" -lt \ - $(( size_margin + rootfs_size )) ]; then + $(( rootfs_size + boot_data_size + size_margin )) ]; then echo "root filesystem already at $rootfs_size blocks" >&2 exit 0 fi