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
38 changes: 38 additions & 0 deletions core/docs/architecture/76-native-mount-session.md
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,44 @@ terminal service fence before the second drain. A failed or short abort reports
`Abort` with its original errno or byte count; later drain, Revoke and Close
failures retain the recorded abort effects in `TeardownCustody.forced`.

### Observing the abort path

A traced Unmount that takes that path reports it beside the ordinary reply, in
the daemon's `unmount` telemetry section of the existing `Observed` envelope
(issue #2). The reply itself is unchanged: success still answers `Unmounted`,
and a stop keeps its `TeardownCustody`. The section's stable keys are:

| Field | Meaning |
| --- | --- |
| `stage` | The boundary the unmount was at: `Join` when the stalled drain was ended by the abort, `Abort` when the one write was short or failed, and `Revoke` or `Close` when a later step stopped with the abort recorded |
| `abort` | The connection's single abort write: `Written`, `Short` or `Failed` |
| `bytes` | The count of a `Short` write only |
| `errno` | The original `Failed` write errno only |
| `detached` | Kernel detach was already known when the abort was made |
| `loops_exited`, `loops_joined` | Receive loops exited and joined, as observed at that stop or completion |
| `active`, `retained` | Request owner counts at the same observation |
| `waited_ms` | Milliseconds from the start of the connection drain to the end of the abort path |

An unmount that never stalled carries no such section, and no normal or forced
teardown carries one otherwise. The same fields are written once to stderr as
a `LAYERFS_DAEMON_UNMOUNT_ABORT <field>=<value>…` line when the abort path
ends, traced or not; it is one diagnostic line per abort, never per-request
logging. That line's `stage` is therefore the abort path's own (`Join`, or
`Abort` for a short or failed write), while a later `Revoke` or `Close` stop
appears in the retained entry's section for the reply that reports it.
Aggregating these facts in a Host view belongs to the
[dsh-layerfs](https://github.com/Ephemeral-AI-Lab/dsh-layerfs) follow-up, outside
this repository.

A retained Revoke or Close stop keeps that observation in its entry, so the
traced reply that later reports the stop's custody carries the same section at
the later boundary. `layerfs-api/tests/unmount_observability.rs` covers both
forms: the completed abort path through the actual daemon executable, and the
retained stop through the in-process service, where the entry's own owner can
be poisoned or closed. That target mounts a Workspace, so `tools/ci_tests.py`
lists it with the SDK mount targets: the fast lane leaves it out and the
nightly mount lane runs it in its own container with `/dev/fuse`.

## Forced unmount

[`ForceUnmount`](80-forced-teardown.md) takes the session out of the entry the
Expand Down
21 changes: 21 additions & 0 deletions core/docs/architecture/80-forced-teardown.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,27 @@ A later normal or forced unmount returns the retained stage, detail and abort
facts unchanged. An unavailable control cannot be forced, and a consumed
control is never written again. Successful completion still replies `Unmounted`.

A traced normal unmount reports the path it took as the `unmount` telemetry
section of its reply, whether it completed or stopped: `stage` (`Join`,
`Abort`, `Revoke` or `Close`), `abort` (`Written`, `Short` or `Failed`), the
short write's `bytes` or the failed write's `errno`, `detached`,
`loops_exited`, `loops_joined`, `active`, `retained`, and `waited_ms` from the
stalled drain to the end of the abort path. The same fields form one
`LAYERFS_DAEMON_UNMOUNT_ABORT` stderr line, written when that path ends (traced
or not); a `Revoke` or `Close` stop that follows it is reported by the retained
entry's section, not by a second line. Both are observations of a normal
unmount only: a forced teardown already reports its `ForcedFacts` in the reply,
and neither envelope changes. The keys are described in
[the normal unmount](76-native-mount-session.md#observing-the-abort-path).
Aggregating them in a Host view is a
[dsh-layerfs](https://github.com/Ephemeral-AI-Lab/dsh-layerfs) follow-up,
outside this repository.

A retained `Revoke` or `Close` stop reports the same section through the
traced reply that reports its custody. Both forms are staged in-process
through the entry's own owner and are covered beside the completed path in
`layerfs-api/tests/unmount_observability.rs`.

`ForceUnmount` remains for a stalled custody that is still forceable (one
whose abort was not attempted) and for a live connection. It takes the session back and makes the
same sequence with two differences. Step 1 is `NativeSession::abort_detached`,
Expand Down
4 changes: 2 additions & 2 deletions core/docs/architecture/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -434,8 +434,8 @@ process-specific cancellation, and it supplies no filesystem drain evidence.
- [Native read observation and lookup custody](73-native-read-custody.md): atomic Workspace answer/count/read ownership, exact source association and bounded retirement; native Fuse integration remains R2.
- [Native directory sources and indexed cookies](74-native-directory-custody.md): exact directory owners, accepted-entry cookie publication, current parent relationships and bounded live cleanup; native kernel integration remains R2.
- [Native request dispatcher and direct ports](75-native-request-service.md): shared fixed workers, event-driven custody, actual Owner/Store adapters and Linux read callbacks with complete opcode accounting.
- [Native mount session, Ready and reversible unmount](76-native-mount-session.md): direct mount and session ownership, Attach/Locate/Ready records, reversible EBUSY probe, connection drain, drain-qualified revocation and Sandbox FUSE access; mutation is described in record 77, Commit in record 79 and forced unmount in record 80.
- [Forced teardown](80-forced-teardown.md): `ForceUnmount` admission order and typed refusals, one abort write, terminal fence, local drain and one plain detach, Revoke and Close, the forced facts kept with retained custody, and the limits (abort control availability, no exit from `Retained`, held Lifecycle slots).
- [Native mount session, Ready and reversible unmount](76-native-mount-session.md): direct mount and session ownership, Attach/Locate/Ready records, reversible EBUSY probe, connection drain, drain-qualified revocation and Sandbox FUSE access, and the traced abort-path observation of a normal unmount; mutation is described in record 77, Commit in record 79 and forced unmount in record 80.
- [Forced teardown](80-forced-teardown.md): `ForceUnmount` admission order and typed refusals, one abort write, terminal fence, local drain and one plain detach, Revoke and Close, the forced facts and traced observation kept with retained custody, and the limits (abort control availability, no exit from `Retained`, held Lifecycle slots).
- [Compare and merge](81-compare-and-merge.md): page-skipping root, binding and line differences, and the three-way merge of roots with conflict markers and `.lww` rules, built on theirs through `update_filesystem`.
- [One Commit per file write](85-commit-per-write-storage.md): what one Commit writes, why file content costs about its change (piece compare, content addressing, deltas, CDC), where the fixed per-Commit cost is and what F-027 removes.
- [Global SQLite Store](84-global-sqlite-store.md): the one global database: lifecycle, the fixed Disposable/WAL/OFF profile, schema, objects and packs, connections, transactions, reclamation and the rules that do not change.
Expand Down
Loading