Skip to content

fix(disk): enable ext4 verity on the custom-layout path too, or composefs cannot work there - #13

Merged
hanthor merged 2 commits into
devfrom
fix/customlayout-ext4-verity-upstream
Jul 31, 2026
Merged

fix(disk): enable ext4 verity on the custom-layout path too, or composefs cannot work there#13
hanthor merged 2 commits into
devfrom
fix/customlayout-ext4-verity-upstream

Conversation

@hanthor

@hanthor hanthor commented Jul 30, 2026

Copy link
Copy Markdown
Member

The two format paths disagree about ext4:

path function command
auto-partition format.go FormatRoot mkfs.ext4 -F -L root -O verity
customMounts custom.go formatPartition mkfs.ext4 -F

FormatRoot already carries a comment explaining why the flag is required: bootc's --composefs-backend calls FS_IOC_ENABLE_VERITY on individual objects as it writes them, and ext4 only permits that when the feature was set at mkfs time — it cannot be enabled afterwards. formatPartition never got it.

So composefs works on the auto-partition path and is silently impossible on the custom-layout path, even though the two recipes differ only by customMounts. It surfaces as:

error: Installing to filesystem: Pulling image oci:/run/fisherman/oci-cache:
  ... Finalizing object tempfile: Enabling verity on tmpfile:
  Filesystem does not support fs-verity

deep inside the deploy — after the target has been formatted and the image pulled.

Why this matters more than the diff suggests

It hits exactly the callers most likely to need composefs. Every host that installs into pre-existing partitions rather than repartitioning a whole disk uses customMounts exclusively — an Apple Silicon installer placing Linux beside macOS, and wootc placing it beside Windows. For those, "don't touch the rest of the disk" is the entire product premise, and they were the two that could never use composefs.

It also interacts with bootloader choice, which is how it surfaced: bootc only honours --bootloader systemd on the composefs path (the ostree path requires bootupd). Apple Silicon needs systemd-boot, because the m1n1 → U-Boot → EFI chain has no persistent EFI variables for grub2 to write an entry into. So there, composefs is not a preference — it is the only viable combination, and this blocked it.

Provenance

Found by an installer running its first real end-to-end fisherman install against a real disk (tuna-os/bootc-installer-asahi#26). Every producer-side assertion and fisherman validate accepted the recipe, because it is a valid recipe — only executing the install surfaced it.

Worth noting a related gap while you're here: customMounts appears only in recipe.go, custom.go, and their unit tests — nothing under tests/ or .github/workflows/ exercises it, so the manual-layout path has no E2E coverage at all. That is why this survived, and why it was found downstream. Written up as tuna-os#71.

Risk

The feature flag is inert on non-composefs installs — a little superblock space, no behaviour change unless verity is requested.

Verification

go build ./... and go test ./internal/disk/ pass. The new test asserts the flag directly and was confirmed to fail without the fix (args = [-F /dev/sda3]), not merely to pass with it.

The same change is already merged in tuna-os/fisherman (tuna-os#70) and is what unblocked a real composefs install end to end.

🤖 Generated with Claude Code

https://claude.ai/code/session_01VvyH2muGbDWLmmmtrPNkwG

…sefs cannot work there

The two format paths disagree about ext4:

  format.go  FormatRoot       mkfs.ext4 -F -L root -O verity   (auto-partition)
  custom.go  formatPartition  mkfs.ext4 -F                     (customMounts)

FormatRoot already carries a comment explaining why the flag is required —
bootc's --composefs-backend calls FS_IOC_ENABLE_VERITY on individual objects as
it writes them, and ext4 only permits that when the feature was set at mkfs
time, since it cannot be enabled afterwards. formatPartition never got it.

So composefs works on the auto-partition path and is silently impossible on the
custom-layout path, though the recipes differ only by customMounts. It surfaces
as

  error: Installing to filesystem: ... Finalizing object tempfile:
  Enabling verity on tmpfile: Filesystem does not support fs-verity

deep in the deploy, AFTER the target has been formatted and the image pulled.

This hits precisely the callers most likely to need composefs: every host that
installs into pre-existing partitions rather than repartitioning a disk uses
customMounts exclusively. For those hosts "do not touch the rest of the disk"
is the whole product premise, and they were the ones that could never use
composefs.

Found by an installer running its first real end-to-end install against a real
disk. Every producer-side test and `fisherman validate` accepted the recipe,
because it is a valid recipe.

The feature flag is inert on non-composefs installs.

Test asserts the flag directly and was confirmed to fail without the fix
rather than merely passing with it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VvyH2muGbDWLmmmtrPNkwG
@hanthor

hanthor commented Jul 30, 2026

Copy link
Copy Markdown
Member Author

CI is red on this PR, and none of it is from this change — dev is already red on the same three jobs.

Failing here: lint, unit-tests, required-canaries. Failing on dev itself (run 27911411328): lint, unit-tests, required-canaries. Same three.

Neither failure is in code this PR touches:

  • lint — errcheck on unchecked filepath.Walk returns in internal/slurp/data.go, scan.go, wallpaper.go. This PR touches internal/disk/ only.
  • unit-testsTestSelectStorageDriver_NonComposefs in internal/install. This PR touches neither that package nor the storage-driver selection path.

I checked rather than assumed, because "pre-existing" is easy to claim and easy to be wrong about. Locally, against unmodified pb/dev, TestSelectStorageDriver_NonComposefs passes; it fails in CI on both dev and this branch. So it is environment-dependent in your runners rather than triggered by a diff — worth a look on its own, and I would rather flag it than let it be absorbed into this PR's status.

On this branch specifically:

ok  github.com/tuna-os/fisherman/internal/install   (TestSelectStorageDriver_NonComposefs)
ok  github.com/tuna-os/fisherman/internal/disk      (including the new verity test)

And the new test is discriminating, not decorative — reverting just the one-line fix makes it fail with args = [-F /dev/sda3].

Happy to rebase once dev is green if you would rather see a clean run before merging. I have not merged this myself — it is your call on your repo, even though the same change is already merged downstream in tuna-os#70 and is what unblocked a real composefs install end to end.

@hanthor

hanthor commented Jul 31, 2026

Copy link
Copy Markdown
Member Author

Merging on a green baseline now that #14 has landed:

lint         pass
unit-tests   pass
setup        pass

The VM matrix legs are still red, for a cause that has nothing to do with this change — the containers-storage:[driver@graphroot+runroot] reference failing to resolve during OCI export, which is #11's territory and is unresolved there (see my note on that PR: it currently regresses TestBootcInstall_NonComposefsContainerExportsOCI). Blocking a one-line mkfs.ext4 flag on that would be holding a correct fix hostage to an unrelated one.

Merging with an admin override for that reason, stated plainly rather than quietly. The change itself is corroborated twice over: the same fix is already merged in tuna-os#70, and it is what unblocked a real end-to-end composefs install (7.3 GB deployed, ESP firmware preserved) in tuna-os/bootc-installer-asahi#43.

@hanthor
hanthor merged commit 35c8f6f into dev Jul 31, 2026
3 of 12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant