mount: check the flush target after every lock acquisition

A flush whose name kept changing published to the name chosen before its
last lock wait. Check after each acquisition and return a retryable error
once the attempts run out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Chris LuandClaude Opus 5.5 committed 2026-11-13 03:15:50 -08:00
1 parent c851066f79
commit 93157e09b8
1 file changed
+11 -8
+11 -8
View File
@@ -206,21 +206,24 @@ func (wfs *WFS) doFlush(ctx context.Context, fh *FileHandle, uid, gid uint32, al
// needed here. The local fhLockTable lock below serializes within this mount.
func (wfs *WFS) flushMetadataToFiler(ctx context.Context, fh *FileHandle, dir, name string, uid, gid uint32) error {
fileFullPath, dir, name := wfs.flushTarget(fh, dir, name)
// Attribute acknowledgement and local retention must complete before a
// whole-entry flush can publish. Take this before the handle's active lock.
unlock := wfs.lockMetadataPublication(fileFullPath)
fhActiveLock := fh.wfs.fhLockTable.AcquireLock("doFlush", fh.fh, util.ExclusiveLock)
// An unlink or rename can land before the locks are held.
for attempt := 0; attempt < 3; attempt++ {
var unlock func()
var fhActiveLock *util.ActiveLock
// An unlink or rename can land while the flush waits for its locks.
for attempt := 0; ; attempt++ {
// Attribute acknowledgement and local retention must complete before a
// whole-entry flush can publish. Take this before the handle's active lock.
unlock = wfs.lockMetadataPublication(fileFullPath)
fhActiveLock = fh.wfs.fhLockTable.AcquireLock("doFlush", fh.fh, util.ExclusiveLock)
nowPath, nowDir, nowName := wfs.flushTarget(fh, dir, name)
if nowPath == fileFullPath && nowDir == dir && nowName == name {
break
}
fh.wfs.fhLockTable.ReleaseLock(fh.fh, fhActiveLock)
unlock()
if attempt == 3 {
return fmt.Errorf("flush %s: name changed while waiting for its locks, now %s", fileFullPath, nowPath)
}
fileFullPath, dir, name = nowPath, nowDir, nowName
unlock = wfs.lockMetadataPublication(fileFullPath)
fhActiveLock = fh.wfs.fhLockTable.AcquireLock("doFlush", fh.fh, util.ExclusiveLock)
}
defer func() {
fh.wfs.fhLockTable.ReleaseLock(fh.fh, fhActiveLock)