]> git.proxmox.com Git - mirror_spl-debian.git/commitdiff
RHEL 6.4 compat, fallocate()
authorBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 8 Jan 2013 17:42:49 +0000 (09:42 -0800)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 8 Jan 2013 17:53:13 +0000 (09:53 -0800)
In the upstream kernel the FALLOC_FL_PUNCH_HOLE #define was
introduced after the fallocate() function was moved from the
inode_operations to the file_operations structure.  Therefore,
the SPL code assumed that if FALLOC_FL_PUNCH_HOLE was defined
it was safe to use f_ops->fallocate().

Unfortunately, the RHEL6.4 kernel has only backported the
FALLOC_FL_PUNCH_HOLE #define and not the fallocate() change.

To address this compatibility issue the spl_filp_fallocate()
helper function was added to properly detect which interface
is available.

Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
config/spl-build.m4
include/linux/file_compat.h
module/spl/spl-vnode.c

index ea25e206f1147863db8d6297810f783c51bae58a..f710d8e953b6b93537d4f49f6da0922f73e869b8 100644 (file)
@@ -78,6 +78,7 @@ AC_DEFUN([SPL_AC_CONFIG_KERNEL], [
        SPL_AC_EXPORTED_RWSEM_IS_LOCKED
        SPL_AC_KERNEL_INVALIDATE_INODES
        SPL_AC_KERNEL_2ARGS_INVALIDATE_INODES
+       SPL_AC_KERNEL_FALLOCATE
        SPL_AC_SHRINK_DCACHE_MEMORY
        SPL_AC_SHRINK_ICACHE_MEMORY
        SPL_AC_KERN_PATH_PARENT_HEADER
@@ -1922,7 +1923,6 @@ AC_DEFUN([SPL_AC_2ARGS_VFS_FSYNC], [
 dnl #
 dnl # 3.5 API change,
 dnl # inode_operations.truncate_range removed
-dnl # (deprecated in favor of FALLOC_FL_PUNCH_HOLE)
 dnl #
 AC_DEFUN([SPL_AC_INODE_TRUNCATE_RANGE], [
        AC_MSG_CHECKING([whether truncate_range() inode operation is available])
@@ -1938,7 +1938,77 @@ AC_DEFUN([SPL_AC_INODE_TRUNCATE_RANGE], [
        ],[
                AC_MSG_RESULT(no)
        ])
-]))
+])
+
+dnl #
+dnl # Linux 2.6.38 - 3.x API
+dnl #
+AC_DEFUN([SPL_AC_KERNEL_FILE_FALLOCATE], [
+       AC_MSG_CHECKING([whether fops->fallocate() exists])
+       SPL_LINUX_TRY_COMPILE([
+               #include <linux/fs.h>
+       ],[
+               long (*fallocate) (struct file *, int, loff_t, loff_t) = NULL;
+               struct file_operations fops __attribute__ ((unused)) = {
+                       .fallocate = fallocate,
+               };
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_FILE_FALLOCATE, 1, [fops->fallocate() exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+])
+
+dnl #
+dnl # Linux 2.6.x - 2.6.37 API
+dnl #
+AC_DEFUN([SPL_AC_KERNEL_INODE_FALLOCATE], [
+       AC_MSG_CHECKING([whether iops->fallocate() exists])
+       SPL_LINUX_TRY_COMPILE([
+               #include <linux/fs.h>
+       ],[
+               long (*fallocate) (struct inode *, int, loff_t, loff_t) = NULL;
+               struct inode_operations fops __attribute__ ((unused)) = {
+                       .fallocate = fallocate,
+               };
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_INODE_FALLOCATE, 1, [fops->fallocate() exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+])
+
+dnl #
+dnl # PaX Linux 2.6.38 - 3.x API
+dnl #
+AC_DEFUN([SPL_AC_PAX_KERNEL_FILE_FALLOCATE], [
+       AC_MSG_CHECKING([whether fops->fallocate() exists])
+       SPL_LINUX_TRY_COMPILE([
+               #include <linux/fs.h>
+       ],[
+               long (*fallocate) (struct file *, int, loff_t, loff_t) = NULL;
+               struct file_operations_no_const fops __attribute__ ((unused)) = {
+                       .fallocate = fallocate,
+               };
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_FILE_FALLOCATE, 1, [fops->fallocate() exists])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+])
+
+dnl #
+dnl # The fallocate callback was moved from the inode_operations
+dnl # structure to the file_operations structure.
+dnl #
+AC_DEFUN([SPL_AC_KERNEL_FALLOCATE], [
+       SPL_AC_KERNEL_FILE_FALLOCATE
+       SPL_AC_KERNEL_INODE_FALLOCATE
+       SPL_AC_PAX_KERNEL_FILE_FALLOCATE
+])
 
 dnl #
 dnl # 2.6.33 API change. Also backported in RHEL5 as of 2.6.18-190.el5.
index 8664df672a795f26b4aa881103bcbdb0579140e1..3dc33278ffc1b6d00a968784aa7d7cf829a52009 100644 (file)
@@ -50,6 +50,26 @@ spl_filp_open(const char *name, int flags, int mode, int *err)
 #define spl_filp_poff(f)               (&(f)->f_pos)
 #define spl_filp_write(fp, b, s, p)    (fp)->f_op->write((fp), (b), (s), p)
 
+static inline int
+spl_filp_fallocate(struct file *fp, int mode, loff_t offset, loff_t len)
+{
+       int error = -EOPNOTSUPP;
+
+#ifdef HAVE_FILE_FALLOCATE
+       if (fp->f_op->fallocate)
+               error = fp->f_op->fallocate(fp, mode, offset, len);
+#else
+# ifdef HAVE_INODE_FALLOCATE
+       if (fp->f_dentry && fp->f_dentry->d_inode &&
+           fp->f_dentry->d_inode->i_op->fallocate)
+               error = fp->f_dentry->d_inode->i_op->fallocate(
+                   fp->f_dentry->d_inode, mode, offset, len);
+# endif /* HAVE_INODE_FALLOCATE */
+#endif /*HAVE_FILE_FALLOCATE */
+
+       return (error);
+}
+
 #ifdef HAVE_VFS_FSYNC
 # ifdef HAVE_2ARGS_VFS_FSYNC
 #  define spl_filp_fsync(fp, sync)     vfs_fsync(fp, sync)
index 0ecd9addfa06f3d184c0cf60a794be07fdd28289..d8da9814b75a9b33714e8de8cb42950682ccaddb 100644 (file)
@@ -654,13 +654,15 @@ int vn_space(vnode_t *vp, int cmd, struct flock *bfp, int flag,
        ASSERT(bfp->l_start >= 0 && bfp->l_len > 0);
 
 #ifdef FALLOC_FL_PUNCH_HOLE
-       if (vp->v_file->f_op->fallocate) {
-               error = -vp->v_file->f_op->fallocate(vp->v_file,
-                   FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE,
-                   bfp->l_start, bfp->l_len);
-               if (!error)
-                       SRETURN(0);
-       }
+       /*
+        * When supported by the underlying file system preferentially
+        * use the fallocate() callback to preallocate the space.
+        */
+       error = -spl_filp_fallocate(vp->v_file,
+           FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE,
+           bfp->l_start, bfp->l_len);
+       if (error == 0)
+               SRETURN(0);
 #endif
 
 #ifdef HAVE_INODE_TRUNCATE_RANGE