]> Cypherpunks repositories - gostls13.git/commitdiff
internal/poll: use F_FULLFSYNC fcntl for FD.Fsync on OS X
authorEmmanuel T Odeke <emmanuel@orijtech.com>
Wed, 22 Aug 2018 05:58:08 +0000 (22:58 -0700)
committerEmmanuel Odeke <emm.odeke@gmail.com>
Wed, 22 Aug 2018 22:26:40 +0000 (22:26 +0000)
As reported in #26650 and also cautioned on the man page
for fsync on OS X, fsync doesn't properly flush content
to permanent storage, and might cause corruption of data if
the OS crashes or if the drive loses power. Thus it is recommended
to use the F_FULLFSYNC fcntl, which flushes all buffered data to
permanent storage and is important for applications such as
databases that require a strict ordering of writes.

Also added a note in syscall_darwin.go that syscall.Fsync is
not invoked for os.File.Sync.

Fixes #26650.

Change-Id: Idecd9adbbdd640b9c5b02e73b60ed254c98b48b6
Reviewed-on: https://go-review.googlesource.com/130676
Run-TryBot: Emmanuel Odeke <emm.odeke@gmail.com>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/internal/poll/fd_fsync_darwin.go [new file with mode: 0644]
src/internal/poll/fd_fsync_posix.go [new file with mode: 0644]
src/internal/poll/fd_posix.go
src/syscall/syscall_darwin.go

diff --git a/src/internal/poll/fd_fsync_darwin.go b/src/internal/poll/fd_fsync_darwin.go
new file mode 100644 (file)
index 0000000..23835f6
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package poll
+
+import "syscall"
+
+// Fsync invokes SYS_FCNTL with SYS_FULLFSYNC because
+// on OS X, SYS_FSYNC doesn't fully flush contents to disk.
+// See Issue #26650 as well as the man page for fsync on OS X.
+func (fd *FD) Fsync() error {
+       if err := fd.incref(); err != nil {
+               return err
+       }
+       defer fd.decref()
+
+       _, _, e1 := syscall.Syscall(syscall.SYS_FCNTL, uintptr(fd.Sysfd), syscall.F_FULLFSYNC, 0)
+       if e1 != 0 {
+               return e1
+       }
+       return nil
+}
diff --git a/src/internal/poll/fd_fsync_posix.go b/src/internal/poll/fd_fsync_posix.go
new file mode 100644 (file)
index 0000000..943f59a
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris windows
+
+package poll
+
+import "syscall"
+
+// Fsync wraps syscall.Fsync.
+func (fd *FD) Fsync() error {
+       if err := fd.incref(); err != nil {
+               return err
+       }
+       defer fd.decref()
+       return syscall.Fsync(fd.Sysfd)
+}
index f178a6fa0ae1b698251d3f7c71e19165676b0f7a..f899a74876d377ef1ad99044a27536dcb32cb414 100644 (file)
@@ -46,12 +46,3 @@ func (fd *FD) Ftruncate(size int64) error {
        defer fd.decref()
        return syscall.Ftruncate(fd.Sysfd, size)
 }
-
-// Fsync wraps syscall.Fsync.
-func (fd *FD) Fsync() error {
-       if err := fd.incref(); err != nil {
-               return err
-       }
-       defer fd.decref()
-       return syscall.Fsync(fd.Sysfd)
-}
index 4d6aa4fcf23e482c7dd6233f91d2d3e13026f8e6..98084a521cac0c25cd6099f0f6d9da3680abd2b9 100644 (file)
@@ -252,6 +252,7 @@ func Kill(pid int, signum Signal) (err error) { return kill(pid, int(signum), 1)
 //sys  Fstat(fd int, stat *Stat_t) (err error) = SYS_FSTAT64
 //sys  Fstatfs(fd int, stat *Statfs_t) (err error) = SYS_FSTATFS64
 //sys  Fsync(fd int) (err error)
+//  Fsync is not called for os.File.Sync(). Please see internal/poll/fd_fsync_darwin.go
 //sys  Ftruncate(fd int, length int64) (err error)
 //sys  Getdirentries(fd int, buf []byte, basep *uintptr) (n int, err error) = SYS_GETDIRENTRIES64
 //sys  Getdtablesize() (size int)