93 lines
3.1 KiB
Markdown
93 lines
3.1 KiB
Markdown
# 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:
|
|
|
|
```text
|
|
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:
|
|
|
|
```text
|
|
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:
|
|
|
|
```text
|
|
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.
|
|
|
|
## Related Coverage
|
|
|
|
- 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.
|