2026-08-18 09:20:44 +02:00
2026-08-18 09:20:44 +02:00
2026-08-18 09:20:44 +02:00
2026-08-18 09:20:44 +02:00
2026-08-18 09:20:44 +02:00
2026-08-18 09:20:44 +02:00
2026-08-18 09:20:44 +02:00
2026-08-18 09:20:44 +02:00
2026-08-18 09:20:44 +02:00
2026-08-18 09:20:44 +02:00
2026-08-18 09:20:44 +02:00

EROFS for FreeBSD

Build Kernel Module

Build on FreeBSD 15 amd64 with a matching FreeBSD source tree. The default source path is /usr/src:

WITH_ZSTDIO=0 ./build.sh

Use FREEBSD_SRC=/path/to/freebsd-src when the source tree is elsewhere. The script is a native FreeBSD wrapper around src/Makefile and bsd.kmod.mk; the Makefile is the authoritative module name, source list, architecture gate, and per-source flag definition. Each run rebuilds build/obj and writes build/erofs.ko.

Only MACHINE_ARCH=amd64 is currently qualified. Other architectures are rejected explicitly instead of inheriting amd64 ABI flags. Build ZSTD support with:

WITH_ZSTDIO=1 ./build.sh

The enabled module references the FreeBSD kernel ZSTD API and therefore requires a running kernel built with options ZSTDIO. WITH_ZSTDIO=0 builds a module without those references and rejects ZSTD-compressed images at mount.

Mount

EROFS is read-only. Mount a single-device image with:

mount -t erofs -o ro /dev/md0 /mnt/erofs

For an image with external blob devices, map every one-based on-disk device slot explicitly with device.<slot>=<provider>:

mount -t erofs -o ro \
  -o device.2=/dev/md92 \
  -o device.1=/dev/md91 \
  /dev/md90 /mnt/erofs

Slot names make the mapping independent of option order. Every external slot must be present exactly once; assigning the same GEOM provider to multiple slots is rejected. The same names and values may be passed directly as nmount(2) iovec entries.

There is no repo-local mount_erofs binary; FreeBSD's generic /sbin/mount frontend passes these distinct option names through to nmount(2). The driver forces every successful mount read-only, so even -o rw produces a read-only mount rather than enabling writes.

If an image has a device table but no device.<slot> options are supplied, the primary provider is treated as a Linux-compatible flatdev image. It must contain the external ranges at their declared uniaddr block offsets, for example a deterministic concatenation of the primary image and its blobs.

Qualified Semantics

  • Compact/extended metadata, Linux device-number decode, plain/inline/chunk data, and LZ4/MicroLZMA/DEFLATE/ZSTD compressed reads.
  • Inline tails are confined to the inode metadata block and declared image or metabox backing bounds.
  • Directory lookup/readdir share strict validation while accepting Linux-style nonzero unused bytes after the final name NUL.
  • Compressed st_blocks reflects the inode's on-disk compressed block count; uncompressed and chunk files retain logical block rounding.
  • FreeBSD 15 local vnode pager sync/async entry points are used for real mmap faults.
  • NFS export uses full 64-bit NIDs and a generation derived from the superblock seed and inode metadata. Replacing metadata changes the generation and makes old handles stale; a metadata-identical, payload-only replacement is not guaranteed to return ESTALE.

See docs/features.md for the bounded feature claim and tests/results/manual/2026-08-09T1804Z-final-review-independent/manual-test-report.md for the final-review evidence.

Test Fixtures

tests/prepare_directory_fixtures.sh creates the deterministic TC048/141/148 directory fixtures. tests/prepare_error_fixtures.sh and tests/erofs_fixture.py create and self-check the structured TC002/086/087/102 and TC112-TC116/119 fixtures. Generated trees, images, overlays, and build/ outputs are test artifacts and are not committed.

S
Description
No description provided
Readme
1.2 MiB
Languages
C 99.7%
Makefile 0.3%