Skip to content

Commit

Permalink
Add interface for file hole punching.
Browse files Browse the repository at this point in the history
This adds an interface to "punch holes" (deallocate space) in VFS
files. The interface is identical to the Solaris VOP_SPACE interface.
This interface is necessary for TRIM support on file vdevs.

This is implemented using Linux fallocate(FALLOC_FL_PUNCH_HOLE), which
was introduced in 2.6.38. For a brief time before 2.6.38 this was done
using the truncate_range inode operation, which was quickly deprecated.
This patch only supports FALLOC_FL_PUNCH_HOLE.
  • Loading branch information
dechamps committed Sep 3, 2012
1 parent ac8ca67 commit 0c0cb0d
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 0 deletions.
23 changes: 23 additions & 0 deletions config/spl-build.m4
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 <linux/fs.h>
#include <linux/falloc.h>
],[
#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
Expand Down
6 changes: 6 additions & 0 deletions include/sys/vnode.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand Down
34 changes: 34 additions & 0 deletions module/spl/spl-vnode.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
\*****************************************************************************/

#include <sys/vnode.h>
#include <linux/falloc.h>
#include <spl-debug.h>

#ifdef SS_DEBUG_SUBSYS
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 0c0cb0d

Please sign in to comment.