spark_storage/kv_paging.rs
1// SPDX-License-Identifier: AGPL-3.0-only
2
3//! KV as a first-class paging kind (part of the tiered-cache
4//! consolidation, DEFAULT-OFF behind `ATLAS_KV_PAGING`).
5//!
6//! The flag-OFF KV overflow tier (`rdma_kv_backend`) takes the "dumb
7//! one-sided path": the peer registers ONE RW MR and the CLIENT owns a static
8//! allocator (`base + group_id × group_stride`) over a fixed arena — no peer
9//! residency, no NVMe spill. It selects that mode with the v2
10//! header's `blob_bytes == 0` RAW sentinel (the bare `[u64 total_bytes]`
11//! handshake is retired).
12//! This module is the alternative client: it sends the paging handshake
13//! (`PAGING_MAGIC_V2`, kind = `PagingKind::KV`) so KV inherits what the SSM
14//! snapshot tier already has — peer-owned residency, an NVMe-backed cold tier
15//! (unbounded depth with `--swap-cap-gb-kv 0`), and peer capacity pooling.
16//! The peer side is ALREADY wired: the `(kind, blob_bytes)` arena registry
17//! accepts kind 1 and `--swap-cap-gb-kv` parses; the whole feature is this
18//! client.
19//!
20//! Layout: the paging RECORD is one whole KV block (`GroupLayout::
21//! block_bytes()` = `2·num_kv_heads·group_stride`) — exactly the fixed-size
22//! record `atlas_tier::Residency` demands, one contiguous blob at one pointer
23//! on both ends, and 1 control RTT per block instead of `2·num_kv_heads`.
24//! Keys fold the per-model fingerprint + full layout identity + a per-client
25//! salt (see [`ns`]); `PagingKind::KV` in the handshake plus the
26//! [`ns::KV_DOMAIN`] fold domain-separate KV from SSM.
27//!
28//! FLAG OFF (`ATLAS_KV_PAGING` unset/0) the selection helper returns the raw
29//! one-sided `RdmaKvBackend` — identical data plane (v2 RAW handshake since
30//! the v2 handshake), so any regression bisects on this single flag.
31
32pub mod ns;
33
34#[cfg(all(feature = "cuda", atlas_rdma_verbs))]
35mod backend;
36#[cfg(all(feature = "cuda", atlas_rdma_verbs))]
37mod connect;
38
39#[cfg(all(feature = "cuda", atlas_rdma_verbs))]
40pub use backend::{KvPagingBackend, KvPagingConnect};
41#[cfg(all(feature = "cuda", atlas_rdma_verbs))]
42pub use connect::connect_kv_peer_backend;
43
44/// The hard-error a KV paging GET miss maps to. `StorageBackend::read` has no
45/// miss channel and an evicted KV block is UNRECOVERABLE without recomputing
46/// the prefix (unlike SSM snapshots, which recompute on miss by design) — so
47/// ST_MISS is corruption-equivalent and must fail loudly, naming the peer
48/// config that makes the KV kind miss-proof.
49pub fn kv_miss_error(layer: u32, block: u32) -> anyhow::Error {
50 anyhow::anyhow!(
51 "kv-paging: block (layer {layer}, disk block {block}) is not on the peer — an \
52 evicted KV block is unrecoverable (silent KV loss would corrupt long-context \
53 output). Run the peer with --swap-cap-gb-kv 0 (unbounded KV disk) and size \
54 --max-blade-gb / ATLAS_KV_PAGING_ARENA_GB for the working set"
55 )
56}
57
58#[cfg(test)]
59mod isolation_tests;