diff options
author | Jakob Unterwurzacher | 2016-06-08 22:39:35 +0200 |
---|---|---|
committer | Jakob Unterwurzacher | 2016-06-09 22:21:00 +0200 |
commit | 5b1eed35eea57655b36be163f0aeadb55d89cf40 (patch) | |
tree | 5310c9d07daa7825d9ff26d3dd6add664bcacb17 /internal | |
parent | 37d824c9a875f71d6184b87794db533c77b0046a (diff) |
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.
Diffstat (limited to 'internal')
-rw-r--r-- | internal/fusefrontend/file.go | 15 | ||||
-rw-r--r-- | internal/fusefrontend/fs_dir.go | 2 |
2 files changed, 14 insertions, 3 deletions
diff --git a/internal/fusefrontend/file.go b/internal/fusefrontend/file.go index 3fa5a48..62303df 100644 --- a/internal/fusefrontend/file.go +++ b/internal/fusefrontend/file.go @@ -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) } diff --git a/internal/fusefrontend/fs_dir.go b/internal/fusefrontend/fs_dir.go index 5fea438..e946087 100644 --- a/internal/fusefrontend/fs_dir.go +++ b/internal/fusefrontend/fs_dir.go @@ -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) |