mirror of
https://github.com/KDE/kde-linux.git
synced 2026-05-19 05:48:58 -04:00
bring back btrfs-shrink
the bash impl is substantially slower and because of -x also too verbose
This commit is contained in:
55
btrfs-shrink-and-umount.py
Executable file
55
btrfs-shrink-and-umount.py
Executable file
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
|
||||
# SPDX-FileCopyrightText: 2024 Harald Sitter <sitter@kde.org>
|
||||
|
||||
# Shrink btrfs. It's a bit awkward because we don't really have a reliable way
|
||||
# to calculate how much space we actually need. So we first chop off a dynamic
|
||||
# portion but leave a bit of a buffer behind. Then we keep resizing until the
|
||||
# resize starts failing.
|
||||
|
||||
import json
|
||||
import os
|
||||
import math
|
||||
import subprocess
|
||||
from subprocess import check_output
|
||||
|
||||
os.chdir('root.raw.mnt')
|
||||
|
||||
drive_size = check_output(['findmnt', '--bytes', '--noheadings', '--output', 'size', '.']).strip()
|
||||
drive_size = int(drive_size)
|
||||
|
||||
out = check_output(["btrfs", "--format", "json", "filesystem", "df", "."])
|
||||
data = json.loads(out)
|
||||
df = data["filesystem-df"]
|
||||
|
||||
size = 0
|
||||
for block_group in df:
|
||||
size += block_group["total"]
|
||||
|
||||
# Give 50% buffer space. We'll shrink from there in smaller steps. Make sure to not blow past the partition size.
|
||||
size = min(drive_size, math.ceil(size * 1.5))
|
||||
original_size = size
|
||||
|
||||
subprocess.check_call(["btrfs", "filesystem", "resize", str(size), "."])
|
||||
|
||||
# With compression one extent is always 128KiB as per btrfs documentation.
|
||||
# extent_size = 128 * 1024
|
||||
# For now we use 32MiB as the extent size so as to not slow down the build too much though.
|
||||
extent_size = 32 * 1024 * 1024
|
||||
while True:
|
||||
try:
|
||||
subprocess.check_call(["btrfs", "filesystem", "resize", f"-{extent_size}", "."], stdout=subprocess.DEVNULL, stdin=subprocess.DEVNULL)
|
||||
subprocess.check_call(["btrfs", "filesystem", "sync", "."])
|
||||
size -= extent_size
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(e)
|
||||
break
|
||||
|
||||
# Next we truncate the actual partition file by the according amount. For practical reasons this happens here so we don't
|
||||
# have to pass the sizes around between different programs.
|
||||
os.chdir('..')
|
||||
subprocess.check_call(['umount', 'root.raw.mnt'])
|
||||
subprocess.check_call(['truncate', f'--size=-{original_size - size}', 'root.raw'])
|
||||
|
||||
|
||||
27
build.sh
27
build.sh
@@ -171,30 +171,9 @@ btrfs filesystem sync .
|
||||
btrfs balance start --full-balance --enqueue .
|
||||
btrfs filesystem sync .
|
||||
|
||||
# How much we'll keep shrinking the filesystem by, in bytes.
|
||||
# Too large = too imprecise, too small = shrink is too slow.
|
||||
# One mebibyte seems good for now.
|
||||
SHRINK_AMOUNT=1048576
|
||||
|
||||
# Repeatedly shrink the filesystem by $SHRINK_AMOUNT until we get an error.
|
||||
# Store the size it has been successfully shrunk by in $SHRINK_SIZE.
|
||||
SHRINK_SIZE=0
|
||||
while true; do
|
||||
btrfs filesystem resize -$SHRINK_AMOUNT . || break
|
||||
SHRINK_SIZE=$((SHRINK_SIZE + SHRINK_AMOUNT))
|
||||
btrfs filesystem sync .
|
||||
done
|
||||
|
||||
# Back out to kde-linux.cache, then unmount root.raw.mnt.
|
||||
cd ..
|
||||
umount root.raw.mnt
|
||||
|
||||
# We shrunk the filesystem, but root.raw as a file itself is still 8G.
|
||||
# Let's safely truncate it by the previously stored $SHRINK_SIZE.
|
||||
truncate --size=-$SHRINK_SIZE root.raw
|
||||
|
||||
# We're done, back out of kde-linux.cache into the root.
|
||||
cd ..
|
||||
cd .. # up to kde-linux.cache
|
||||
../btrfs-shrink-and-umount.py
|
||||
cd .. # and back to root
|
||||
|
||||
# Create rootfs tarball for consumption by systemd-sysext (doesn't currently support consuming raw images :()
|
||||
rm -rf "$ROOTFS_TAR" ./*.tar
|
||||
|
||||
Reference in New Issue
Block a user