Skip to content

bootc status fails with EBUSY when the ESP is already mounted (e.g. via systemd.mount-extra) #2355

Description

@dustinkirkland

On composefs-based bootc hosts where the ESP is auto-mounted in the root
mount namespace before bootc status runs, the status command fails
consistently with:

error: Status: Mounting /dev/vda1: Device or resource busy (os error 16)

Reproduction

Any bootc composefs deployment where the ESP is pre-mounted. One common
path: bootc install to-filesystem writes
systemd.mount-extra=UUID=<ESP>:/boot:auto:ro into the deployment kernel
cmdline (visible in /proc/cmdline). At boot, systemd's fstab-generator
processes the cmdline arg and emits a boot.mount unit that mounts the
ESP read-only at /boot before user services start.

bootc status at any later point then hits:

crates/lib/src/store/mod.rs BootedStorage::new (ComposefsBooted arm)
→ crates/lib/src/bootc_composefs/boot.rs mount_esp(...)
→ crates/mount/src/tempmount.rs TempMount::mount_dev(...)
→ rustix::mount::mount(dev, tmpdir, "vfat", ...)

which returns EBUSY because the same block device is already mounted
elsewhere in the same mount namespace.

Environment where reproduced

  • bootc v1.16.6 (also reproduced on main at 3bfa9dd)
  • Linux 6.18-series kernel (mainline)
  • systemd 261.2
  • QEMU x86_64, single-deployment composefs bootc host
  • /boot mounted ro via systemd.mount-extra=UUID=...:/boot:auto:ro

Impact

bootc status, bootc status --json, and any consumer scripting
around them are broken on these hosts.

Suggested fix

Split the "mount ESP" primitive into mount_esp (unchanged, fresh
mount(2)) and a new mount_esp_readonly that gracefully reuses an
existing ESP mount via open_tree(OPEN_TREE_CLONE) + move_mount.
Wire the read-only status path to the latter; leave the write-path
callers (bootc install, gc) using mount_esp and failing loudly
on EBUSY — silently writing to a ro clone would be worse.

Fix + tests: (PR link forthcoming)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions