# HG changeset patch # Parent 3312b0f02247e73151fc8dcdf01a174d062c0d18 Add fallocate and fdiscard syscalls. diff -r 3312b0f02247 sys/kern/syscalls.master --- a/sys/kern/syscalls.master Sun Mar 23 23:21:53 2014 -0400 +++ b/sys/kern/syscalls.master Sun Mar 23 23:40:15 2014 -0400 @@ -944,3 +944,7 @@ 478 STD { int|sys|60|_lwp_park(clockid_t clock_id, int flags, \ const struct timespec *ts, lwpid_t unpark, \ const void *hint, const void *unparkhint); } +479 STD RUMP { int|sys||fallocate(int fd, int PAD, off_t pos, \ + off_t len); } +480 STD RUMP { int|sys||fdiscard(int fd, int PAD, off_t pos, \ + off_t len); } diff -r 3312b0f02247 sys/kern/vfs_syscalls.c --- a/sys/kern/vfs_syscalls.c Sun Mar 23 23:21:53 2014 -0400 +++ b/sys/kern/vfs_syscalls.c Sun Mar 23 23:40:15 2014 -0400 @@ -116,6 +116,11 @@ #include #include +/* XXX this shouldn't be here */ +#ifndef OFF_T_MAX +#define OFF_T_MAX __type_max(off_t) +#endif + static int change_flags(struct vnode *, u_long, struct lwp *); static int change_mode(struct vnode *, int, struct lwp *); static int change_owner(struct vnode *, uid_t, gid_t, struct lwp *, int); @@ -4685,3 +4690,105 @@ vrele(vp); return (error); } + +/* + * Allocate backing store for a file, filling a hole without having to + * explicitly write anything out. + */ +/* ARGSUSED */ +int +sys_fallocate(struct lwp *l, const struct sys_fallocate_args *uap, + register_t *retval) +{ + /* { + syscallarg(int) fd; + syscallarg(off_t) pos; + syscallarg(off_t) len; + } */ + int fd; + off_t pos, len; + struct file *fp; + struct vnode *vp; + int result; + + fd = SCARG(uap, fd); + pos = SCARG(uap, pos); + len = SCARG(uap, len); + + if (pos < 0 || len < 0 || len > OFF_T_MAX - pos) { + return EINVAL; + } + + result = fd_getvnode(fd, &fp); + if (result) { + return result; + } + if ((fp->f_flag & FWRITE) == 0) { + result = EBADF; + goto fail; + } + vp = fp->f_data; + + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + if (vp->v_type == VDIR) { + result = EISDIR; + } else { + result = VOP_FALLOCATE(vp, pos, len); + } + VOP_UNLOCK(vp); + +fail: + fd_putfile(fd); + return result; +} + +/* + * Dellocate backing store for a file, creating a hole. Also used for + * invoking TRIM on disks. + */ +/* ARGSUSED */ +int +sys_fdiscard(struct lwp *l, const struct sys_fdiscard_args *uap, + register_t *retval) +{ + /* { + syscallarg(int) fd; + syscallarg(off_t) pos; + syscallarg(off_t) len; + } */ + int fd; + off_t pos, len; + struct file *fp; + struct vnode *vp; + int result; + + fd = SCARG(uap, fd); + pos = SCARG(uap, pos); + len = SCARG(uap, len); + + if (pos < 0 || len < 0 || len > OFF_T_MAX - pos) { + return EINVAL; + } + + result = fd_getvnode(fd, &fp); + if (result) { + return result; + } + if ((fp->f_flag & FWRITE) == 0) { + result = EBADF; + goto fail; + } + vp = fp->f_data; + + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + if (vp->v_type == VDIR) { + result = EISDIR; + } else { + result = VOP_FDISCARD(vp, pos, len); + } + VOP_UNLOCK(vp); + +fail: + fd_putfile(fd); + return result; +}