diff options
-rw-r--r-- | usr/src/uts/common/brand/lx/os/lx_syscall.c | 4 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/sys/lx_syscalls.h | 1 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/syscall/lx_sync.c | 49 |
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); +} |