]> git.proxmox.com Git - mirror_zfs.git/commitdiff
Linux 4.11 compat: iops.getattr and friends
authorOlaf Faaland <faaland1@llnl.gov>
Tue, 21 Mar 2017 00:51:16 +0000 (17:51 -0700)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Tue, 21 Mar 2017 00:51:16 +0000 (17:51 -0700)
In torvalds/linux@a528d35, there are changes to the getattr family of functions,
struct kstat, and the interface of inode_operations .getattr.

The inode_operations .getattr and simple_getattr() interface changed to:

int (*getattr) (const struct path *, struct dentry *, struct kstat *,
    u32 request_mask, unsigned int query_flags)

The request_mask argument indicates which field(s) the caller intends to use.
Fields the caller has not specified via request_mask may be set in the returned
struct anyway, but their values may be approximate.

The query_flags argument indicates whether the filesystem must update
the attributes from the backing store.

Currently both fields are ignored.  It is possible that getattr-related
functions within zfs could be optimized based on the request_mask.

struct kstat includes new fields:
u32               result_mask;  /* What fields the user got */
u64               attributes;   /* See STATX_ATTR_* flags */
struct timespec   btime;        /* File creation time */

Fields attribute and btime are cleared; the result_mask reflects this.  These
appear to be optional based on simple_getattr() and vfs_getattr() within the
kernel, which take the same approach.

Reviewed-by: Chunwei Chen <david.chen@osnexus.com>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Olaf Faaland <faaland1@llnl.gov>
Closes #5875

config/kernel-inode-getattr.m4 [new file with mode: 0644]
config/kernel.m4
include/linux/vfs_compat.h
module/zfs/zpl_ctldir.c
module/zfs/zpl_inode.c

diff --git a/config/kernel-inode-getattr.m4 b/config/kernel-inode-getattr.m4
new file mode 100644 (file)
index 0000000..f10e0b2
--- /dev/null
@@ -0,0 +1,67 @@
+dnl #
+dnl # Linux 4.11 API
+dnl # See torvalds/linux@a528d35
+dnl #
+AC_DEFUN([ZFS_AC_PATH_KERNEL_IOPS_GETATTR], [
+       AC_MSG_CHECKING([whether iops->getattr() takes a path])
+       ZFS_LINUX_TRY_COMPILE([
+               #include <linux/fs.h>
+
+               int test_getattr(
+                   const struct path *p, struct kstat *k,
+                   u32 request_mask, unsigned int query_flags)
+                   { return 0; }
+
+               static const struct inode_operations
+                   iops __attribute__ ((unused)) = {
+                       .getattr = test_getattr,
+               };
+       ],[
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_PATH_IOPS_GETATTR, 1,
+                   [iops->getattr() takes a path])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+])
+
+
+
+dnl #
+dnl # Linux 3.9 - 4.10 API
+dnl #
+AC_DEFUN([ZFS_AC_VFSMOUNT_KERNEL_IOPS_GETATTR], [
+       AC_MSG_CHECKING([whether iops->getattr() takes a vfsmount])
+       ZFS_LINUX_TRY_COMPILE([
+               #include <linux/fs.h>
+
+               int test_getattr(
+                   struct vfsmount *mnt, struct dentry *d,
+                   struct kstat *k)
+                   { return 0; }
+
+               static const struct inode_operations
+                   iops __attribute__ ((unused)) = {
+                       .getattr = test_getattr,
+               };
+       ],[
+       ],[
+               AC_MSG_RESULT(yes)
+               AC_DEFINE(HAVE_VFSMOUNT_IOPS_GETATTR, 1,
+                   [iops->getattr() takes a vfsmount])
+       ],[
+               AC_MSG_RESULT(no)
+       ])
+])
+
+
+dnl #
+dnl # The interface of the getattr callback from the inode_operations
+dnl # structure changed.  Also, the interface of the simple_getattr()
+dnl # function provided by the kernel changed.
+dnl #
+AC_DEFUN([ZFS_AC_KERNEL_INODE_OPERATIONS_GETATTR], [
+       ZFS_AC_PATH_KERNEL_IOPS_GETATTR
+       ZFS_AC_VFSMOUNT_KERNEL_IOPS_GETATTR
+])
index 0b50a54e3fff6d76e928dbcc50925fcf326fb8b8..25271cedcd8d9c4964774ca41dfb42fb13196462 100644 (file)
@@ -59,6 +59,7 @@ AC_DEFUN([ZFS_AC_CONFIG_KERNEL], [
        ZFS_AC_KERNEL_INODE_OPERATIONS_CHECK_ACL_WITH_FLAGS
        ZFS_AC_KERNEL_INODE_OPERATIONS_GET_ACL
        ZFS_AC_KERNEL_INODE_OPERATIONS_SET_ACL
+       ZFS_AC_KERNEL_INODE_OPERATIONS_GETATTR
        ZFS_AC_KERNEL_INODE_SET_FLAGS
        ZFS_AC_KERNEL_GET_ACL_HANDLE_CACHE
        ZFS_AC_KERNEL_SHOW_OPTIONS
index baa29801822b3f34b7d3af78e2876ce3ff0a278a..cd22b522ab79d7b93652011bf861eb0f40fe6321 100644 (file)
@@ -454,4 +454,47 @@ setattr_prepare(struct dentry *dentry, struct iattr *ia)
 }
 #endif
 
+/*
+ * 4.11 API change
+ * These macros are defined by kernel 4.11.  We define them so that the same
+ * code builds under kernels < 4.11 and >= 4.11.  The macros are set to 0 so
+ * that it will create obvious failures if they are accidentally used when built
+ * against a kernel >= 4.11.
+ */
+
+#ifndef STATX_BASIC_STATS
+#define        STATX_BASIC_STATS       0
+#endif
+
+#ifndef AT_STATX_SYNC_AS_STAT
+#define        AT_STATX_SYNC_AS_STAT   0
+#endif
+
+/*
+ * 4.11 API change
+ * 4.11 takes struct path *, < 4.11 takes vfsmount *
+ */
+
+#ifdef HAVE_VFSMOUNT_IOPS_GETATTR
+#define        ZPL_GETATTR_WRAPPER(func)                                       \
+static int                                                             \
+func(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)  \
+{                                                                      \
+       struct path path = { .mnt = mnt, .dentry = dentry };            \
+       return func##_impl(&path, stat, STATX_BASIC_STATS,              \
+           AT_STATX_SYNC_AS_STAT);                                     \
+}
+#elif defined(HAVE_PATH_IOPS_GETATTR)
+#define        ZPL_GETATTR_WRAPPER(func)                                       \
+static int                                                             \
+func(const struct path *path, struct kstat *stat, u32 request_mask,    \
+    unsigned int query_flags)                                          \
+{                                                                      \
+       return (func##_impl(path, stat, request_mask, query_flags));    \
+}
+#else
+#error
+#endif
+
+
 #endif /* _ZFS_VFS_H */
index b6a3b669d1f3a9880ad550bc77ec796665ce74a8..bd8af3928835ac4f07f310e617049d22a6a0f4cd 100644 (file)
@@ -100,16 +100,15 @@ zpl_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
  */
 /* ARGSUSED */
 static int
-zpl_root_getattr(struct vfsmount *mnt, struct dentry *dentry,
-    struct kstat *stat)
+zpl_root_getattr_impl(const struct path *path, struct kstat *stat,
+    u32 request_mask, unsigned int query_flags)
 {
-       int error;
-
-       error = simple_getattr(mnt, dentry, stat);
+       generic_fillattr(path->dentry->d_inode, stat);
        stat->atime = CURRENT_TIME;
 
-       return (error);
+       return (0);
 }
+ZPL_GETATTR_WRAPPER(zpl_root_getattr);
 
 static struct dentry *
 #ifdef HAVE_LOOKUP_NAMEIDATA
@@ -375,21 +374,22 @@ zpl_snapdir_mkdir(struct inode *dip, struct dentry *dentry, zpl_umode_t mode)
  */
 /* ARGSUSED */
 static int
-zpl_snapdir_getattr(struct vfsmount *mnt, struct dentry *dentry,
-    struct kstat *stat)
+zpl_snapdir_getattr_impl(const struct path *path, struct kstat *stat,
+    u32 request_mask, unsigned int query_flags)
 {
-       zfsvfs_t *zfsvfs = ITOZSB(dentry->d_inode);
-       int error;
+       zfsvfs_t *zfsvfs = ITOZSB(path->dentry->d_inode);
 
        ZFS_ENTER(zfsvfs);
-       error = simple_getattr(mnt, dentry, stat);
+       generic_fillattr(path->dentry->d_inode, stat);
+
        stat->nlink = stat->size = 2;
        stat->ctime = stat->mtime = dmu_objset_snap_cmtime(zfsvfs->z_os);
        stat->atime = CURRENT_TIME;
        ZFS_EXIT(zfsvfs);
 
-       return (error);
+       return (0);
 }
+ZPL_GETATTR_WRAPPER(zpl_snapdir_getattr);
 
 /*
  * The '.zfs/snapshot' directory file operations.  These mainly control
@@ -509,10 +509,10 @@ zpl_shares_readdir(struct file *filp, void *dirent, filldir_t filldir)
 
 /* ARGSUSED */
 static int
-zpl_shares_getattr(struct vfsmount *mnt, struct dentry *dentry,
-    struct kstat *stat)
+zpl_shares_getattr_impl(const struct path *path, struct kstat *stat,
+    u32 request_mask, unsigned int query_flags)
 {
-       struct inode *ip = dentry->d_inode;
+       struct inode *ip = path->dentry->d_inode;
        zfsvfs_t *zfsvfs = ITOZSB(ip);
        znode_t *dzp;
        int error;
@@ -520,11 +520,11 @@ zpl_shares_getattr(struct vfsmount *mnt, struct dentry *dentry,
        ZFS_ENTER(zfsvfs);
 
        if (zfsvfs->z_shares_dir == 0) {
-               error = simple_getattr(mnt, dentry, stat);
+               generic_fillattr(path->dentry->d_inode, stat);
                stat->nlink = stat->size = 2;
                stat->atime = CURRENT_TIME;
                ZFS_EXIT(zfsvfs);
-               return (error);
+               return (0);
        }
 
        error = -zfs_zget(zfsvfs, zfsvfs->z_shares_dir, &dzp);
@@ -538,6 +538,7 @@ zpl_shares_getattr(struct vfsmount *mnt, struct dentry *dentry,
 
        return (error);
 }
+ZPL_GETATTR_WRAPPER(zpl_shares_getattr);
 
 /*
  * The '.zfs/shares' directory file operations.
index 2e438eaff8c221ab9a050061e15ce2fea3568040..8351ab5a0c62b2fff32c830181f677137b9de442 100644 (file)
@@ -340,18 +340,25 @@ zpl_rmdir(struct inode *dir, struct dentry *dentry)
 }
 
 static int
-zpl_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+zpl_getattr_impl(const struct path *path, struct kstat *stat, u32 request_mask,
+    unsigned int query_flags)
 {
        int error;
        fstrans_cookie_t cookie;
 
        cookie = spl_fstrans_mark();
-       error = -zfs_getattr_fast(dentry->d_inode, stat);
+
+       /*
+        * XXX request_mask and query_flags currently ignored.
+        */
+
+       error = -zfs_getattr_fast(path->dentry->d_inode, stat);
        spl_fstrans_unmark(cookie);
        ASSERT3S(error, <=, 0);
 
        return (error);
 }
+ZPL_GETATTR_WRAPPER(zpl_getattr);
 
 static int
 zpl_setattr(struct dentry *dentry, struct iattr *ia)