Skip to content

Add FileSystemHost.Notify for kernel cache invalidation#1

Merged
hooyao merged 2 commits into
mainfrom
feat/notify-api
May 3, 2026
Merged

Add FileSystemHost.Notify for kernel cache invalidation#1
hooyao merged 2 commits into
mainfrom
feat/notify-api

Conversation

@hooyao
Copy link
Copy Markdown
Owner

@hooyao hooyao commented May 3, 2026

Summary

  • Adds FspFileSystemNotify P/Invoke + FspFsctlNotifyInfo struct (12-byte, matches the static_assert in winfsp/fsctl.h)
  • New FileNotify constants class (Change* filters, Action* actions) — values cross-checked against WinNT.h
  • New public FileSystemHost.Notify(filter, action, fileName) — stack-allocated buffer (≤ 4 KB), ArrayPool fallback for longer paths, returns NTSTATUS unchanged
  • Auto-uppercases the path in place when the host is case-insensitive (the WinFsp driver's cache key is the upper-cased form — verified against the fuse.c reference implementation)
  • Adds FileOperationInfo.FileName so callbacks like OverwriteFile (whose IFileSystem signature has no path parameter) can issue Notify without storing the path on Context themselves
  • 5 new NotifyTests (struct size, packing, case sensitivity, oversized rejection, constants)

Why

User-mode file systems built on this binding could not invalidate the WinFsp kernel FileInfo cache after path-mutating operations — because the actual FspFileSystemNotify API was not exposed in the binding (only the unused Begin/End framing was). Concrete failure: leveldb's atomic-rename pattern reads zero bytes from a freshly-renamed CURRENT file when FileInfoTimeout > 0, breaking every Chromium leveldb component (Local Storage, GCM Store, Sync Data, Site Characteristics Database, …).

The downstream RamDrive change that consumes this API is at https://github.com/hooyao/RamDrive (PR will follow after this one merges and the package is published to NuGet).

Version bumped to 0.1.2-pre.2 and tagged v0.1.2-pre.2.

Test plan

  • dotnet test tests/WinFsp.Native.Tests --filter NotifyTests — 5/5 pass
  • Existing FileSystemHostTests still pass (no regression in TestMemFs fixture)
  • dotnet pack -c Release -o ./artifacts produces WinFsp.Native.0.1.2-pre.2.nupkg
  • Local consumer (RamDrive) builds and passes its 28-test integration suite against this package

🤖 Generated with Claude Code

hooyao and others added 2 commits May 3, 2026 12:42
Adds FspFileSystemNotify P/Invoke + FspFsctlNotifyInfo struct + FileNotify
constants + public FileSystemHost.Notify(filter, action, fileName) so user-mode
file systems can invalidate the WinFsp kernel FileInfo cache after path-mutating
operations (rename, delete, overwrite, create, set-size, set-attrs).

Required for correctness when FileInfoTimeout is large or uint.MaxValue —
otherwise the kernel can serve stale Open/Read results from cache without
consulting user-mode. Concrete failure: leveldb's atomic-rename pattern reads
zero bytes from a freshly-renamed CURRENT file, breaking every Chromium leveldb
component (Local Storage, GCM Store, Sync Data, ...).

Also adds FileOperationInfo.FileName so callbacks like OverwriteFile (whose
IFileSystem signature does not include a path parameter) can issue Notify
without storing the path on Context themselves.

Bumped to 0.1.2-pre.2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
xUnit's IClassFixture<T> creates one fixture instance per test class.
NotifyTests + SyncTests both used IClassFixture<SyncFixture>, so xUnit
instantiated SyncFixture twice in the same process — the second mount
collided on the same UNC prefix and failed STATUS_OBJECT_NAME_COLLISION
(0x80070050).

Switching to [CollectionDefinition] / [Collection("Sync")] makes the fixture
shared across both classes — one mount, run all tests, one unmount.
The same pattern is applied to SyncCompleted and TrueAsync for consistency.

Did not surface locally because NotifyTests was usually filtered to run
alone; on CI the full suite runs and exposed the collision.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@hooyao hooyao merged commit 1b18918 into main May 3, 2026
2 checks passed
@hooyao hooyao deleted the feat/notify-api branch May 3, 2026 06:06
hooyao added a commit that referenced this pull request May 3, 2026
v0.1.2-pre.2 tag was pushed before PR review, and the early CI failure
(fixture collision now fixed in #1) prevented the release workflow from
publishing. Cutting a fresh pre-release from merged main so the published
package corresponds to a green commit.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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