diff --git a/python/sglang/srt/mem_cache/hiradix_cache.py b/python/sglang/srt/mem_cache/hiradix_cache.py index d621d6cd6..f5fd7fc1a 100644 --- a/python/sglang/srt/mem_cache/hiradix_cache.py +++ b/python/sglang/srt/mem_cache/hiradix_cache.py @@ -1041,6 +1041,10 @@ class HiRadixCache(RadixCache): self.enable_storage = server_args.hicache_storage_backend is not None self.enable_storage_metrics = self.enable_storage and params.enable_metrics self.extra_metric_labels = server_args.extra_metric_labels + # CP L3 durable floor (disk tier): own content-addressed path, NOT enable_storage. Built on the + # pooled shared-L2 (server_args validation already enforced the prerequisites + mutual exclusion). + self.enable_cp_l3 = bool(getattr(server_args, "enable_cp_l3", False)) and self._uses_cp_hicache + self.cp_l3_store = None # constructed after the host pool + allocator (slab accessors need them) ( extra_config, @@ -5591,8 +5595,11 @@ class HiRadixCache(RadixCache): self._update_leaf_status(node) self._update_leaf_status(new_node) - # Compute hash_value if storage or kv events are enabled - if self.enable_storage or self.enable_kv_cache_events: + # Compute hash_value if storage or kv events are enabled, or for the CP L3 disk tier (the + # per-page content hash is L3's key). Clean-boot only (default-off+additive): a fresh process + # with --enable-cp-l3 computes the unbroken parent-chained hash from the root; flipping it at + # runtime would leave pre-existing nodes None-seeded (R1 HIGH-3). + if self.enable_storage or self.enable_kv_cache_events or self.enable_cp_l3: new_node.hash_value = compute_node_hash_values(new_node, self.page_size) # Emit BlockStored so the router indexes this block. diff --git a/python/sglang/srt/server_args.py b/python/sglang/srt/server_args.py index f4626cb57..ab8583604 100644 --- a/python/sglang/srt/server_args.py +++ b/python/sglang/srt/server_args.py @@ -597,6 +597,10 @@ class ServerArgs: cp_shared_l2_hugetlbfs_dir: str = "/mnt/huge_2m" cp_shared_l2_slab_size_gb: int = 0 cp_shared_l2_numa_policy: str = "interleave_2m" + # L3 durable floor (disk tier), built on the pooled shared-L2. Its own content-addressed path — + # NOT the mainline hicache_storage_backend page-op path (which stays disabled under CP). + enable_cp_l3: bool = False + cp_l3_config: Optional[str] = None # Hierarchical sparse attention enable_hisparse: bool = False @@ -1000,6 +1004,19 @@ class ServerArgs: "hicache_storage_backend in the host-only CP HiCache stage. " "Disable hicache_storage_backend or disable CP shared KV." ) + if self.enable_cp_l3: + # L3 is a distinct CP content-addressed disk tier, NOT the mainline storage page-op path + # (which stays off under CP). The 6 CP storage forbids gate on hicache_storage_backend and + # correctly never fire here. One assert keeps the two paths mutually exclusive. + assert self.hicache_storage_backend is None, ( + "enable_cp_l3 is mutually exclusive with hicache_storage_backend: L3 uses its own " + "CpL3Store path, not the mainline storage backend. Unset --hicache-storage-backend." + ) + assert self.enable_cp_shared_physical_l2_hicache, ( + "enable_cp_l3 requires --enable-cp-shared-physical-l2-hicache (L3 spills/reloads the " + "pooled shared-L2 objects)." + ) + assert self.cp_l3_config, "enable_cp_l3 requires --cp-l3-config ." assert not ( self.enable_nsa_prefill_cp_shared_kv and envs.SGLANG_REQ_WAITING_TIMEOUT.get() > 0 @@ -5661,6 +5678,26 @@ class ServerArgs: "strict_local, round_robin." ), ) + parser.add_argument( + "--enable-cp-l3", + action="store_true", + default=ServerArgs.enable_cp_l3, + help=( + "Enable the CP HiCache L3 durable floor (disk tier) on top of the pooled shared-L2. " + "Content-addressed, per-rank-by-owner spill/reload. Requires " + "--enable-cp-shared-physical-l2-hicache and --cp-l3-config; mutually exclusive with " + "--hicache-storage-backend." + ), + ) + parser.add_argument( + "--cp-l3-config", + type=str, + default=ServerArgs.cp_l3_config, + help=( + "Path to the per-machine L3 config (TOML/JSON): disks (paths + budgets), rank->disk " + "mapping, backend, index location, PLP gate. See CpL3Config." + ), + ) # Hierarchical sparse attention parser.add_argument(