cd ~/>cat multi-boot-partitioning-maintenance.md

Multi-boot partitioning / Maintenance

#linux#btrfs#void#arch#grub#multiboot#maintenance

What requires ongoing attention

Most of this setup runs without intervention. The pieces that do require attention are specific and infrequent.

Kernel filename changes in 40_custom

The most brittle part of the setup. Arch’s 40_custom contains hardcoded kernel filenames for Void’s kernel:

linux /vmlinuz-6.12.81_1
initrd /initramfs-6.12.81_1.img

When Void updates its kernel, the filename changes — vmlinuz-6.12.82_1, for example. The hardcoded entry becomes stale. GRUB will attempt to load the old filename, fail to find it, and present an error at boot.

The mitigation is a post-install hook on Void. In Void, xbps hooks live in /etc/xbps.d/:

# /etc/xbps.d/kernel-update.sh (called by a hook)
#!/bin/bash
KERNEL=$(ls /boot/vmlinuz-* | sort -V | tail -1 | xargs basename)
INITRD=$(ls /boot/initramfs-*.img | grep -v fallback | sort -V | tail -1 | xargs basename)

sed -i "s|linux /vmlinuz-.*|linux /$KERNEL|" /boot/grub/40_custom_void
sed -i "s|initrd /initramfs-.*\.img|initrd /$INITRD|" /boot/grub/40_custom_void

grub-mkconfig -o /boot/grub/grub.cfg

This requires network access to the Arch GRUB installation and appropriate permissions. The simpler approach: after every Void kernel update, update 40_custom manually and run grub-mkconfig on Arch. Kernel updates are infrequent enough that manual handling is acceptable.

/boot space

p8 is 7.6G. Void and Arch each keep two kernels (current and LTS, or current and previous). Realistically:

  • 2 Void kernels + initramfs: ~500MB each = ~1G
  • 2 Arch kernels + initramfs: ~500MB each = ~1G
  • GRUB files, memtest, misc: ~100MB

Total expected occupancy: ~2.1G on a 7.6G partition. This is not a concern under normal conditions. It would become a concern only if many kernel versions accumulated without cleanup.

Check with:

df -h /boot
ls -lh /boot/vmlinuz-*

btrfs scrub — quarterly

btrfs scrub reads all data and metadata and verifies checksums. It detects silent corruption — blocks that were written correctly but later bit-rotted. On a single-device btrfs pool with no RAID, it cannot repair corruption it finds, but it reports which files are affected.

btrfs scrub start /
btrfs scrub status /

Scrub is I/O intensive. Run it during off-hours or cap its I/O priority:

ionice -c 3 btrfs scrub start /

Quarterly is sufficient for a desktop NVMe. If scrub finds errors, the file path is logged — you can restore from snapshot or backup.

What does NOT require attention

The list of things that worry multi-boot users but should not:

btrfs balance on a schedule — unnecessary unless metadata block groups are filling or you have deleted many snapshots. See [Multi-boot partitioning / btrfs metadata and balance].

EFI entry drift — there is one EFI entry pointing to Arch’s GRUB. GRUB reads the config from p8. Adding a new distro means adding a 40_custom entry, not a new EFI entry.

/boot/efi contents — the ESP contains only GRUB’s EFI binary. It does not need to be touched except during GRUB reinstallation.

zram — configured once, starts on boot, requires no attention.

Snapshot strategy

snapper manages snapshots for @void. It is not configured for @void-var, @home, or @data.

@void-var snapshots would capture package caches, logs, and journal data — noisy and large. Rolling back a Void system snapshot while keeping var as-is is the correct behavior: OS state reverts, package database and runtime data stay current.

@home snapshots would be enormous and mostly noise. Home directory contents change constantly. Meaningful home backup belongs in a dedicated backup tool (restic, borg) with deduplication, not in CoW snapshots.

@data is infrequently written. No snapshot configuration currently — data here is either versioned in git or backed up elsewhere.

The shared @docker risk

@docker at /var/lib/docker is shared between Void and Arch. Both distros mount it. The assumption is that only one distro runs at a time — dual-boot, not virtualization.

The risk: if one distro’s Docker daemon corrupts the storage backend (overlay2 layer metadata, the image store, the build cache), the corruption is immediately visible to the other distro. There is no isolation at the filesystem level.

Mitigation: don’t use Docker’s --privileged mode carelessly, don’t kill the daemon mid-write, and run docker system prune periodically to reduce the surface area of the shared state.

If the storage backend does become corrupted, docker system prune -a --volumes resets it. Images are re-pulled; containers are disposable.

Kernel update procedure for Void

  1. xbps-install -Su updates Void, including the kernel if a new version is available
  2. New kernel files appear in /boot/ with the new version string
  3. Update 40_custom on Arch with the new filename:
    # on Arch
    vim /etc/grub.d/40_custom  # update vmlinuz- and initramfs- lines
    grub-mkconfig -o /boot/grub/grub.cfg
  4. Reboot into Void to confirm the new kernel boots
  5. Remove the old kernel from Void: xbps-remove linux6.12 (old version)
  6. Old kernel files disappear from /boot/

Step 3 must happen before step 4. Rebooting into Void before updating the GRUB config means GRUB still points at the old (now deleted) kernel and will fail.

// END OF TRANSMISSION
See you, Space Cowboy.

Connection closed. Returning to terminal...