mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-08-20 14:17:07 +00:00
* mount: discard a path-cache insert that raced a purge The Windows adapter's walk resolves a component with a Lookup RPC and inserts the result holding no lock, so a purge can land in between - and what the walk just resolved is then the very name the purge removed. Anything opening the old path concurrently with a rename repopulates the cache with the vacated name, which the next stat is served from for up to a second. The release path already guards its equivalent insert; the walk had nothing. The cache counts purges now. A resolve snapshots the generation before its lookups and insert discards the entry when any purge ran in between, parking the reference in the graveyard so the in-flight caller keeps a valid inode either way. Seen once in CI as TestRenameOverExisting failing with 'source survived the rename': every SeaweedFS layer is synchronous with the rename, but a background open of the source - an antivirus scan of the just-written file fits - can requalify the stale name through this window. The assertion also reports what stat returned now, and whether it persisted, so a recurrence indicts a specific layer instead of reading as a mystery. * mount: cover the path-cache discard by key, and let a discard rest Review follow-ups. The generation was global, so any purge between a walk's snapshot and its insert discarded the entry whatever its name - and an open retries resolve-then-steal only four times before failing with EIO, so sustained unrelated churn could fail opens of untouched paths. Purges are remembered by key now and only one that covers the inserted name discards it; past the remembered window the insert is discarded without a check, which only costs a retry. A discard that itself tripped the sweep also handed its own reference straight to forget while the walker was still using the inode. The graveyard holds two generations now, so an appended reference always survives the sweep of the call that appended it - which the displaced-entry and purge paths needed too. Also restores the original path-cache test suite this branch had overwritten instead of extended, and rewords the semantics-test failure so it no longer claims the source survived when stat returned a transient error. * mount: take an open's reference directly instead of stealing it back resolveAndSteal cached the final component only to steal it back, so an open depended on that insert surviving whatever purges raced it - four attempts and then EIO. The keyed purge window narrowed how often an insert is discarded, but past the window the discard is blind again, so the cliff had only moved. A cached entry is still stolen; anything else is now looked up directly, with the caller owning the reference from the start. No retry loop, and no way for churn - covered, unrelated or overflowing the window - to fail an open. Also covers the whole-cache purge: purge of the root with prefix set clears every entry, but the covers check tested for a '/'-prefixed key that a normalised key never has, so it covered no in-flight insert at all.