diff options
author | Jerry Jelinek <jerry.jelinek@joyent.com> | 2015-07-02 16:08:15 +0000 |
---|---|---|
committer | Jerry Jelinek <jerry.jelinek@joyent.com> | 2015-07-02 16:08:15 +0000 |
commit | 2f5d1852d0879c52fae03a5cf1142a4fcb820172 (patch) | |
tree | df35bfc29a4ec733c2e890671dcda1d0e032e2e5 | |
parent | 1fbb9b858a49a324cae03665aeab3cc866814618 (diff) | |
download | illumos-joyent-2f5d1852d0879c52fae03a5cf1142a4fcb820172.tar.gz |
OS-4469 journald needs fallocate(2) syscall
-rw-r--r-- | usr/src/lib/brand/lx/testing/ltp_skiplist | 4 | ||||
-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/sys/lx_types.h | 4 | ||||
-rw-r--r-- | usr/src/uts/common/brand/lx/syscall/lx_fallocate.c | 227 | ||||
-rw-r--r-- | usr/src/uts/intel/Makefile.files | 1 |
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 \ |