summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/src/uts/common/brand/lx/os/lx_syscall.c4
-rw-r--r--usr/src/uts/common/brand/lx/sys/lx_syscalls.h1
-rw-r--r--usr/src/uts/common/brand/lx/syscall/lx_sync.c49
3 files changed, 52 insertions, 2 deletions
diff --git a/usr/src/uts/common/brand/lx/os/lx_syscall.c b/usr/src/uts/common/brand/lx/os/lx_syscall.c
index 13857f3d22..b47b82be29 100644
--- a/usr/src/uts/common/brand/lx/os/lx_syscall.c
+++ b/usr/src/uts/common/brand/lx/os/lx_syscall.c
@@ -934,7 +934,7 @@ lx_sysent_t lx_sysent32[] = {
{"set_robust_list", lx_set_robust_list, 0, 2}, /* 311 */
{"get_robust_list", lx_get_robust_list, 0, 3}, /* 312 */
{"splice", NULL, NOSYS_NULL, 0}, /* 313 */
- {"sync_file_range", NULL, NOSYS_NULL, 0}, /* 314 */
+ {"sync_file_range", lx_sync_file_range, 0, 4}, /* 314 */
{"tee", NULL, NOSYS_NULL, 0}, /* 315 */
{"vmsplice", NULL, NOSYS_NULL, 0}, /* 316 */
{"move_pages", NULL, NOSYS_NULL, 0}, /* 317 */
@@ -1264,7 +1264,7 @@ lx_sysent_t lx_sysent64[] = {
{"get_robust_list", lx_get_robust_list, 0, 3}, /* 274 */
{"splice", NULL, NOSYS_NULL, 0}, /* 275 */
{"tee", NULL, NOSYS_NULL, 0}, /* 276 */
- {"sync_file_range", NULL, NOSYS_NULL, 0}, /* 277 */
+ {"sync_file_range", lx_sync_file_range, 0, 4}, /* 277 */
{"vmsplice", NULL, NOSYS_NULL, 0}, /* 278 */
{"move_pages", NULL, NOSYS_NULL, 0}, /* 279 */
{"utimensat", NULL, 0, 4}, /* 280 */
diff --git a/usr/src/uts/common/brand/lx/sys/lx_syscalls.h b/usr/src/uts/common/brand/lx/sys/lx_syscalls.h
index c51763b056..7a32a1e1d8 100644
--- a/usr/src/uts/common/brand/lx/sys/lx_syscalls.h
+++ b/usr/src/uts/common/brand/lx/sys/lx_syscalls.h
@@ -117,6 +117,7 @@ extern long lx_setrlimit();
extern long lx_setsockopt();
extern long lx_socket();
extern long lx_socketcall();
+extern long lx_sync_file_range();
extern long lx_syncfs();
extern long lx_sysinfo32();
extern long lx_sysinfo64();
diff --git a/usr/src/uts/common/brand/lx/syscall/lx_sync.c b/usr/src/uts/common/brand/lx/syscall/lx_sync.c
index 327a73d3b7..614afca0b0 100644
--- a/usr/src/uts/common/brand/lx/syscall/lx_sync.c
+++ b/usr/src/uts/common/brand/lx/syscall/lx_sync.c
@@ -15,7 +15,10 @@
#include <sys/systm.h>
#include <sys/types.h>
+#include <sys/errno.h>
+#include <sys/file.h>
#include <sys/vfs.h>
+#include <sys/vnode.h>
#include <sys/lx_impl.h>
#include <sys/lx_brand.h>
@@ -35,3 +38,49 @@ lx_syncfs(int fd)
return (0);
}
+
+#define LX_SYNC_FILE_RANGE_WAIT_BEFORE 0x1
+#define LX_SYNC_FILE_RANGE_WRITE 0x2
+#define LX_SYNC_FILE_RANGE_WAIT_AFTER 0x4
+
+#define LX_SYNC_FILE_RANGE_VALID (LX_SYNC_FILE_RANGE_WAIT_BEFORE | \
+ LX_SYNC_FILE_RANGE_WRITE | LX_SYNC_FILE_RANGE_WAIT_AFTER)
+
+
+long
+lx_sync_file_range(int fd, off_t offset, off_t nbytes, int flags)
+{
+ file_t *fp;
+ int error, sflags = 0;
+
+ if ((flags & ~LX_SYNC_FILE_RANGE_VALID) != 0)
+ return (set_errno(EINVAL));
+ if (offset < 0 || nbytes < 0)
+ return (set_errno(EINVAL));
+
+ if ((fp = getf(fd)) == NULL)
+ return (set_errno(EBADF));
+
+ /*
+ * Since sync_file_range is implemented in terms of VOP_PUTPAGE, both
+ * SYNC_FILE_RANGE_WAIT flags are treated as forcing synchronous
+ * operation. While this differs from the Linux behavior where
+ * BEFORE/AFTER are distinct, it achieves an adequate level of safety
+ * since the requested data is synced out at the end of the call.
+ */
+ if ((flags & (LX_SYNC_FILE_RANGE_WAIT_BEFORE |
+ LX_SYNC_FILE_RANGE_WAIT_AFTER)) == 0) {
+ sflags |= B_ASYNC;
+ }
+
+ error = VOP_PUTPAGE(fp->f_vnode, offset, nbytes, sflags, CRED(), NULL);
+ if (error == ENOSYS) {
+ error = ESPIPE;
+ }
+
+ releasef(fd);
+ if (error != 0) {
+ return (set_errno(error));
+ }
+ return (0);
+}