Skip to content

land: storage-cross-volume - #504

Open
aft-alfonso[bot] wants to merge 3 commits into
mainfrom
land/storage-cross-volume
Open

aft-alfonso[bot] wants to merge 3 commits into
mainfrom
land/storage-cross-volume

Conversation

@aft-alfonso

@aft-alfonso aft-alfonso Bot commented Oct 17, 2026 •

Copy link
Copy Markdown

Accepted agent delivery; branch-keyed search descriptor included.


Summary by cubic

Makes storage operations work when storage folders live on a separate volume, falling back to copies when a rename would cross devices instead of failing.

Cross-volume moves

  • New cross_volume::move_path tries a plain rename first and, on a cross-device error, copies the tree, publishes it under the destination name, and removes the source; a failed copy leaves the source untouched.
  • Legacy folder repairs (root backups, bash tasks, filter folders, state files) now use this fallback and keep the source in place with a warning when the move still fails.
  • Callgraph orphan sweeping now reaches another key's build temporaries when the callgraph folder is a mount point, instead of skipping the whole folder.
  • A simulated-volume test seam makes CI reproduce EXDEV errors without a second filesystem.

Retention and migration preflight

  • Retention retires a mount-point cache folder by emptying it on its own volume instead of renaming it into the domain trash; the emptied mount point counts as gone on later passes.
  • Storage migration preflight now checks free space on each destination volume (the target root plus any cache folder on another volume), charging each volume only the bytes headed for it.

Written for commit a7bb59f. Summary will update on new commits.

View guided diff Turn on auto-fix

RetriggerView in GreptileConfidence Score: 4/5

Fix mounted-cache cleanup recovery before merging so interrupted deletes do not leave files permanently stranded.

Findings

  1. P1 Interrupted cleanup strands cache files ▶
  2. P2 Slow deletes block storage work ▶

Summary

Adds cross-volume moves for legacy storage repair and checks migration space on each destination volume.

  • Legacy storage repairs can move data across volumes.
  • Storage migration checks free space on every destination volume.
  • Retention empties mounted cache folders without moving the mount.
  • The callgraph sweep scans keys on a separately mounted volume.
  • The search benchmark records this change as engine-unwired.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Legacy storage repair] --> B[Try rename]
  B -->|Success| C[Use destination]
  B -->|Cross-volume error| D[Copy into destination staging path]
  D --> E[Sync and publish copy]
  E --> F[Remove source]
  F --> C
  D -->|Copy fails| G[Keep source and report failure]
Loading

Reviews (1) · Last reviewed commit: "release notes and search-quality descrip..." · Reviewed by Greptile

ualtinok and others added 3 commits October 18, 2026 00:42
…unt-point retire, per-volume preflight)

Co-authored-by: alfonso-aft <289616620+alfonso-aft@users.noreply.github.com>
Co-authored-by: alfonso-aft <289616620+alfonso-aft@users.noreply.github.com>
Co-authored-by: alfonso-aft <289616620+alfonso-aft@users.noreply.github.com>
Comment on lines +1165 to +1169
fn emptied_mount_point(cache: &Path) -> bool {
crate::cross_volume::is_mount_point(cache).unwrap_or(false)
&& fs::read_dir(cache).is_ok_and(|mut entries| {
entries.all(|entry| entry.is_ok_and(|entry| entry.file_name() == ".retention-trash"))
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Interrupted cleanup strands cache files

If the daemon exits after moving every entry into the mount-local .retention-trash, or deleting that trash fails, emptied_mount_point still returns true. Later passes skip the cache, and reap_retired only checks trash under the domain folder. The leftover data is never reclaimed.

Retry or reap mount-local trash before treating the mount as empty, and add an interrupted-cleanup test.

}
crate::cross_volume::rename(&entry.path(), &retired.join(entry.file_name()))?;
}
fs::remove_dir_all(&trash)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Slow deletes block storage work

retire_mount_point_contents deletes the full tree before returning. Its caller still holds retention/sweep.lock and the guard from filesystem_guard, so a slow mounted volume can block new binds, pins, and SQLite file work throughout deletion. The entry limit does not bound how long disk operations take.

Leave the slow delete to a background worker, as the normal retirement path does.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

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.

1 participant