diff --git a/config/spl-build.m4 b/config/spl-build.m4 index b7ab54d3..aec882d6 100644 --- a/config/spl-build.m4 +++ b/config/spl-build.m4 @@ -72,6 +72,7 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [ SPL_AC_4ARGS_VFS_RENAME SPL_AC_VFS_FSYNC SPL_AC_2ARGS_VFS_FSYNC + SPL_AC_FALLOC_FL_PUNCH_HOLE SPL_AC_FS_STRUCT_SPINLOCK SPL_AC_CRED_STRUCT SPL_AC_GROUPS_SEARCH @@ -1992,6 +1993,28 @@ AC_DEFUN([SPL_AC_2ARGS_VFS_FSYNC], [ ]) ]) +dnl # +dnl # 2.6.38 API change, +dnl # check if file hole punching is available +dnl # +AC_DEFUN([SPL_AC_FALLOC_FL_PUNCH_HOLE], + [AC_MSG_CHECKING([whether kernel defines FALLOC_FL_PUNCH_HOLE]) + SPL_LINUX_TRY_COMPILE([ + #include + #include + ],[ + #ifndef FALLOC_FL_PUNCH_HOLE + #error FALLOC_FL_PUNCH_HOLE is undefined + #endif + ],[ + AC_MSG_RESULT([yes]) + AC_DEFINE(HAVE_FALLOC_FL_PUNCH_HOLE, 1, + [kernel defines FALLOC_FL_PUNCH_HOLE]) + ],[ + AC_MSG_RESULT([no]) + ]) +]) + dnl # dnl # 2.6.33 API change. Also backported in RHEL5 as of 2.6.18-190.el5. dnl # Earlier versions of rwsem_is_locked() were inline and had a race diff --git a/include/sys/vnode.h b/include/sys/vnode.h index 03462bd7..99614d55 100644 --- a/include/sys/vnode.h +++ b/include/sys/vnode.h @@ -66,6 +66,9 @@ #define FNODSYNC 0x10000 /* fsync pseudo flag */ #define FNOFOLLOW 0x20000 /* don't follow symlinks */ +#define F_FREESP 11 /* Free file space */ + + /* * The vnode AT_ flags are mapped to the Linux ATTR_* flags. * This allows them to be used safely with an iattr structure. @@ -185,6 +188,8 @@ extern int vn_remove(const char *path, uio_seg_t seg, int flags); extern int vn_rename(const char *path1, const char *path2, int x1); extern int vn_getattr(vnode_t *vp, vattr_t *vap, int flags, void *x3, void *x4); extern int vn_fsync(vnode_t *vp, int flags, void *x3, void *x4); +extern int vn_space(vnode_t *vp, int cmd, struct flock *bfp, int flag, + offset_t offset, void *x6, void *x7); extern file_t *vn_getf(int fd); extern void vn_releasef(int fd); extern int vn_set_pwd(const char *filename); @@ -197,6 +202,7 @@ void spl_vn_fini(void); #define VOP_SEEK vn_seek #define VOP_GETATTR vn_getattr #define VOP_FSYNC vn_fsync +#define VOP_SPACE vn_space #define VOP_PUTPAGE(vp, o, s, f, x1, x2) ((void)0) #define vn_is_readonly(vp) 0 #define getf vn_getf diff --git a/module/spl/spl-vnode.c b/module/spl/spl-vnode.c index 2e55b007..16a44958 100644 --- a/module/spl/spl-vnode.c +++ b/module/spl/spl-vnode.c @@ -25,6 +25,7 @@ \*****************************************************************************/ #include +#include #include #ifdef SS_DEBUG_SUBSYS @@ -510,6 +511,39 @@ int vn_fsync(vnode_t *vp, int flags, void *x3, void *x4) } /* vn_fsync() */ EXPORT_SYMBOL(vn_fsync); +int vn_space(vnode_t *vp, int cmd, struct flock *bfp, int flag, + offset_t offset, void *x6, void *x7) +{ + SENTRY; + + if (cmd != F_FREESP || bfp->l_whence != 0) + SRETURN(-EOPNOTSUPP); + + ASSERT(vp); + ASSERT(vp->v_file); + ASSERT(bfp->l_start >= 0 && bfp->l_len > 0); + +#ifndef HAVE_FALLOC_FL_PUNCH_HOLE + + SRETURN(-EOPNOTSUPP); + +#else + + if (!vp->v_file->f_op->fallocate) + SRETURN(-EOPNOTSUPP); + + /* + * TODO: on some older kernel versions the interface is a + * "truncate_range" inode operation. + */ + SRETURN(-vp->v_file->f_op->fallocate(vp->v_file, + FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE, + bfp->l_start, bfp->l_len)); + +#endif +} +EXPORT_SYMBOL(vn_space); + /* Function must be called while holding the vn_file_lock */ static file_t * file_find(int fd)