aboutsummaryrefslogtreecommitdiff
path: root/internal/syscallcompat/sys_common.go
diff options
context:
space:
mode:
authorJakob Unterwurzacher2020-10-14 00:35:16 +0200
committerJakob Unterwurzacher2020-10-14 00:35:16 +0200
commitaf4c1fb7a3f428ff704af22294ad955d05ed41dd (patch)
tree66bdf7480ff1dd82bf2653c2070871762f24d742 /internal/syscallcompat/sys_common.go
parent803fdf410bb57d34ef09357ec4924646978c20b5 (diff)
syscallcompat: retry ops on EINTR
Retry operations that have been shown to throw EINTR errors on CIFS. Todo: Solution for this pain in the back: warning: unix.Getdents returned errno 2 in the middle of data rm: cannot remove 'linux-3.0.old3/Documentation/ABI/removed': Input/output error Progress towards fixing https://github.com/rfjakob/gocryptfs/issues/483 .
Diffstat (limited to 'internal/syscallcompat/sys_common.go')
-rw-r--r--internal/syscallcompat/sys_common.go34
1 files changed, 22 insertions, 12 deletions
diff --git a/internal/syscallcompat/sys_common.go b/internal/syscallcompat/sys_common.go
index c50c940..d178a9b 100644
--- a/internal/syscallcompat/sys_common.go
+++ b/internal/syscallcompat/sys_common.go
@@ -44,7 +44,8 @@ func Faccessat(dirfd int, path string, mode uint32) error {
return unix.Faccessat(dirfd, path, mode, 0)
}
-// Openat wraps the Openat syscall, retrying on EINTR.
+// Openat wraps the Openat syscall.
+// Retries on EINTR.
func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) {
if flags&syscall.O_CREAT != 0 {
// O_CREAT should be used with O_EXCL. O_NOFOLLOW has no effect with O_EXCL.
@@ -59,24 +60,28 @@ func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error)
flags |= syscall.O_NOFOLLOW
}
}
- // Like ignoringEINTR() in the Go stdlib:
- // https://github.com/golang/go/blob/d2a80f3fb5b44450e0b304ac5a718f99c053d82a/src/os/file_posix.go#L243
- for {
- fd, err = unix.Openat(dirfd, path, flags, mode)
- if err != unix.EINTR {
- return fd, err
- }
- }
+ fd, err = retryEINTR2(func() (int, error) {
+ return unix.Openat(dirfd, path, flags, mode)
+ })
+ return fd, err
}
// Renameat wraps the Renameat syscall.
+// Retries on EINTR.
func Renameat(olddirfd int, oldpath string, newdirfd int, newpath string) (err error) {
- return unix.Renameat(olddirfd, oldpath, newdirfd, newpath)
+ err = retryEINTR(func() error {
+ return unix.Renameat(olddirfd, oldpath, newdirfd, newpath)
+ })
+ return err
}
// Unlinkat syscall.
+// Retries on EINTR.
func Unlinkat(dirfd int, path string, flags int) (err error) {
- return unix.Unlinkat(dirfd, path, flags)
+ err = retryEINTR(func() error {
+ return unix.Unlinkat(dirfd, path, flags)
+ })
+ return err
}
// Fchownat syscall.
@@ -105,17 +110,22 @@ func Mkdirat(dirfd int, path string, mode uint32) (err error) {
}
// Fstatat syscall.
+// Retries on EINTR.
func Fstatat(dirfd int, path string, stat *unix.Stat_t, flags int) (err error) {
// Why would we ever want to call this without AT_SYMLINK_NOFOLLOW?
if flags&unix.AT_SYMLINK_NOFOLLOW == 0 {
tlog.Warn.Printf("Fstatat: adding missing AT_SYMLINK_NOFOLLOW flag")
flags |= unix.AT_SYMLINK_NOFOLLOW
}
- return unix.Fstatat(dirfd, path, stat, flags)
+ err = retryEINTR(func() error {
+ return unix.Fstatat(dirfd, path, stat, flags)
+ })
+ return err
}
// Fstatat2 is a more convenient version of Fstatat. It allocates a Stat_t
// for you and also handles the Unix2syscall conversion.
+// Retries on EINTR.
func Fstatat2(dirfd int, path string, flags int) (*syscall.Stat_t, error) {
var stUnix unix.Stat_t
err := Fstatat(dirfd, path, &stUnix, flags)