#[non_exhaustive]pub struct CacheDir { /* private fields */ }Expand description
Handle to the kernel image cache directory.
Implementations§
Source§impl CacheDir
impl CacheDir
Sourcepub fn default_root() -> Result<PathBuf>
pub fn default_root() -> Result<PathBuf>
Resolve the default cache root path without side effects.
Sourcepub fn lookup(&self, cache_key: &str) -> Option<CacheEntry>
pub fn lookup(&self, cache_key: &str) -> Option<CacheEntry>
Look up a cached kernel by cache key.
On hit, emits a tracing::warn! via
warn_if_unstripped_vmlinux when the cached entry took the
strip-failure fallback (see should_warn_unstripped for the
exact predicate). Caller-facing call sites want the warning;
internal call sites that look the entry up only to compare
against caller intent (notably Self::store’s in-lock
recheck) use Self::lookup_silent to avoid double-emitting
the same warning the caller will see on its next lookup.
Sourcepub fn list(&self) -> Result<Vec<ListedEntry>>
pub fn list(&self) -> Result<Vec<ListedEntry>>
List all cached kernel entries, sorted by build time (newest first).
Sourcepub fn store(
&self,
cache_key: &str,
artifacts: &CacheArtifacts<'_>,
metadata: &KernelMetadata,
) -> Result<CacheEntry>
pub fn store( &self, cache_key: &str, artifacts: &CacheArtifacts<'_>, metadata: &KernelMetadata, ) -> Result<CacheEntry>
Store a kernel image (and optional vmlinux sidecar) in the
cache under cache_key. Atomic install via temp directory +
renameat2(RENAME_EXCHANGE), so a concurrent reader never
observes a partially-written entry.
§Steps (in order)
- Validate inputs.
validate_cache_keyrejects.., slashes, NUL, leading-dot keys (theTMP_DIR_PREFIXreservation plus any other dotfile-shaped key, sincelist()skips every dotfile child);validate_filenamerejects path-separator characters in the image basename. Invalid input fails before any I/O. - Acquire the per-key store lock.
LOCK_EXon<root>/.locks/<cache_key>.lock. Timeout defaults toSTORE_EXCLUSIVE_LOCK_DEFAULT_TIMEOUT(5 minutes) and can be overridden viaSTORE_EXCLUSIVE_LOCK_TIMEOUT_ENVfor environments where a slow vmlinux strip stacks many contending peers behind the head writer. The lock excludes other writers for the same key while letting readers and writers for unrelated keys proceed. Timeout produces an error rather than blocking forever — a hung writer cannot indefinitely block a fresh rebuild attempt. - Double-checked re-lookup inside the lock. After
acquiring
LOCK_EX, re-runSelf::lookup_silentforcache_key. When N peers race to publish the same key they all miss the pre-lock cache check, queue onLOCK_EX, and serialise behind the head writer. Without this recheck, every peer re-runs the full copy + strip + publish steps in series even though the head writer’s output already satisfies them. The recheck early-returns when the existing cached entry’s content-defining metadata fields (cache_content_matches— config_hash, ktstr_kconfig_hash, extra_kconfig_hash, has_vmlinux) match the caller’s intent for this publish, so only the head writer pays the strip/copy/rename cost. Cache-relevant differences (a fresh kconfig hash, a different vmlinux presence) bypass the early-return and proceed to a real overwrite-publish. Cache-irrelevant differences (a freshbuilt_attimestamp, a differentversiondisplay string) trigger the early-return — the on-disk bytes the overwrite would write are byte-equivalent to what’s already cached, so the publish is redundant. - Stage into a temp directory.
<root>/.tmp-<key>-<pid>is created (or pruned and recreated if a previous attempt by the same PID exists), withTmpDirGuardenrolling the path for cleanup on any subsequent error. A best-effortclean_orphaned_tmp_dirspass also runs here so dead sibling temp directories from crashed PIDs are GC’d before we add another one. - Copy the boot image.
metadata.image_namelands attmp/<image_name>viareflink::reflink_or_copy(copy-on-write when the cache filesystem supports it, else a plain byte copy). - Strip and copy vmlinux (if supplied). When
artifacts.vmlinuxisSome,strip_vmlinux_debugruns the two-stage strip pipeline and the result is written totmp/vmlinux. Strip-fallback rationale: if the strip pipeline returns an error (e.g. an unrecognised ELF layout from a future toolchain or an exotic config), the write does NOT abort — it falls back to copying the raw unstripped vmlinux and recordsvmlinux_stripped: falsein metadata. The cache trades a much larger on-disk payload for “still usable for monitoring/probes,” andcargo ktstr kernel list --jsonexposes thevmlinux_strippedfield so operators can spot entries that need rebuilding once the strip-failure root cause is fixed. A hard failure here would be worse: it would effectively brick the cache for that build. - Write
metadata.json. A pretty-printed serde dump ofKernelMetadata(withhas_vmlinuxandvmlinux_strippedset from step 6) attmp/metadata.json. Pretty-print is intentional — operators inspect this file directly when debugging cache state. - Atomic publish.
fs::rename(tmp → final)iffinaldoes not exist; otherwiseatomic_swap_dirsusesrenameat2(RENAME_EXCHANGE)to swap the two directories in a single atomic syscall. Either way, no reader observes a partial entry; the swap path also cleans up the now-stale prior version under the temp name.
Sourcepub fn clean_all(&self) -> Result<usize>
pub fn clean_all(&self) -> Result<usize>
Remove every cached entry. Returns the number of entries
removed. Preserves the .locks/ subdirectory.
Sourcepub fn clean_keep(&self, keep: usize) -> Result<usize>
pub fn clean_keep(&self, keep: usize) -> Result<usize>
Remove every cached entry except the keep most recent ones
(by built_at timestamp). Preserves the .locks/
subdirectory.
Acquire LOCK_SH on the cache-entry lockfile.
Sourcepub fn acquire_exclusive_lock_blocking(
&self,
cache_key: &str,
timeout: Duration,
) -> Result<ExclusiveLockGuard>
pub fn acquire_exclusive_lock_blocking( &self, cache_key: &str, timeout: Duration, ) -> Result<ExclusiveLockGuard>
Acquire LOCK_EX on the cache-entry lockfile, blocking up
to timeout. On timeout, the error message surfaces the
STORE_EXCLUSIVE_LOCK_TIMEOUT_ENV override so an operator
hitting a contended store() discovers the env-var
remediation without reading the docs.
Sourcepub fn try_acquire_exclusive_lock(
&self,
cache_key: &str,
) -> Result<ExclusiveLockGuard>
pub fn try_acquire_exclusive_lock( &self, cache_key: &str, ) -> Result<ExclusiveLockGuard>
Non-blocking LOCK_EX attempt on the cache-entry lockfile.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for CacheDir
impl RefUnwindSafe for CacheDir
impl Send for CacheDir
impl Sync for CacheDir
impl Unpin for CacheDir
impl UnwindSafe for CacheDir
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more