Skip to content

composefs: Find GRUB's boot directory on a separate /boot when upgrading - #2516

Merged
cgwalters merged 3 commits into
bootc-dev:mainfrom
cgwalters-forge:bot/cfs-separate-boot
Oct 1, 2026
Merged

cgwalters merged 3 commits into
bootc-dev:mainfrom
cgwalters-forge:bot/cfs-separate-boot

Conversation

@cgwalters-bot

Copy link
Copy Markdown
Contributor

With GRUB and a separate /boot partition (as every image-builder disk has), composefs bootc switch and bootc upgrade fail with "Getting sorted Type1 boot entries: No such file or directory": staging built its paths from /sysroot, and /sysroot/boot is empty when the boot partition is mounted on /boot. #2440 fixed the same for status (and, through the booted storage, rollback, finalize and GC), so this keeps the path that get_boot_dir_for_grub() picked in Storage and derives the BLS and GRUB UKI staging paths from it, including the kernel paths in BLS entries, which must then be relative to the boot partition.

The second commit adds plan-57, which gives the test VM's disk a separate ext4 /boot (carved out of the ESP, like the XBOOTLDR test does) and then switches, upgrades and rolls back. bcvk's disks have no separate /boot, and a disk installed to a loop device inside the VM can't be booted, so repartitioning was the way to cover the booted paths.

Tested on a 16-core devspace (composefs, GRUB, ext4, BLS): just unit-tests, just validate, and plans 56 (now renumbered 57), 24 and 36 passed. Without the fix, the new plan fails with the error above. The fix also passed switch + reboot + upgrade + reboot in rhel-bootc-examples' composefs e2e test on an image-builder disk: https://gist.github.com/cgwalters-bot/04b3e5503547a054ebcdf227238eaec1

Related: #2440

The Signed-off-by: Colin Walters <walters@verbum.org> on these commits was added on cgwalters's approval of the review draft: cgwalters-forge#29 (review)

Generated-by: https://github.com/cgwalters/#llms

Comment thread crates/lib/src/store/mod.rs Outdated
/// there's a separate boot partition
const PHYSICAL_ROOT_BOOT_PATH: &str = "/sysroot/boot";
/// Where a separate boot partition is mounted in the booted root
const BOOT_MOUNT_PATH: &str = "/boot";

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has gotta be the 4th of these const for /boot

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 12fe993:

  • The new /sysroot/boot and /boot consts are gone. The PR's code (and the rest of crates/lib that spelled out "boot"/"/boot") now uses install::BOOT, in a new prep commit, 2ba5da9 "lib: Use the BOOT const for the boot directory". That one needs your sign-off.
  • The get_boot_dir_for_grub() doc and the test's header comment no longer imply that systemd.mount-extra is the only way /boot gets mounted.
  • Once install: Use systemd-repart for partitioning #2314 lands, plan-57 could switch to its repart.d fixture instead of repartitioning the VM's disk.

Your sign-off is kept on 3350f09 and 12fe993, the reworked versions of your two signed commits.

Tested on a 16-core devspace: just validate, just unit-tests, and plans 57 and 24 (composefs, GRUB, ext4, BLS) passed. The only change since that run is comment text.

Generated-by: https://github.com/cgwalters/#llms

Comment on lines +12 to +13
# Disk images from e.g. image-builder have a separate /boot partition, which
# the VMs these tests run in don't have. With GRUB, the boot partition holds

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. It's kind of about time now we need a CI flow that is going through the image-builder CLI so we are covering that in general, but specifically so we are matching the defaults around things like /boot as a partition.

This is going to be messy because there's a fundamental conflict right now in that it wants to run as root, prior bits in bootc-dev/bcvk#73

The most likely viable path is to enhance bcvk for this so we can mostly otherwise reuse our infrastructure there to do things like run the VMs with tmt if we craft a flow which hands them off to libvirt etc.

That said, we already have prior art for testing anaconda code (see anaconda.rs here).

We can also try out the "image builder in vm" flow...

@cgwalters-bot just research this a bit with live experimentation and code investigation into a gist as p1

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually there's also an intersection with #2314 here - a test fixture which uses an embedded repart.d definition to require a separate /boot would work.

But I'm uncertain if we want to merge that first. Maybe...

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having systemd-repart in the base image would definitely make this test much simpler. But again, we don't want to test only a separate /boot partition. This comes back to, I think, having a --systemd-repart cli option and not us unconditionally using repart if we find definitions. Wdyt @cgwalters? We can probably make it a hidden option as it's only useful for testing a bunch of stuff using the same image

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But again, we don't want to test only a separate /boot partition.

Isn't that all we need here? Or why do you say that?

This comes back to, I think, having a --systemd-repart cli option and not us unconditionally using repart if we find definitions.

I am not sure what you mean. We just made repart the default if found...but if yuou think there's issue with our repart let's take that to a new issue?

Comment thread crates/lib/src/bootc_composefs/boot.rs Outdated
Ok(if is_mountpoint == Some(true) {
"/"
} else {
"/boot"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's have the const used for things like this

@jmpolom

jmpolom commented Sep 29, 2026

Copy link
Copy Markdown

#2399 was incomplete (my fault) and failed to explain that the issue also affected upgrade and switch.

Comment thread crates/lib/src/store/mod.rs Outdated
Comment on lines +425 to +426
/// is mounted on `/boot` (see the `systemd.mount-extra` karg added at install
/// time). Everything that reads or writes GRUB's boot entries must go through

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note systemd.mount-extra is not the only way to do a separate /boot, in the general case other tools may not do that.

I'd just rephrase to clarify.

Comment on lines +12 to +13
# Disk images from e.g. image-builder have a separate /boot partition, which
# the VMs these tests run in don't have. With GRUB, the boot partition holds

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually there's also an intersection with #2314 here - a test fixture which uses an embedded repart.d definition to require a separate /boot would work.

But I'm uncertain if we want to merge that first. Maybe...

@github-actions github-actions Bot added the area/install Issues related to `bootc install` label Sep 29, 2026
@cgwalters-bot

Copy link
Copy Markdown
Contributor Author

plan-57 failed in CI on fedora-44 (my earlier devspace run had used the default base, not F44) with partx: error adding partition 4: systemd-udevd 259 resyncs a disk's partitions via BLKPG itself after it's written to, racing with partx. 4e10ca5 now holds the disk's lock (udevadm lock) across sfdisk and partx and checks the kernel's partition sizes; on F44 the test's /boot check also had to skip the gpt-auto automount stacked under the boot mount.

On a 16-core devspace with BOOTC_base=quay.io/fedora/fedora-bootc:44: the old 12fe993 fails the same way on ext4 and xfs; 4e10ca5 passes plan-57 twice each on ext4 and xfs (composefs, GRUB, BLS, unsealed). The test commit needs your re-sign-off now, along with the prep commit 2ba5da9.

Generated-by: https://github.com/cgwalters/#llms

@cgwalters cgwalters left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really dislike the test case code, but we can break out the image-builder or enhanced bcvk as a followup

cgwalters
cgwalters previously approved these changes Sep 30, 2026
@cgwalters
cgwalters enabled auto-merge (rebase) September 30, 2026 15:28
@cgwalters-bot

Copy link
Copy Markdown
Contributor Author

@cgwalters The centos-10 ext4 grub failure was infra: libvirt's session socket was missing, so the VM for the first plan never started and no test ran. The centos-10 xfs grub leg passed, plan-57 included. Please restart the failed job: https://github.com/bootc-dev/bootc/actions/runs/36734182266/job/109968865098

Generated-by: https://github.com/cgwalters/#llms

auto-merge was automatically disabled October 1, 2026 00:10

Head branch was pushed to by a user without write access

@cgwalters-bot
cgwalters-bot force-pushed the bot/cfs-separate-boot branch from fa5e9c3 to 0246895 Compare October 1, 2026 00:10
@cgwalters-bot

cgwalters-bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor Author

@cgwalters Rebased onto main (now 0246895). The only conflicts were in the generated tmt/plans/integration.fmf and tmt/tests/tests.fmf, next to main's new plan-50; I kept both entries, and the test keeps number 57.

  • 28a20c3 (lib: Use the BOOT const) and c864232 (composefs: Find GRUB's boot directory) rebased cleanly and keep your sign-off.
  • 0246895 (tests: Add composefs test with GRUB and a separate /boot partition) had the conflict resolved, so it lost your sign-off and needs your re-approval.

Tested on a 16-core devspace with BOOTC_base=quay.io/fedora/fedora-bootc:44: just validate passes, just unit-tests 470 passed, and just test-tmt-nobuild plan-57 (composefs, grub, ext4, bls) passed.

Generated-by: https://github.com/cgwalters/#llms

We already have `install::BOOT`, but many places still spelled out
"boot" or "/boot" by hand, which makes it easy to miss one and invites
yet more local constants for the same thing.

Prep for reusing it in the GRUB separate /boot handling.

Generated-by: AI
Signed-off-by: Colin Walters <walters@verbum.org>
With GRUB and a separate boot partition, `bootc switch` and `bootc
upgrade` fail with "Getting sorted Type1 boot entries: No such file or
directory": the boot partition is mounted on /boot (via the
systemd.mount-extra karg install adds), and /sysroot/boot is just an
empty directory on the physical root. bootc-dev#2440 taught the booted storage
to find the right directory for status, rollback, finalization and GC,
but staging a new deployment still built its paths from /sysroot, both
for BLS entries and for GRUB's UKI menu entries.

So have get_boot_dir_for_grub() return the path it picked along with
the directory, keep that in Storage, and derive every GRUB boot path
while staging from it. The decision itself moves into a pure function
so it can be unit tested. That also fixes the BLS entries' kernel and
initramfs paths, which must be relative to the boot partition then.

Every disk image-builder makes has a separate /boot, so this blocked
using those for composefs.

Generated-by: AI
Signed-off-by: Colin Walters <walters@verbum.org>
@cgwalters-bot
cgwalters-bot force-pushed the bot/cfs-separate-boot branch from 0246895 to 0f565f9 Compare October 1, 2026 12:43
@cgwalters-bot

Copy link
Copy Markdown
Contributor Author

@cgwalters Rebased onto main (regenerated tmt fmf only); 0f565f9 needs your approval for DCO.

Generated-by: https://github.com/cgwalters/#llms

Disks from image-builder always have a separate /boot, but the VMs tmt
runs in don't, so nothing covered switching, upgrading or rolling back
with that layout on composefs.

Installing to a loop device inside the VM with a separate /boot would
exercise install, but we can't boot that disk. So instead, like the
XBOOTLDR test does, give the VM's own disk the layout install would
have made: split the ESP into a smaller ESP and an ext4 XBOOTLDR
partition, move /sysroot/boot there, make the BLS entries point at the
kernels relative to it and add the systemd.mount-extra karg, and point
bootupd's bootuuid.cfg at the new filesystem. Then switch, upgrade and
roll back, checking that everything stays on /boot and that GC keeps
the kernels there in sync with the entries.

Generated-by: AI
Signed-off-by: Colin Walters <walters@verbum.org>
@cgwalters-bot
cgwalters-bot force-pushed the bot/cfs-separate-boot branch from 0f565f9 to d26a2cd Compare October 1, 2026 13:31
@cgwalters cgwalters added this to the 1.17 milestone Oct 1, 2026
@cgwalters
cgwalters enabled auto-merge (rebase) October 1, 2026 15:57
@cgwalters
cgwalters merged commit df63494 into bootc-dev:main Oct 1, 2026
53 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/install Issues related to `bootc install`

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants