fusefrontend: Utimens: convert ENOENT to EBADF
If /proc/self/fd/X did not exist, the actual error is that the file descriptor was invalid. go-fuse's pathfs prefers using an open fd even for path-based operations but does not take any locks to prevent the fd from being closed. Instead, it retries the operation by path if it get EBADF. So this change allows the retry logic to work correctly. This fixes the error rsync: failed to set times on "/tmp/ping.Kgw.mnt/linux-3.0/[...]/.dvb_demux.c.N7YlEM": No such file or directory (2) that was triggered by pingpong-rsync.bash.
This commit is contained in:
parent
37d824c9a8
commit
5b1eed35ee
@ -286,7 +286,9 @@ func (f *file) Write(data []byte, off int64) (uint32, fuse.Status) {
|
||||
f.fdLock.RLock()
|
||||
defer f.fdLock.RUnlock()
|
||||
if f.released {
|
||||
// The file descriptor has been closed concurrently.
|
||||
// The file descriptor has been closed concurrently, which also means
|
||||
// the wlock has been freed. Exit here so we don't crash trying to access
|
||||
// it.
|
||||
toggledlog.Warn.Printf("ino%d fh%d: Write on released file", f.ino, f.intFd())
|
||||
return 0, fuse.EBADF
|
||||
}
|
||||
@ -514,5 +516,14 @@ func (f *file) Utimens(a *time.Time, m *time.Time) fuse.Status {
|
||||
}
|
||||
|
||||
fn := fmt.Sprintf("/proc/self/fd/%d", f.fd.Fd())
|
||||
return fuse.ToStatus(syscall.UtimesNano(fn, ts))
|
||||
err := syscall.UtimesNano(fn, ts)
|
||||
if err != nil {
|
||||
toggledlog.Debug.Printf("UtimesNano on %q failed: %v", fn, err)
|
||||
}
|
||||
if err == syscall.ENOENT {
|
||||
// If /proc/self/fd/X did not exist, the actual error is that the file
|
||||
// descriptor was invalid.
|
||||
return fuse.EBADF
|
||||
}
|
||||
return fuse.ToStatus(err)
|
||||
}
|
||||
|
@ -190,7 +190,7 @@ func (fs *FS) Rmdir(path string, context *fuse.Context) (code fuse.Status) {
|
||||
}
|
||||
return fuse.ToStatus(err)
|
||||
}
|
||||
// Delete "gocryptfs.diriv.rmdir.INODENUMBER"
|
||||
// Delete "gocryptfs.diriv.rmdir.XYZ"
|
||||
err = syscall.Unlinkat(int(parentDirFd.Fd()), tmpName)
|
||||
if err != nil {
|
||||
toggledlog.Warn.Printf("Rmdir: Could not clean up %s: %v", tmpName, err)
|
||||
|
Loading…
Reference in New Issue
Block a user