mirror of
https://github.com/morgan9e/systemd
synced 2026-04-14 00:14:32 +09:00
repart: Correctly handle btrfs compression (#39597)
systemd-repart is incorrectly choosing the loop-mount code path to copy files after formatting, instead of using the --rootdir path, which is required by mkfs.btrfs to apply compression (since it's on files, not the fs). So two fixes (and an integ test): 1. If Btrfs compression is requested without a root directory (e.g., Compression= without CopyFiles=), we now log a warning and skip the --compress flag. This prevents the mkfs.btrfs failure, and it's meaningless anyway without any files. 2. The logic in repart now uses the --rootdir code path whenever the partition is btrfs and compression is requested. Otherwise it still won't work even in the legitimate case because use the loop mounting code, which is too late to use --compress. Fixes: https://github.com/systemd/systemd/issues/39584
This commit is contained in:
@@ -1685,6 +1685,76 @@ EOF
|
||||
grep -q 'UUID=[0-9a-f-]* /home btrfs discard,rw,nodev,suid,exec,subvol=@home,zstd:1,noatime,lazytime 0 1' "$root"/etc/fstab
|
||||
}
|
||||
|
||||
testcase_btrfs_compression() {
|
||||
local defs imgs loop output
|
||||
|
||||
if ! systemd-analyze compare-versions "$(btrfs --version | head -n 1 | awk '{ print $2 }')" ge v6.13; then
|
||||
echo "btrfs-progs is not installed or older than v6.13, skipping test."
|
||||
return 0
|
||||
fi
|
||||
|
||||
defs="$(mktemp -d)"
|
||||
imgs="$(mktemp -d)"
|
||||
# shellcheck disable=SC2064
|
||||
trap "rm -rf '$defs' '$imgs'" RETURN
|
||||
chmod 0755 "$defs"
|
||||
|
||||
echo "*** testcase for btrfs compression with CopyFiles (OFFLINE=$OFFLINE) ***"
|
||||
|
||||
# Must not be in tmpfs due to exclusions. It also must be large and
|
||||
# compressible so that the compression check succeeds later.
|
||||
src=/etc/test-source-file
|
||||
dd if=/dev/zero of="$src" bs=1M count=1 2>/dev/null
|
||||
|
||||
tee "$defs/btrfs-compressed.conf" <<EOF
|
||||
[Partition]
|
||||
Type=linux-generic
|
||||
Format=btrfs
|
||||
Compression=zstd
|
||||
CopyFiles=$src:/test-file
|
||||
SizeMinBytes=100M
|
||||
SizeMaxBytes=100M
|
||||
EOF
|
||||
|
||||
systemd-repart --offline="$OFFLINE" \
|
||||
--definitions="$defs" \
|
||||
--empty=create \
|
||||
--size=auto \
|
||||
--dry-run=no \
|
||||
--seed="$seed" \
|
||||
"$imgs/btrfs-compressed.img" 2>&1 | tee "$imgs/repart-output.txt"
|
||||
rm "$src"
|
||||
|
||||
output=$(cat "$imgs/repart-output.txt")
|
||||
|
||||
assert_in "Rootdir from:" "$output"
|
||||
assert_in "Compress:" "$output"
|
||||
|
||||
if [[ "$OFFLINE" == "yes" ]] || systemd-detect-virt --quiet --container; then
|
||||
echo "Skipping mount verification (requires loop devices)"
|
||||
return 0
|
||||
fi
|
||||
loop="$(losetup -P --show --find "$imgs/btrfs-compressed.img")"
|
||||
# shellcheck disable=SC2064
|
||||
trap "umount '$imgs/mount' 2>/dev/null || true; losetup -d '$loop' 2>/dev/null || true; rm -rf '$defs' '$imgs'" RETURN
|
||||
echo "Loop device: $loop"
|
||||
udevadm wait --timeout=60 --settle "${loop:?}p1"
|
||||
|
||||
mkdir -p "$imgs/mount"
|
||||
mount -t btrfs "${loop:?}p1" "$imgs/mount"
|
||||
|
||||
[[ -f "$imgs/mount/test-file" ]]
|
||||
[[ "$(stat -c%s "$imgs/mount/test-file")" == "1048576" ]]
|
||||
|
||||
if command -v compsize &>/dev/null; then
|
||||
output=$(compsize "$imgs/mount/test-file" 2>&1)
|
||||
assert_in "zstd" "$output"
|
||||
fi
|
||||
|
||||
umount "$imgs/mount"
|
||||
losetup -d "$loop"
|
||||
}
|
||||
|
||||
testcase_varlink_list_devices() {
|
||||
REPART="$(which systemd-repart)"
|
||||
varlinkctl introspect "$REPART"
|
||||
|
||||
Reference in New Issue
Block a user