unix: correct argument order for SyncFileRange syscall on linux/ppc64{,le}

On linux/ppc64{,le} the SYS_SYNC_FILE_RANGE2 syscall is used to
implement SyncFileRange. This syscall has a different argument order
than SYS_SYNC_FILE_RANGE. Apart from that the implementations of both
syscalls are the same, so use a simple wrapper to invoke the syscall
with the correct argument order.

For context see:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=edd5cd4a9424f22b0fa08bef5e299d41befd5622

Fixes golang/go#27485

Change-Id: Idc154eab7b7c521a34de821e1d1a97095e96fed0
Reviewed-on: https://go-review.googlesource.com/133215
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
diff --git a/unix/syscall_linux_ppc64x.go b/unix/syscall_linux_ppc64x.go
index 8c6720f..6a38dfd 100644
--- a/unix/syscall_linux_ppc64x.go
+++ b/unix/syscall_linux_ppc64x.go
@@ -44,7 +44,6 @@
 //sys	Splice(rfd int, roff *int64, wfd int, woff *int64, len int, flags int) (n int64, err error)
 //sys	Stat(path string, stat *Stat_t) (err error)
 //sys	Statfs(path string, buf *Statfs_t) (err error)
-//sys	SyncFileRange(fd int, off int64, n int64, flags int) (err error) = SYS_SYNC_FILE_RANGE2
 //sys	Truncate(path string, length int64) (err error)
 //sys	Ustat(dev int, ubuf *Ustat_t) (err error)
 //sys	accept(s int, rsa *RawSockaddrAny, addrlen *_Socklen) (fd int, err error)
@@ -129,3 +128,11 @@
 	}
 	return poll(&fds[0], len(fds), timeout)
 }
+
+//sys	syncFileRange2(fd int, flags int, off int64, n int64) (err error) = SYS_SYNC_FILE_RANGE2
+
+func SyncFileRange(fd int, off int64, n int64, flags int) error {
+	// The sync_file_range and sync_file_range2 syscalls differ only in the
+	// order of their arguments.
+	return syncFileRange2(fd, flags, off, n)
+}
diff --git a/unix/syscall_linux_test.go b/unix/syscall_linux_test.go
index 7fb5804..0f68077 100644
--- a/unix/syscall_linux_test.go
+++ b/unix/syscall_linux_test.go
@@ -7,6 +7,7 @@
 package unix_test
 
 import (
+	"io/ioutil"
 	"os"
 	"runtime"
 	"runtime/debug"
@@ -441,3 +442,26 @@
 		}
 	}
 }
+
+func TestSyncFileRange(t *testing.T) {
+	file, err := ioutil.TempFile("", "TestSyncFileRange")
+	if err != nil {
+		t.Fatal(err)
+	}
+	defer os.Remove(file.Name())
+	defer file.Close()
+
+	err = unix.SyncFileRange(int(file.Fd()), 0, 0, 0)
+	if err == unix.ENOSYS || err == unix.EPERM {
+		t.Skip("sync_file_range syscall is not available, skipping test")
+	} else if err != nil {
+		t.Fatalf("SyncFileRange: %v", err)
+	}
+
+	// invalid flags
+	flags := 0xf00
+	err = unix.SyncFileRange(int(file.Fd()), 0, 0, flags)
+	if err != unix.EINVAL {
+		t.Fatalf("SyncFileRange: unexpected error: %v, want EINVAL", err)
+	}
+}
diff --git a/unix/zsyscall_linux_ppc64.go b/unix/zsyscall_linux_ppc64.go
index 2f7110d..f3fae1d 100644
--- a/unix/zsyscall_linux_ppc64.go
+++ b/unix/zsyscall_linux_ppc64.go
@@ -1998,16 +1998,6 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func SyncFileRange(fd int, off int64, n int64, flags int) (err error) {
-	_, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE2, uintptr(fd), uintptr(off), uintptr(n), uintptr(flags), 0, 0)
-	if e1 != 0 {
-		err = errnoErr(e1)
-	}
-	return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
 func Truncate(path string, length int64) (err error) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(path)
@@ -2317,3 +2307,13 @@
 	}
 	return
 }
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func syncFileRange2(fd int, flags int, off int64, n int64) (err error) {
+	_, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE2, uintptr(fd), uintptr(flags), uintptr(off), uintptr(n), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
diff --git a/unix/zsyscall_linux_ppc64le.go b/unix/zsyscall_linux_ppc64le.go
index bb3bd59..011b0a5 100644
--- a/unix/zsyscall_linux_ppc64le.go
+++ b/unix/zsyscall_linux_ppc64le.go
@@ -1998,16 +1998,6 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func SyncFileRange(fd int, off int64, n int64, flags int) (err error) {
-	_, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE2, uintptr(fd), uintptr(off), uintptr(n), uintptr(flags), 0, 0)
-	if e1 != 0 {
-		err = errnoErr(e1)
-	}
-	return
-}
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
 func Truncate(path string, length int64) (err error) {
 	var _p0 *byte
 	_p0, err = BytePtrFromString(path)
@@ -2317,3 +2307,13 @@
 	}
 	return
 }
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
+func syncFileRange2(fd int, flags int, off int64, n int64) (err error) {
+	_, _, e1 := Syscall6(SYS_SYNC_FILE_RANGE2, uintptr(fd), uintptr(flags), uintptr(off), uintptr(n), 0, 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}