diff options
| -rw-r--r-- | internal/fusefrontend/file.go | 14 | ||||
| -rw-r--r-- | internal/syscallcompat/eintr.go | 27 | 
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 +	}  } | 
