The issue
I’m a Gentoo use since a long time now and one of the biggest constrain I see while using this distribution is the long upgrade time.
Here I want to say that the issue is not the time by itself but the time under which the running OS is in a possibly instable state. The major issue being that while we are building the packages there is for some moments issues while the next packages have not yet been built and installed.
The major issue being when we are under the non stables versions for which we can be stucked in the middle of the upgrade with needs to search solutions with a system which will possibly not boot again if we reboot before fixing them.
The snapshot approach
With the BTRFS I see a possible improvement by using the snapshot feature not killing my system before getting all the packages built and installed.
The idea
The idea is basically to perform the update following the given steps :
- Perform
emerge --syncto get the new package tree. - Make a snapthot in read/write mode for the / filesystem.
- Chroot in the new snashot directory
- Build the new packages and generate the related binary packages.
- Once done, install the binary packages in the running system.
The good point in theses steps is that we can stop, pause any time in the build process without having a broken running system.
Scripts
I detail in the following the content of the operations to perform.
But I provide here a set of script in an archive doing everything and to extract in your / (or anywhere else but with some fixes to apply in paths).
2024-05-17-gentoo-btrfs-slash-scripts.tar.bz2
It contains:
- ./backup/create_build_dir.sh
- ./backup/create_snapshot.sh
- ./backup/delete_snapshot.sh
- mount.sh
- umount.sh
- chroot.sh
- update.sh
It currently store all the common files in /home/gentoo.
To be done once
In order to each the chrooting I prepare some scripts in my / directory. It also help in case of boot issues if I need to make some fixes from a libusb in last ressort.
So I create two scripts in / :
- A script to mount the gentoo sub filesystems (mount.sh)
- Chroot in (chroot.sh)
Script mount.sh :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/bin/bash
# Note : to be placed in "/mount.sh"
set -e
set -u
set -x
#dir=/mnt/gentoo
dir=${PWD}
if [[ ${dir} == "/" ]]; then
echo "Invalid working dir : $dir !" 1>&2
exit 1
fi
# common OS paths
mount --types proc /proc $dir/proc
mount --rbind /sys $dir/sys
mount --make-rslave $dir/sys
mount --rbind /dev $dir/dev
mount --make-rslave $dir/dev
mount --bind /run $dir/run
mount --make-slave $dir/run
# to put the binpkg at the right place
binpkg=/var/cache/binpkgs
mount --bind $binpkg $dir/$binpkg
mount --make-slave $dir/$binpkg
# to put the sources at the right place
distdir=/var/cache/distfiles
mount --bind $distdir $dir/$distdir
mount --make-slave $dir/$distdir
# If use a tmpfir elsewhere
#mount -U 583574f3-2a25-46c8-ba2a-d82e04a11cf6 $dir/var/tmp/portage/
Script chroot.sh :
1
2
#!/bin/bash
chroot $dir /bin/bash
Practical steps
Sync
First we need to sync the packages:
1
emerge --sync
Snapshot
Then we can snashot usnig btrfs :
1
2
3
4
5
6
7
8
9
10
11
12
# create /backup dir
mkdir -p /backup
cd /backup
# create a readonly backup in case
btrfs subvolume snapshot -r / /backup/snapshot-$(date "+%Y_%m_%d")
# create the read/write one
btrfs subvolume snapshot / /backup/build-$(date "+%Y_%m_%d")
# create a symlink on last
ln -s -f build-$(date "+%Y_%m_%d") build-current
Scripts to snapthots
In practice I made myself some helper script to ease the procedure which I store in /backup dir :
Script /backup/create_build_dir.sh
1
2
3
4
5
6
7
8
9
10
11
12
#!/bin/bash
set -e
set -x
#./create_snapshot.sh
dirname=build-$(date "+%Y_%m_%d")
btrfs subvolume snapshot / /backup/${dirname}
ln -s -f ${dirname} build-current
Script /backup/create_snapshot.sh
1
2
3
4
5
6
#!/bin/bash
set -e
set -x
btrfs subvolume snapshot -r / /backup/snapshot-$(date "+%Y_%m_%d")
Script /backup/delete_snapshot.sh
1
2
3
4
5
6
7
#!/bin/bash
set -e
set -u
set -x
btrfs subvolume delete $1
Chroot
Now we can chroot in this new root dir:
1
2
3
4
5
6
7
8
9
# jump in
cd /backup/build-current
# mount sub filesystems
./mount.sh
# chroot in
./chroot.sh
Build
Now we can build all the update taking care to build the binary packaging in
the mean time (you can also use quickpkg afterward in case):
1
2
# perform the update
emerge --update --newuse --deep --with-bdeps=y --buildpkg @world -a
You can now quit the chroot to come back to the running Gentoo :
1
2
# exit chroot
exit
Install in running system
Now just perform the update in you running system forcing the use of binary
packages thankgs to the emerge -K/--usepkgonly option :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# perform update from binary packages only (-K)
emerge --update --newuse --deep --with-bdeps=y --usepkgonly @world
# rebuild modules
emerge -a -1 gentoo-kernel @module-rebuild
# eventually look to update grub for new kernels
grub-mkconfig -o /boot/grub/grub.cfg
# perform the next standard steps :
dispatch-conf
emerge --depclean
# read news
eselect news list
Delete temporary snapthot
Delete the build snapthot :
1
2
# delete snapthot
btrfs subvolume delete snapshot-2024_01_04