Skip to content

Preserve attachment lifetime and native file semantics - #1

Merged
techartdev merged 33 commits into
mainfrom
feat/graceful-detach
Sep 12, 2026
Merged

techartdev merged 33 commits into
mainfrom
feat/graceful-detach

Conversation

@techartdev

@techartdev techartdev commented Sep 10, 2026 •

Copy link
Copy Markdown
Owner

Explicit detach now reports busy instead of retiring a drive while local applications hold files. Protocol v2 reports readiness, status and cleanup warnings; the parent retains a busy attachment for another explicit attempt.

Windows gates detach against open contexts. Volume flush attempts every writable descriptor and preserves the first failure; confirmed renames update related open paths and context drop closes remote handles. Linux/macOS use ordinary unmount without force or lazy flags. Linux negotiates shared mmap only when the kernel advertises support, while retaining ordinary direct I/O.

Validation:

  • Windows, Ubuntu and macOS 14 builds/tests pass at 30c4125 (run 34511425152).
  • Real WinFsp 2.1.25156 on a disposable Windows CI runner passes offset I/O above 4 GiB, flush/truncate, replacement saves, exact paged directory enumeration, rename/deletion, basic errors and capacity through ordinary Windows APIs. Shared cross-page mapped writes, lifetime after descriptor close, read-only and private maps pass with independently inspected backing files. A held file prevents detach; a second request after close removes the drive. The fixture uses a disposable local provider, without SSH credentials or user profiles.
  • Native Linux 6.8 acceptance through the core SFTP root passes file operations, replacement saves, directory rename with an open file, capacity, shared/private/read-only maps and busy detach, followed by confirmed disposable cleanup.
  • Lifecycle, Windows handle-gate, rename bookkeeping and volume-flush unit tests pass; Windows and Linux clippy pass.

Remaining release gates include desktop-created Windows SFTP mappings and Explorer/editor UI acceptance, real remote failure cases, modern macOS native runtime and concurrent remote-edit semantics. These checks do not establish database or VM-image compatibility. CI installs the pinned official WinFsp MSI only on its disposable runner after SHA-256 and signer checks; normal tests skip the opt-in native fixture.

Native failure acceptance also passes at 36464c5 (CI run 34512537189): write-through I/O/offline/timeout/read-only errors map to the expected Windows codes, source bytes stay unchanged, failed flush reports failure, unrelated I/O remains usable, and close/cleanup deletion warnings reach the parent. Failed deletion preserves the source. These injected provider errors do not substitute for real network-loss or remote disk-full acceptance.

At 1459801, CI run 34513391440 also passes actual Windows IPC-loss acceptance: cutting both parent pipes while a file is open makes the next write fail within ten seconds, preserves confirmed source bytes, exits the helper unsuccessfully and removes the drive letter. Unexpected lifecycle replies or connection loss now return failure exits on both Windows and FUSE. Actual SSH outages and abnormal native FUSE teardown remain separate verification gates; fuser's teardown fallback can use lazy/forced unmount, unlike normal explicit Detach.

The 1459801 Linux CI artifact also passes actual pipe-loss acceptance on Linux 6.8 as root, through the core SFTP provider: write and close return ENOTCONN with an open descriptor, confirmed source bytes remain unchanged, the helper exits with failure and mountinfo confirms removal. The disposable fixture and staged binary were verified removed. Modern macOS and actual SSH network outages remain separate checks; later non-root Linux results follow.

Setup diagnostics at 49c481a were checked by launching the helper without WinFsp: it completes the capability handshake, requests no filesystem operations and exits promptly with official runtime installation guidance.

Native directory rename coverage at e58d386 passes in CI run 34518237898, alongside all earlier Windows cases (32.21 seconds). Windows correctly rejects rename while a child file is open without damaging the source; closing the child permits rename while two directory aliases remain open, and both still return metadata. A rejected replacement preserves both trees. The expectation was checked against a separate NTFS baseline and Microsoft's MS-FSA rules; Windows does not use POSIX open-child rename semantics.

FUSE cursor recovery at 87a28c9 clears retired handles and buffered entries before reopening. Linux/macOS regressions cover failed close/reopen and invalid replies followed by a later seek; all platform jobs pass in CI run 34519068114. Its Linux artifact passes native rewind of the same directory descriptor before and after rename through the core SFTP provider, plus the prior I/O, mmap and busy-detach checks. Fixture/mount and staged binary cleanup were independently verified. Native injected reopen failure remains a separate check.

Unprivileged Linux acceptance now also passes at 87a28c9 on Linux 6.8 (UID 65534, installed fusermount3): file operations, directory rewind/rename, mmap, busy detach and ordinary unmount. A separate open-file pipe-loss run returns ENOTCONN, preserves confirmed backing bytes, exits with failure and removes the mount before any privileged recovery. Source bytes and removal of both disposable trees/mounts and the staged binary were independently verified. No accounts or FUSE configuration changed.

Native volume-wide flush passes at 9c4fbe1 in CI run 34521265017 (full native suite: 28.88 seconds). FlushFileBuffers on the actual disposable volume visits all three writable files despite a provider flush failure and returns ERROR_IO_DEVICE. Clearing the injected fault permits a successful subsequent flush with independently verified backing bytes. All platform jobs and prior native checks pass.

Inode lifetime regressions pass at 558d1f2 in CI run 34521983619, covering both kernel-forget/open-release orders and recreated-path isolation. Its Linux artifact passes native Linux 6.8 acceptance as UID 65534 through the core SFTP provider: unlink/recreate yields a distinct inode, the old descriptor reads/writes its original object, and closing it leaves the replacement intact. Source-owner inspection verifies replacement bytes. Prior directory rewind, mmap, busy detach and ordinary unmount checks pass; fixture, mount and staged binary cleanup were independently verified. All platform jobs and native Windows acceptance pass (29.24 seconds).

Windows read-only projection at 447b1c3 passes native CI 34523633220 (37.15 seconds), all platform regressions and clippy. Existing regular-file read-only set/clear reaches provider permissions, blocks new writes/deletion, and unsupported combined DOS-attribute requests fail without partial mutation. Attribute-only opens use a remote read handle; the matching core separately passes live SFTP metadata set/clear with read-only-root and truncation enforcement. No protocol fields or required provider methods were added. This projects ordinary Unix permission bits; DOS flag persistence, creation/overwrite attributes and creation/change timestamps are not claimed complete.

Timestamp handling at 3f66501 passes native CI 34524595837 (29.14 seconds), all platform builds/tests and Windows clippy. Unavailable creation/change times are no longer synthesized from modification time. Supported access/modification times round-trip; unsupported mixed requests fail before modifying timestamps or permissions. A separate live SFTP probe verifies single-field timestamp preservation and out-of-range rejection without partial changes. Creation/change-time storage is unavailable in the present contract; explicit changes report unsupported. Creation/overwrite attributes remain a separate review item.

@techartdev
techartdev marked this pull request as ready for review September 10, 2026 16:31
@techartdev techartdev changed the title Preserve busy attachments during graceful detach Preserve attachment lifetime and Windows open-file state Sep 10, 2026
@techartdev techartdev changed the title Preserve attachment lifetime and Windows open-file state Preserve attachment lifetime and native file semantics Sep 10, 2026
@techartdev
techartdev merged commit 300e77b into main Sep 12, 2026
6 checks passed
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