Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion control/crates/layerfs-sandbox/src/files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ pub fn workspaces(directory: &Path) -> Result<Vec<(PathBuf, WorkspaceRecord)>> {
Ok(found)
}
/// A Workspace record's token: its id (64 hex digits) and namespace.
fn token_of(value: &WorkspaceRecord) -> Result<layerfs_bridge::control::WorkspaceToken> {
pub fn token_of(value: &WorkspaceRecord) -> Result<layerfs_bridge::control::WorkspaceToken> {
let id = helpers::required(value.id(), "id")?;
let bytes: Vec<u8> = (0..id.len())
.step_by(2)
Expand Down
13 changes: 13 additions & 0 deletions control/crates/layerfs-sandbox/src/unmount_guard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,19 @@ fn find_in(directory: &std::path::Path, path: &str) -> Result<Option<SdkValue>,
}
Ok(None)
}
/// The token of the Workspace recorded at `path`, read from its record: the
/// live mount table no longer answers a Retained Workspace.
pub fn token(state: &SandboxState, path: &str) -> Result<WorkspaceToken, SdkRefusal> {
for (_, record) in discovery::workspaces(&state.directory)? {
if record.path() == Some(path) {
return discovery::token_of(&record);
}
}
Err(refused(
"NotMounted",
format!("{}:{path} is not mounted", state.id),
))
}
/// Closing a running Sandbox may not race a registered terminal operation.
pub fn check_all(state: &SandboxState) -> Result<Vec<String>, SdkRefusal> {
let mut recoverable = Vec::new();
Expand Down
18 changes: 14 additions & 4 deletions control/crates/layerfs-sandbox/src/workspace/serve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,12 +259,22 @@ pub fn unmount(host: &Host, path: Option<&str>, discard: bool, force: bool) -> O
let guard = layerfs_store::project::discovery::guard(&state.directory)?;
// Another process may have registered while this call waited for the
// short admission section. Check again before sending anything.
if let Some(value) = crate::unmount_guard::find(&state, path)? {
if !crate::unmount_guard::retry(&value) {
let retrying = match crate::unmount_guard::find(&state, path)? {
Some(value) if !crate::unmount_guard::retry(&value) => {
return crate::unmount_guard::repeat(&value);
}
}
let token = state.token(path)?;
Some(_) => true,
None => false,
};
// A retryable Retained Workspace's live mount table no longer answers:
// read its token from the workspace record (as `sandbox.close` does)
// instead of re-running `unmount_guard::check`, which would re-report
// the Retained custody before the retry ever reaches the daemon (#538).
let token = if retrying {
crate::unmount_guard::token(&state, path)?
} else {
state.token(path)?
};
// its running commands (D-10): `Busy`, or with `force` cancelled first
let wsid = layerfs_bridge::sdk_values::hex(&token.workspace.to_bytes());
let unreached = &mut crate::exec::cancel::unreached;
Expand Down
Loading