Skip to content

racer: replace segment allocator with an extent volume - #948

Draft
Jordan Olshevski (jveski) wants to merge 5 commits into
mainfrom
racer-extent-alloc
Draft

Jordan Olshevski (jveski) wants to merge 5 commits into
mainfrom
racer-extent-alloc

Conversation

@jveski

Copy link
Copy Markdown
Contributor

This replaces the Racer dataplane's segment allocator and in-memory page index with a per-worker extent volume. Each volume splits the disk into 16 MiB slots that hold either one large page or many small pages in size classes from 4 KiB, and indexes them in an on-disk copy-on-write B+tree committed through A/B superblocks with fsync, so there is no write-ahead log. Pages have two tiers: cache pages are committed lazily and may be lost on crash, while held pages use the storage tier and are durable before the hold is acknowledged. Checkpoints now carry only object metadata, existing slab files are reformatted on first start, and disk eviction now frees whole slots. Tests that covered only the removed segment, freeze, and checkpoint pause code were deleted; the new volume has unit, io_uring, and crash and bit-flip simulation tests.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved issues affect safe slab migration, hold durability and eviction protection, and shutdown completion.

3 open issues
What changed in this PR

Replaces Racer’s segment allocator and page index with per-worker extent volumes, separating disposable cache data from durable held pages.

Changes:

  • Adds volume formats, checksummed index nodes, and A/B superblocks.
  • Integrates durable holds, periodic commits, and metadata-only checkpoints.
  • Updates configuration, telemetry, documentation, and storage tests.
File Description
docs/​content/​reference/​racer.md Documents slot storage and durability guarantees.
designs/​racer-page-alloc.md Updates allocator architecture documentation.
designs/​racer-extent-volume.md Describes volume layout and recovery.
cmd/​racer-dataplane/​tests/​production_dataplane/​hotpath.rs Updates disk-page statistics.
cmd/​racer-dataplane/​tests/​production_dataplane.rs Migrates storage fixtures and assertions.
cmd/​racer-dataplane/​tests/​process_restart.rs Checks metadata-only checkpoints.
cmd/​racer-dataplane/​src/​test_support.rs Updates shared storage fixtures.
cmd/​racer-dataplane/​src/​telemetry.rs Uses slot-based accounting internally.
cmd/​racer-dataplane/​src/​subscription_interop.rs Mounts volumes in subscription fixtures.
cmd/​racer-dataplane/​src/​store/​versions.rs Adds bounded version reverse mappings.
cmd/​racer-dataplane/​src/​store/​test_disk.rs Adds simulated volume test helpers.
cmd/​racer-dataplane/​src/​store/​key.rs Defines hashed disk-page keys.
cmd/​racer-dataplane/​src/​store/​holds.rs Tracks storage-tier hold publications.
cmd/​racer-dataplane/​src/​runtime.rs Updates record-size constants in tests.
cmd/​racer-dataplane/​src/​retention.rs Adapts eviction accounting to slots.
cmd/​racer-dataplane/​src/​read/​tests/​warming.rs Adapts warm tests to durable commits.
cmd/​racer-dataplane/​src/​read/​tests/​remote.rs Updates remote-read storage fixtures.
cmd/​racer-dataplane/​src/​read/​tests/​peer_copies.rs Mounts volumes for disk-copy tests.
cmd/​racer-dataplane/​src/​read/​tests/​hot_reads.rs Updates writer startup in tests.
cmd/​racer-dataplane/​src/​read/​tests/​fill.rs Adds held-page corruption repair coverage.
cmd/​racer-dataplane/​src/​read/​tests.rs Mounts storage for hold admission tests.
cmd/​racer-dataplane/​src/​read/​dispatch.rs Commits raised hold deadlines before replying.
cmd/​racer-dataplane/​src/​read/​candidates.rs Uses volume-key ownership scan cursors.
cmd/​racer-dataplane/​src/​contention.rs Updates contention storage fixtures.
cmd/​racer-dataplane/​src/​config.rs Validates slots and deprecates segment settings.
cmd/​racer-dataplane/​src/​app/​tests/​dst.rs Updates simulated disk inspection.
cmd/​racer-dataplane/​src/​app/​tests.rs Tests lazy commits and volume metrics.
cmd/​racer-dataplane/​src/​app/​recovery.rs Recovers metadata and purges removed caches.
cmd/​racer-dataplane/​src/​app/​native.rs Checks slot-rounded slab sizing.
cmd/​racer-dataplane/​src/​app/​devices/​loop_test.rs Tests offset-based device I/O.
cmd/​racer-dataplane/​src/​app.rs Integrates volume startup and commit lifecycle.
cmd/​racer-dataplane/​src/​admission.rs Uses shared record sizing for budgets.
cmd/​racer-dataplane/​Cargo.lock Records the allocator checksum dependency.
cmd/​racer-dataplane/​alloc/​tests/​volume_slab.rs Tests volume binding, I/O, and syncing.
cmd/​racer-dataplane/​alloc/​tests/​common/​mod.rs Adds shared volume test utilities.
cmd/​racer-dataplane/​alloc/​src/​volume/​superblock.rs Adds checksummed superblock encoding.
cmd/​racer-dataplane/​alloc/​src/​volume/​node.rs Adds validated tree-node encoding.
cmd/​racer-dataplane/​alloc/​src/​volume/​mod.rs Exposes volume APIs.
cmd/​racer-dataplane/​alloc/​src/​volume/​format.rs Defines geometry, keys, and values.
cmd/​racer-dataplane/​alloc/​src/​lib.rs Replaces segment exports with volume APIs.
cmd/​racer-dataplane/​alloc/​src/​index.rs Removes the old in-memory page index.
cmd/​racer-dataplane/​alloc/​Cargo.toml Adds CRC-64 support.

Review effort: Balanced

Comment thread cmd/racer-dataplane/src/app.rs Resolved
Comment thread cmd/racer-dataplane/src/app.rs Resolved

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Unresolved hold protection, capacity enforcement, allocation progress, and checkpoint failures affect storage reliability.

No open issues 🎉

1 previously missed issue

In code that hasn't changed since last review

Medium severity Failed hold commits can strand in-memory reservations

cmd/​racer-dataplane/​src/​read/​dispatch.rs:897

A commit failure here leaves the in-memory reservation behind. StoreWriter::reserve_hold reserves capacity before awaiting the commit (src/store.rs:1142-1143), but the error prevents reserve_warm from adding this worker to its cleanup list (src/read/dispatch.rs:467-473). Failed admission therefore omits it when releasing unused holds (src/read/warm.rs:615-620). A refused HEAD can strand its requested capacity until expiry and cause later warm requests to be refused. Track reservations that succeeded even when their commit failed, and release their unused capacity without dropping published holds or interfering with another active job.

3 resolved since last review

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Unresolved retention, reclamation, and checkpoint-boundary issues affect held-page guarantees and recovery.

No open issues 🎉

1 previously missed issue

In code that hasn't changed since last review

Medium severity Deferred storage reclamation stalls without a second commit

cmd/​racer-dataplane/​src/​app.rs:1680

Deferred storage frees need a second successful commit even when the index is clean. After a held full-page record is invalidated, the first commit clears is_dirty(), but its slot stays charged until the next successful epoch (cmd/racer-dataplane/alloc/src/volume/slots.rs:549-561). This gate schedules no follow-up, and an explicit clean commit also returns immediately (cmd/racer-dataplane/alloc/src/volume/store.rs:1205-1212). At the storage-slot quota, repair can therefore remain blocked with Busy until unrelated mutations or hold expiry. Treat pending reclamation as commit work and allow a superblock-only rotation without new index changes. Cover repair at the storage quota with no unrelated writes.

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Retention protection, checkpoint key limits, and disk-page capacity enforcement remain unresolved.

No open issues 🎉

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved allocation stalls and incomplete ownership scans affect storage progress and resident-page maintenance.

1 open issue
1 previously missed issue

In code that hasn't changed since last review

Medium severity Open cache slots block allocation for new size classes

cmd/​racer-dataplane/​src/​config.rs:473

The accepted four-slot geometry can leave cache writes for a new size class returning Busy indefinitely. Three small records in different size classes occupy all three data slots, which remain open while partly filled (alloc/src/volume/slots.rs:625-645,1083-1092). Eviction skips every open slot (alloc/src/volume/slots.rs:818-821), so a fourth class, including a full page, cannot allocate even after leases are released and with no holds. Add pressure reclamation that safely closes and evicts eligible open cache slots, with a regression test for this minimum-size volume. Raising the minimum alone would only hide the allocator problem.

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The persistent-format migration and crash-durability guarantees require human validation, alongside resolution of the retained correctness issues.

1 open issue
1 resolved since last review

Review effort: Balanced

Comment thread cmd/racer/src/read/candidates.rs Resolved

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The storage migration and crash-durability protocol require human review, alongside unresolved retention correctness concerns.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Eviction can overwrite slots still used by active reads, and forward wall-clock jumps can delete pages whose holds remain live.

3 open issues

Review effort: Balanced

where
S::Error: From<Error>,
{
let Some((slot, incarnation)) = self.shared.state().slots.evict_candidate(now, tier) else {

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Human assessment is needed because metadata eviction can break pinned reads when the origin is offline, alongside cancellation-cleanup and scan-progress risks.

1 open issue
2 resolved since last review

Review effort: Balanced

This replaces the Racer dataplane's segment allocator and in-memory
page index with a per-worker extent volume. Each volume splits the disk
into 16 MiB slots that hold either one large page or many small pages
in size classes from 4 KiB, and indexes them in an on-disk
copy-on-write B+tree committed through A/B superblocks with fsync, so
there is no write-ahead log. Pages have two tiers: cache pages are
committed lazily and may be lost on crash, while held pages use the
storage tier and are durable before the hold is acknowledged.
Checkpoints now carry only object metadata, existing slab files are
reformatted on first start, and disk eviction now frees whole slots.
Tests that covered only the removed segment, freeze, and checkpoint
pause code were deleted; the new volume has unit, io_uring, and crash
and bit-flip simulation tests.
…l returns

allocate_evicting and reserve_free moved each eviction's removals into a
local vector, so a later error or a dropped future lost them and the caller's
take_evicted cleanup could not release their bookkeeping. They now stay
queued on the volume until the call returns them.
…g it

Eviction yields between batches, and reads can lease the slot meanwhile.
Finishing the eviction freed the slot regardless, so allocation could reuse
it while a disk or GPU read still used it. Eviction now gives the slot back
when it is leased at the end; its removed entries stay removed, and a later
eviction frees it once the lease is gone.
A hold stays live until both its wall and monotonic deadlines pass, but
storage eviction compared retain_until with the wall clock alone, so a
forward wall-clock jump could evict pages the worker still reported as held.
Eviction now uses a time that follows the wall clock but never runs ahead of
monotonic time elapsed since its last reading.

This branch has not been deployed

No deployments
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.

2 participants