diff --git a/bsd/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c b/bsd/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c index f2fe4b9fa659b6511c5f89e3a75caa3da0e34701..da2856899551c2c202b5d8cc9fdea8511b926407 100644 --- a/bsd/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c +++ b/bsd/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c @@ -26,6 +26,10 @@ /* Portions Copyright 2007 Jeremy Teo */ /* Portions Copyright 2010 Robert Milkowski */ +/* + * Copyright (c) 2011, Lawrence Livermore National Security, LLC. + */ + #include <sys/types.h> #include <sys/param.h> #include <sys/time.h> @@ -67,6 +71,7 @@ #include <sys/extdirent.h> #include <sys/kidmap.h> #include <sys/acl.h> +#include <sys/fcntl.h> /* * Programming rules. @@ -4221,6 +4226,56 @@ zfs_delmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr, return (0); } +#endif /* sun */ +#endif /* NOTYET */ + +/* + * convoff - converts the given data (start, whence) to the + * given whence. + */ +int +convoff(vnode_t *vp, flock64_t *lckdat, int whence, offset_t offset) +{ + vattr_t vap; + int error; + + if ((lckdat->l_whence == 2) || (whence == 2)) { + if ((error = zfs_getattr(vp, &vap) != 0)) + return (error); + } + + switch (lckdat->l_whence) { + case 1: + lckdat->l_start += offset; + break; + case 2: + lckdat->l_start += vap.va_size; + /* FALLTHRU */ + case 0: + break; + default: + return (EINVAL); + } + + if (lckdat->l_start < 0) + return (EINVAL); + + switch (whence) { + case 1: + lckdat->l_start -= offset; + break; + case 2: + lckdat->l_start -= vap.va_size; + /* FALLTHRU */ + case 0: + break; + default: + return (EINVAL); + } + + lckdat->l_whence = (short)whence; + return (0); +} /* * Free or allocate space in a file. Currently, this function only @@ -4229,7 +4284,8 @@ zfs_delmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr, * well as free space. * * IN: vp - vnode of file to free data in. - * cmd - action to take (only F_FREESP supported). + * cmd - action to take (F_FREESP and + * (F_FREESP | F_KEEPSP) supported). * bfp - section of file to free/alloc. * flag - current file open mode flags. * offset - current file offset. @@ -4245,17 +4301,18 @@ zfs_delmap(vnode_t *vp, offset_t off, struct as *as, caddr_t addr, /* ARGSUSED */ static int zfs_space(vnode_t *vp, int cmd, flock64_t *bfp, int flag, - offset_t offset, cred_t *cr, caller_context_t *ct) + offset_t offset) { znode_t *zp = VTOZ(vp); zfsvfs_t *zfsvfs = zp->z_zfsvfs; - uint64_t off, len; + uint64_t off, len, original_size; int error; ZFS_ENTER(zfsvfs); ZFS_VERIFY_ZP(zp); - if (cmd != F_FREESP) { + if (cmd != F_FREESP && + ((cmd & (F_FREESP | F_KEEPSP)) != (F_FREESP | F_KEEPSP))) { ZFS_EXIT(zfsvfs); return (EINVAL); } @@ -4270,16 +4327,45 @@ zfs_space(vnode_t *vp, int cmd, flock64_t *bfp, int flag, return (EINVAL); } + original_size = zp->z_size; off = bfp->l_start; len = bfp->l_len; /* 0 means from off to end of file */ - error = zfs_freesp(zp, off, len, flag, TRUE); + if (error = zfs_freesp(zp, off, len, flag, TRUE)) { + ZFS_EXIT(zfsvfs); + return (error); + } + + if (cmd & F_KEEPSP) { + error = zfs_freesp(zp, original_size, 0, 0, TRUE); + } ZFS_EXIT(zfsvfs); return (error); } -#endif /* sun */ +static int +zfs_fallocate(vnode_t *vp, int mode, loff_t offset, loff_t len) +{ + int error = EOPNOTSUPP; + + if ((mode & (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE)) == + (FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE)) { + flock64_t bf; + + bf.l_type = F_WRLCK; + bf.l_whence = 0; + bf.l_start = offset; + bf.l_len = len; + bf.l_pid = 0; + + error = zfs_space(vp, F_FREESP | F_KEEPSP, &bf, FWRITE, offset); + } + + return (error); +} + +#ifdef NOTYET CTASSERT(sizeof(struct zfid_short) <= sizeof(struct fid)); CTASSERT(sizeof(struct zfid_long) <= sizeof(struct fid)); @@ -4953,5 +5039,6 @@ struct vnops zfs_vnops = { zfs_inactive, /* inactive */ zfs_truncate, /* truncate */ zfs_link, /* link */ - zfs_arc, /* arc */ + zfs_arc, /* arc */ + zfs_fallocate, /* fallocate */ }; diff --git a/bsd/sys/sys/fcntl.h b/bsd/sys/sys/fcntl.h new file mode 100644 index 0000000000000000000000000000000000000000..af7514ed281afd47fa5064f5cee7b2d164bb9cb1 --- /dev/null +++ b/bsd/sys/sys/fcntl.h @@ -0,0 +1,4 @@ +#ifndef _OSV_BSD_FCNTL_H +#define _OSV_BSD_FCNTL_H +#include <fcntl.h> +#endif