aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal/fusefrontend/file.go14
-rw-r--r--internal/syscallcompat/eintr.go27
2 files changed, 26 insertions, 15 deletions
diff --git a/internal/fusefrontend/file.go b/internal/fusefrontend/file.go
index 0367705..98e5802 100644
--- a/internal/fusefrontend/file.go
+++ b/internal/fusefrontend/file.go
@@ -391,9 +391,9 @@ func (f *File) Release(ctx context.Context) syscall.Errno {
}
f.released = true
openfiletable.Unregister(f.qIno)
- f.fd.Close()
+ err := f.fd.Close()
f.fdLock.Unlock()
- return 0
+ return fs.ToErrno(err)
}
// Flush - FUSE call
@@ -401,15 +401,7 @@ func (f *File) Flush(ctx context.Context) syscall.Errno {
f.fdLock.RLock()
defer f.fdLock.RUnlock()
- // Since Flush() may be called for each dup'd fd, we don't
- // want to really close the file, we just want to flush. This
- // is achieved by closing a dup'd fd.
- newFd, err := syscall.Dup(f.intFd())
-
- if err != nil {
- return fs.ToErrno(err)
- }
- err = syscallcompat.Close(newFd)
+ err := syscallcompat.Flush(f.intFd())
return fs.ToErrno(err)
}
diff --git a/internal/syscallcompat/eintr.go b/internal/syscallcompat/eintr.go
index 122af9b..f0a82f5 100644
--- a/internal/syscallcompat/eintr.go
+++ b/internal/syscallcompat/eintr.go
@@ -11,6 +11,9 @@ import (
//
// This is needed because CIFS throws lots of EINTR errors:
// https://github.com/rfjakob/gocryptfs/issues/483
+//
+// Don't use retryEINTR() with syscall.Close()!
+// See https://code.google.com/p/chromium/issues/detail?id=269623 .
func retryEINTR(op func() error) error {
for {
err := op()
@@ -40,9 +43,25 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
return fd, err
}
-// Close wraps syscall.Close.
+// Flush is a helper for the FUSE command FLUSH.
// Retries on EINTR.
-func Close(fd int) (err error) {
- err = retryEINTR(func() error { return syscall.Close(fd) })
- return err
+func Flush(fd int) error {
+ for {
+ // Flushing is achieved by closing a dup'd fd.
+ newFd, err := syscall.Dup(fd)
+ if err == syscall.EINTR {
+ continue
+ }
+ if err != nil {
+ return err
+ }
+ err = syscall.Close(newFd)
+ // Even if we get EINTR here, newFd is dead - see
+ // https://code.google.com/p/chromium/issues/detail?id=269623 .
+ // We have to make a new one with Dup(), so continue at the top.
+ if err == syscall.EINTR {
+ continue
+ }
+ return err
+ }
}