Files
erofs-freebsd-out-tree/issues/TC010-48bit-statfs-large-provider.md
T
2026-08-18 09:20:44 +02:00

3.1 KiB

TC010 48-bit statfs Large Provider

Status: RESOLVED - qualified sparse vnode provider validated

Resolved: 2026-08-09

Baseline: cd0e985b5ac54a4b7acb7042422329ad1729fb3e

Original Problem

TC010 requires a real EROFS mount whose 48-bit superblock block count has a nonzero high word. A nonzero blocks_hi declares at least 2^32 filesystem blocks, so a 4 KiB filesystem needs a provider larger than 16 TiB. Earlier vnode-md work used only small regular images and correctly could not claim PASS.

This affects:

  • 48-bit superblock block-count decoding;
  • primary-device media-size validation;
  • FreeBSD statfs(2) and df(1) 64-bit totals;
  • the union selector between rb.blocks_hi and rb.rootnid_2b.

Exact Trigger

  1. EROFS_FEATURE_INCOMPAT_48BIT is set.
  2. rootnid_8b is nonzero, selecting rb.blocks_hi.
  3. blocks_hi is nonzero.
  4. Provider media size is at least total_blocks << blkszbits.
  5. Superblock CRC32C, root inode, and normal mount checks pass.

A short provider fails with ENXIO; that negative guard cannot replace the positive statfs test. TC150's rootnid_8b == 0 fallback and multidevice totals also select different production paths.

Earlier Attempts

  1. Structured metadata patching and CRC32C recomputation succeeded.
  2. The normal small vnode provider failed media-size validation as expected.
  3. Static source comparison confirmed Linux's 48BIT && rootnid_8b selector, but static arithmetic was not counted as dynamic coverage.
  4. No earlier run had attached and mounted a qualified 16 TiB provider, so the issue remained SHELVED.

Resolution

The isolated FreeBSD 15.0-RELEASE-p8 guest uses UFS2, which supports a sparse regular file large enough for vnode md without allocating 16 TiB physically:

truncate -s 17592193667072 TC010-provider.raw
stat: size=17592193667072 allocated_blocks=15232 block_size=32768
mdconfig -a -t vnode -f TC010-provider.raw: md0
diskinfo mediasize: 17592193667072 bytes

The structured fixture encoded:

blocks_lo=1861
blocks_hi=1
rootnid_8b=36
total_blocks=4294969157
required_provider_length=17592193667072

Prefix SHA256: d3ffadc6fc9e73f85a8a5973b4ac5ee2a2da57b4e8baeccd259fa4325a2146cf.

The exact prefix was copied to the sparse provider, then extended with zeros. Mount succeeded with KLD SHA256 8349c97c7ced253fff32a9e706f29313f309cb63a270e4e39a4501426f2b95c6. df reported:

Filesystem  Type  1024-blocks        Used Avail Capacity
/dev/md0    erofs 17179876628 17179876628     0   100%

17179876628 == 4294969157 * 4; no 32-bit wrap occurred. f_bfree and available blocks were zero, so Used correctly equaled total. The control file matched, dmesg had no new fault, and the mount, md unit, sparse provider, and KLD were cleaned up.

  • TC017 separately repeated the small-provider ENXIO guard and qualified sparse-provider mount, proving the nonzero high-word parse dynamically.
  • TC018 separately read exact bytes from physical offset 17592191561728, above 16 TiB; it did not substitute a large df result for high-address data I/O.

No repo22 kernel source change was made during this resolution.