pool only.Expand description
The file-backed extent store: a userspace extent allocator over one anonymous file per extent class in a scratch directory.
Files. Each class of the ladder the caller passes to
FileStore::open gets one file, opened O_TMPFILE so it has no name
and the kernel frees its blocks when the process exits, crash included.
Where the filesystem refuses O_TMPFILE, the store creates a uniquely
named file and unlinks it immediately. A slot (class, index) lives at
byte offset index * class_size of its class’s file.
Block ownership. Each class allocates slot indices with a
SlotAllocator behind its own mutex. Its warm side holds free slots
whose blocks are still allocated, its cold side free slots whose blocks
were punched, and slots above its high-water mark were never touched.
Freeing a slot pushes it warm with no filesystem call, so slot reuse
performs no metadata operation. A slot taken cold or from the high-water
mark is fallocated before it is handed out, which turns ENOSPC into
an allocation failure before any data is in flight.
Capacity. Every slot with allocated blocks, in use or warm, is
charged at its class size against the store’s capacity. When an
allocation does not fit, the store punches holes over warm slots of the
other class holding the most warm bytes, moving them cold, until it
fits. Independently, FileStore::release_warm punches warm slots on
its caller’s schedule, so the bytes the store holds follow its live data
and space freed in one class is available to any other. A slot it punches
pays a fallocate when next allocated.
Alignment. Class sizes are page multiples, and every transfer covers
whole pages from a page-aligned buffer, which satisfies O_DIRECT on
devices with 512-byte and 4 KiB logical blocks. The store owns that
rounding: FileStore::write and FileStore::read return the length
they transferred. open probes one page-aligned write and read. A probe
failing with EINVAL means the device needs a larger alignment or the
filesystem lacks direct I/O, and the store reopens its files buffered:
each write is then followed by a synchronous writeback and a page-cache
drop over its range. Memory-backed filesystems are rejected by type,
since tmpfs accepts the probe and would hold extents in RAM.
Errors. Running out of capacity, or ENOSPC from fallocate, fails
the allocation with AllocError::Full. An ENOSPC from a write fails
it with WriteError::Full after the store punches and takes back the
slot. A short direct write is retried whole first, and its final error
is classified the same way. Either ENOSPC additionally lowers the
capacity to the bytes allocated at that moment. The volume can be shared
with other writers, so FileStore::refresh_capacity re-derives the
capacity from the volume’s free space, and room another writer frees
becomes usable again. Any other write or fallocate error disables
writes for the store’s lifetime. Data
already written stays readable. A read error, short read, or checksum
mismatch panics: there is no correct value to return, and the pool’s
contents are recreatable.
Modules§
- sys 🔒
- The platform seam: every filesystem syscall the store makes.
Structs§
- Aligned
Buf 🔒 - Page-aligned, growable byte buffer for
O_DIRECTreads. - Class 🔒
- One extent class: its file and slot allocator.
- Counters 🔒
- File
Slot 🔒 - A slot in the store:
indexin the file of extent classclass. - File
Store 🔒 - The file-backed extent store. See the module documentation.
- File
Store 🔒Stats - A snapshot of the store’s counters.
Enums§
- Alloc
Error 🔒 - Why an allocation failed.
- IoMode 🔒
- Where the store’s I/O goes.
- Write
Error 🔒 - Why a write failed.
Constants§
- DIRECT_
WRITE_ 🔒ATTEMPTS - Attempts a direct write makes at a slot before a short write counts as failed.
- READ_
LATENCY_ BUCKETS - Number of read-latency buckets. Bucket
i < READ_LATENCY_BUCKETS - 1counts reads that took less than32 µs << iand, fori > 0, at least16 µs << i. The last bucket counts reads of 65.536 ms and more.
Functions§
- crc 🔒
- The checksum the store verifies on every read.
- derived_
capacity 🔒 - The capacity of a new store on a volume with
availablebytes free, perusable_bytes.Noneif that cannot hold one slot oflargest_classbytes, the largest extent class. - open_
files 🔒 - Opens
classesanonymous files forio_modeand probes the first. InIoMode::Direct, anEINVALfrom the open or the probe means direct I/O is unusable here. - probe 🔒
- Allocates, writes, reads back, and punches one page at offset 0.
- read_
latency_ 🔒bucket - The bucket of
FileStoreStats::read_latency_bucketsfor a read that tookmicrosmicroseconds. - usable_
bytes 🔒 - The bytes a store may allocate on a volume with
availablebytes free to unprivileged writers: those bytes minus the larger of 1 GiB and 2% of them. - write_
all 🔒 - Writes all of
bufatoffset, retrying onEINTRand short writes. InIoMode::Direct, a short write restarts the whole buffer atoffset, at mostDIRECT_WRITE_ATTEMPTStimes, and the final attempt’s error is returned.