summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerry Jelinek <jerry.jelinek@joyent.com>2015-07-02 16:08:15 +0000
committerJerry Jelinek <jerry.jelinek@joyent.com>2015-07-02 16:08:15 +0000
commit2f5d1852d0879c52fae03a5cf1142a4fcb820172 (patch)
treedf35bfc29a4ec733c2e890671dcda1d0e032e2e5
parent1fbb9b858a49a324cae03665aeab3cc866814618 (diff)
downloadillumos-joyent-2f5d1852d0879c52fae03a5cf1142a4fcb820172.tar.gz
OS-4469 journald needs fallocate(2) syscall
-rw-r--r--usr/src/lib/brand/lx/testing/ltp_skiplist4
-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/sys/lx_types.h4
-rw-r--r--usr/src/uts/common/brand/lx/syscall/lx_fallocate.c227
-rw-r--r--usr/src/uts/intel/Makefile.files1
6 files changed, 236 insertions, 5 deletions
diff --git a/usr/src/lib/brand/lx/testing/ltp_skiplist b/usr/src/lib/brand/lx/testing/ltp_skiplist
index fdd2eb6206..7568a28682 100644
--- a/usr/src/lib/brand/lx/testing/ltp_skiplist
+++ b/usr/src/lib/brand/lx/testing/ltp_skiplist
@@ -127,9 +127,7 @@ add_key02
clone02
clone08
crash02
-fallocate01
-fallocate01
-fallocate01
+fallocate04 # needs SEEK_HOLE
fanotify01
fanotify02
fanotify03
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 6b8f60efda..993af09f12 100644
--- a/usr/src/uts/common/brand/lx/os/lx_syscall.c
+++ b/usr/src/uts/common/brand/lx/os/lx_syscall.c
@@ -851,7 +851,7 @@ lx_sysent_t lx_sysent32[] = {
{"signalfd", NULL, 0, 3}, /* 321 */
{"timerfd_create", NULL, 0, 2}, /* 322 */
{"eventfd", NULL, 0, 1}, /* 323 */
- {"fallocate", NULL, NOSYS_NULL, 0}, /* 324 */
+ {"fallocate", lx_fallocate, 0, 4}, /* 324 */
{"timerfd_settime", NULL, 0, 4}, /* 325 */
{"timerfd_gettime", NULL, 0, 2}, /* 326 */
{"signalfd4", NULL, 0, 4}, /* 327 */
@@ -1179,7 +1179,7 @@ lx_sysent_t lx_sysent64[] = {
{"signalfd", NULL, 0, 3}, /* 282 */
{"timerfd_create", NULL, 0, 2}, /* 283 */
{"eventfd", NULL, 0, 1}, /* 284 */
- {"fallocate", NULL, NOSYS_NULL, 0}, /* 285 */
+ {"fallocate", lx_fallocate, 0, 4}, /* 285 */
{"timerfd_settime", NULL, 0, 4}, /* 286 */
{"timerfd_gettime", NULL, 0, 2}, /* 287 */
{"accept4", NULL, 0, 4}, /* 288 */
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 989991e6c0..41587591fd 100644
--- a/usr/src/uts/common/brand/lx/sys/lx_syscalls.h
+++ b/usr/src/uts/common/brand/lx/sys/lx_syscalls.h
@@ -43,6 +43,7 @@ extern long lx_clock_getres();
extern long lx_clock_gettime();
extern long lx_clock_settime();
extern long lx_connect();
+extern long lx_fallocate();
extern long lx_fchmod();
extern long lx_fchmodat();
extern long lx_fchown();
diff --git a/usr/src/uts/common/brand/lx/sys/lx_types.h b/usr/src/uts/common/brand/lx/sys/lx_types.h
index 922c412020..e91484c16b 100644
--- a/usr/src/uts/common/brand/lx/sys/lx_types.h
+++ b/usr/src/uts/common/brand/lx/sys/lx_types.h
@@ -40,6 +40,10 @@ extern "C" {
#define INT_MAX 2147483647 /* max value of an "int" */
#define UINT_MAX 4294967295U /* max value of an "unsigned int" */
+#ifndef LLONG_MAX
+#define LLONG_MAX 9223372036854775807LL
+#endif
+
#if defined(_LP64)
#define LONG_MAX 9223372036854775807L
#define ULONG_MAX 18446744073709551615UL
diff --git a/usr/src/uts/common/brand/lx/syscall/lx_fallocate.c b/usr/src/uts/common/brand/lx/syscall/lx_fallocate.c
new file mode 100644
index 0000000000..2c214bfb87
--- /dev/null
+++ b/usr/src/uts/common/brand/lx/syscall/lx_fallocate.c
@@ -0,0 +1,227 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2015 Joyent, Inc.
+ */
+
+#include <sys/systm.h>
+#include <sys/zone.h>
+#include <sys/types.h>
+#include <sys/filio.h>
+#include <sys/fcntl.h>
+#include <sys/stat.h>
+#include <sys/nbmlock.h>
+#include <sys/lx_impl.h>
+#include <sys/lx_brand.h>
+#include <sys/sdt.h>
+
+extern int flock_check(vnode_t *, flock64_t *, offset_t, offset_t);
+
+#define LX_FALLOC_FL_KEEP_SIZE 0x01
+#define LX_FALLOC_FL_PUNCH_HOLE 0x02
+#define LX_FALLOC_FL_NO_HIDE_STALE 0x04
+#define LX_FALLOC_FL_COLLAPSE_RANGE 0x08
+#define LX_FALLOC_FL_ZERO_RANGE 0x10
+
+#define LX_FALLOC_VALID (LX_FALLOC_FL_KEEP_SIZE | LX_FALLOC_FL_PUNCH_HOLE | \
+ LX_FALLOC_FL_NO_HIDE_STALE | LX_FALLOC_FL_COLLAPSE_RANGE | \
+ LX_FALLOC_FL_ZERO_RANGE)
+
+long
+lx_fallocate(int fd, int mode, off_t offset, off_t len)
+{
+ int error = 0;
+ file_t *fp;
+ vnode_t *vp;
+ int64_t tot;
+ struct flock64 bf;
+ vattr_t vattr;
+ u_offset_t f_offset;
+ boolean_t in_crit = B_FALSE;
+
+ /*
+ * Error checking is in a specific order to make LTP happy.
+ */
+
+ tot = offset + len;
+ if (tot > (LLONG_MAX / (int64_t)1024))
+ return (set_errno(EFBIG));
+
+ if (mode & LX_FALLOC_FL_COLLAPSE_RANGE)
+ return (set_errno(EOPNOTSUPP));
+
+ if ((fp = getf(fd)) == NULL)
+ return (set_errno(EBADF));
+
+ if ((fp->f_flag & FWRITE) == 0) {
+ error = EBADF;
+ goto done;
+ }
+
+ vp = fp->f_vnode;
+ if (vp->v_type != VREG) {
+ error = EINVAL;
+ goto done;
+ }
+
+ if (offset < 0 || len <= 0) {
+ error = EINVAL;
+ goto done;
+ }
+
+ if (tot < 0LL) {
+ error = EFBIG;
+ goto done;
+ }
+
+ if ((mode & ~LX_FALLOC_VALID) != 0) {
+ error = EINVAL;
+ goto done;
+ }
+
+ /*
+ * If this is the only flag then we don't actually do any work.
+ */
+ if (mode == LX_FALLOC_FL_KEEP_SIZE)
+ goto done;
+
+ bzero(&bf, sizeof (bf));
+
+ vattr.va_mask = AT_SIZE;
+ if ((error = VOP_GETATTR(vp, &vattr, 0, CRED(), NULL)) != 0)
+ goto done;
+
+ if (mode == 0) {
+ /* Nothing to do if not extending the file */
+ if (vattr.va_size >= tot)
+ goto done;
+
+ /* Extend the file. */
+ bf.l_start = (off64_t)tot;
+ bf.l_len = (off64_t)0;
+
+ } else if (mode & LX_FALLOC_FL_PUNCH_HOLE) {
+ /*
+ * Deallocate space in the file.
+ */
+ if ((mode & LX_FALLOC_FL_KEEP_SIZE) == 0) {
+ /* this flag is required with punch hole */
+ error = EINVAL;
+ goto done;
+ }
+
+ if (mode &
+ ~(LX_FALLOC_FL_PUNCH_HOLE | LX_FALLOC_FL_KEEP_SIZE)) {
+ error = EINVAL;
+ goto done;
+ }
+
+ /* Make sure we don't extend since keep_size is set. */
+ if (vattr.va_size < tot) {
+ if (offset > vattr.va_size)
+ goto done;
+ len = (off_t)vattr.va_size - offset;
+ }
+
+ bf.l_start = (off64_t)offset;
+ bf.l_len = (off64_t)len;
+
+ } else if (mode & LX_FALLOC_FL_ZERO_RANGE) {
+ /*
+ * Zero out the space in the file.
+ */
+ if (mode &
+ ~(LX_FALLOC_FL_ZERO_RANGE | LX_FALLOC_FL_KEEP_SIZE)) {
+ error = EINVAL;
+ goto done;
+ }
+
+ /* Make sure we don't extend when keep_size is set. */
+ if (mode & LX_FALLOC_FL_KEEP_SIZE && vattr.va_size < tot) {
+ if (offset > vattr.va_size)
+ goto done;
+ len = vattr.va_size - offset;
+ }
+
+ bf.l_start = (off64_t)offset;
+ bf.l_len = (off64_t)len;
+ } else {
+ /* We should have already handled all flags */
+ VERIFY(0);
+ }
+
+ /*
+ * Check for locks in the range.
+ */
+ f_offset = fp->f_offset;
+ error = flock_check(vp, &bf, f_offset, MAXOFF_T);
+ if (error != 0)
+ goto done;
+
+ /*
+ * Check for conflicting non-blocking mandatory locks.
+ * We need to get the size again under nbl_start_crit.
+ */
+ if (nbl_need_check(vp)) {
+ u_offset_t begin;
+ ssize_t length;
+
+ nbl_start_crit(vp, RW_READER);
+ in_crit = B_TRUE;
+ vattr.va_mask = AT_SIZE;
+ if ((error = VOP_GETATTR(vp, &vattr, 0, CRED(), NULL)) != 0)
+ goto done;
+
+ /*
+ * Make sure we don't extend when keep_size is set.
+ */
+ if (mode & LX_FALLOC_FL_KEEP_SIZE && vattr.va_size < tot) {
+ ASSERT(mode & (LX_FALLOC_FL_PUNCH_HOLE |
+ LX_FALLOC_FL_ZERO_RANGE));
+
+ /*
+ * If the size grew we can short-circuit the rest of
+ * the work, otherwise adjust bf for the vop_space
+ * call.
+ */
+ if (offset >= vattr.va_size)
+ goto done;
+ len = vattr.va_size - offset;
+ bf.l_len = (off64_t)len;
+ }
+
+ if (offset > vattr.va_size) {
+ begin = vattr.va_size;
+ length = offset - vattr.va_size;
+ } else {
+ begin = offset;
+ length = vattr.va_size - offset;
+ }
+
+ if (nbl_conflict(vp, NBL_WRITE, begin, length, 0, NULL)) {
+ error = EACCES;
+ goto done;
+ }
+ }
+
+ error = VOP_SPACE(vp, F_FREESP, &bf, 0, f_offset, fp->f_cred, NULL);
+
+done:
+ if (in_crit)
+ nbl_end_crit(vp);
+
+ releasef(fd);
+ if (error != 0)
+ return (set_errno(error));
+
+ return (0);
+}
diff --git a/usr/src/uts/intel/Makefile.files b/usr/src/uts/intel/Makefile.files
index 4e69d03511..7e30c5843f 100644
--- a/usr/src/uts/intel/Makefile.files
+++ b/usr/src/uts/intel/Makefile.files
@@ -294,6 +294,7 @@ LX_BRAND_OBJS = \
lx_clone.o \
lx_cpu.o \
lx_errno.o \
+ lx_fallocate.o \
lx_fcntl.o \
lx_futex.o \
lx_getdents.o \