aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Unterwurzacher2016-06-08 22:39:35 +0200
committerJakob Unterwurzacher2016-06-09 22:21:00 +0200
commit5b1eed35eea57655b36be163f0aeadb55d89cf40 (patch)
tree5310c9d07daa7825d9ff26d3dd6add664bcacb17
parent37d824c9a875f71d6184b87794db533c77b0046a (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.
-rw-r--r--internal/fusefrontend/file.go15
-rw-r--r--internal/fusefrontend/fs_dir.go2
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)