syscallcompat: don't retry Close()
After Close() returns, the fd is dead, even if we received EINTR. Don't retry, we could shoot down an unrelated fd that received the same fd number.
This commit is contained in:
parent
af4c1fb7a3
commit
ec3eaf0b87
@ -391,9 +391,9 @@ func (f *File) Release(ctx context.Context) syscall.Errno {
|
|||||||
}
|
}
|
||||||
f.released = true
|
f.released = true
|
||||||
openfiletable.Unregister(f.qIno)
|
openfiletable.Unregister(f.qIno)
|
||||||
f.fd.Close()
|
err := f.fd.Close()
|
||||||
f.fdLock.Unlock()
|
f.fdLock.Unlock()
|
||||||
return 0
|
return fs.ToErrno(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flush - FUSE call
|
// Flush - FUSE call
|
||||||
@ -401,15 +401,7 @@ func (f *File) Flush(ctx context.Context) syscall.Errno {
|
|||||||
f.fdLock.RLock()
|
f.fdLock.RLock()
|
||||||
defer f.fdLock.RUnlock()
|
defer f.fdLock.RUnlock()
|
||||||
|
|
||||||
// Since Flush() may be called for each dup'd fd, we don't
|
err := syscallcompat.Flush(f.intFd())
|
||||||
// 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)
|
|
||||||
return fs.ToErrno(err)
|
return fs.ToErrno(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,9 @@ import (
|
|||||||
//
|
//
|
||||||
// This is needed because CIFS throws lots of EINTR errors:
|
// This is needed because CIFS throws lots of EINTR errors:
|
||||||
// https://github.com/rfjakob/gocryptfs/issues/483
|
// 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 {
|
func retryEINTR(op func() error) error {
|
||||||
for {
|
for {
|
||||||
err := op()
|
err := op()
|
||||||
@ -40,9 +43,25 @@ func Open(path string, mode int, perm uint32) (fd int, err error) {
|
|||||||
return fd, err
|
return fd, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close wraps syscall.Close.
|
// Flush is a helper for the FUSE command FLUSH.
|
||||||
// Retries on EINTR.
|
// Retries on EINTR.
|
||||||
func Close(fd int) (err error) {
|
func Flush(fd int) error {
|
||||||
err = retryEINTR(func() error { return syscall.Close(fd) })
|
for {
|
||||||
return err
|
// 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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user