]> granicus.if.org Git - zfs/commitdiff
RHEL 7.5 compat: FMODE_KABI_ITERATE
authorBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 2 May 2018 22:01:24 +0000 (15:01 -0700)
committerGitHub <noreply@github.com>
Wed, 2 May 2018 22:01:24 +0000 (15:01 -0700)
As of RHEL 7.5 the mainline fops.iterate() method was added to
the file_operations structure and is correctly detected by the
configure script.

Normally this is what we want, but in order to maintain KABI
compatibility the RHEL change additionally does the following:

* Requires that callers intending to use this extended interface
  set the FMODE_KABI_ITERATE flag on the file structure when
  opening the directory.
* Adds the fops.iterate() method to the end of the structure,
  without removing fops.readdir().

This change updates the configure check to ignore the RHEL 7.5+
variant of fops.iterate() when detected.  Instead fallback to
the fops.readdir() interface which will be available.

Finally, add the 'zpl_' prefix to the directory context wrappers
to avoid colliding with the kernel provided symbols when both
the fops.iterate() and fops.readdir() are provided by the kernel.

Reviewed-by: Olaf Faaland <faaland1@llnl.gov>
Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov>
Closes #7460
Closes #7463

config/kernel-vfs-iterate.m4
include/sys/zfs_vnops.h
include/sys/zpl.h
module/zfs/zfs_vnops.c
module/zfs/zpl_ctldir.c
module/zfs/zpl_file.c

index 7b1599e1326989b994642a90df66b32a7e8ccec3..5de901d4462e7748ee61e93c7c22214a29e2aa1a 100644 (file)
@@ -23,16 +23,27 @@ AC_DEFUN([ZFS_AC_KERNEL_VFS_ITERATE], [
                dnl #
                dnl # 3.11 API change
                dnl #
+               dnl # RHEL 7.5 compatibility; the fops.iterate() method was
+               dnl # added to the file_operations structure but in order to
+               dnl # maintain KABI compatibility all callers must set
+               dnl # FMODE_KABI_ITERATE which is checked in iterate_dir().
+               dnl # When detected ignore this interface and fallback to
+               dnl # to using fops.readdir() to retain KABI compatibility.
+               dnl #
                AC_MSG_CHECKING([whether fops->iterate() is available])
                ZFS_LINUX_TRY_COMPILE([
                        #include <linux/fs.h>
-                       int iterate(struct file *filp, struct dir_context * context)
-                           { return 0; }
+                       int iterate(struct file *filp,
+                           struct dir_context *context) { return 0; }
 
                        static const struct file_operations fops
                            __attribute__ ((unused)) = {
                                .iterate         = iterate,
                        };
+
+                       #if defined(FMODE_KABI_ITERATE)
+                       #error "RHEL 7.5, FMODE_KABI_ITERATE interface"
+                       #endif
                ],[
                ],[
                        AC_MSG_RESULT(yes)
@@ -44,8 +55,8 @@ AC_DEFUN([ZFS_AC_KERNEL_VFS_ITERATE], [
                        AC_MSG_CHECKING([whether fops->readdir() is available])
                        ZFS_LINUX_TRY_COMPILE([
                                #include <linux/fs.h>
-                               int readdir(struct file *filp, void *entry, filldir_t func)
-                                   { return 0; }
+                               int readdir(struct file *filp, void *entry,
+                                   filldir_t func) { return 0; }
 
                                static const struct file_operations fops
                                    __attribute__ ((unused)) = {
@@ -57,7 +68,7 @@ AC_DEFUN([ZFS_AC_KERNEL_VFS_ITERATE], [
                                AC_DEFINE(HAVE_VFS_READDIR, 1,
                                          [fops->readdir() is available])
                        ],[
-                               AC_MSG_ERROR(no; file a bug report with ZFSOnLinux)
+                               AC_MSG_ERROR(no; file a bug report with ZoL)
                        ])
                ])
        ])
index f2f4d13f4ed2270e737acd8aceaa6be8cb19dc14..767cba10da2b4883a47b4ab48217bb1914fd71cb 100644 (file)
@@ -54,7 +54,7 @@ extern int zfs_mkdir(struct inode *dip, char *dirname, vattr_t *vap,
     struct inode **ipp, cred_t *cr, int flags, vsecattr_t *vsecp);
 extern int zfs_rmdir(struct inode *dip, char *name, struct inode *cwd,
     cred_t *cr, int flags);
-extern int zfs_readdir(struct inode *ip, struct dir_context *ctx, cred_t *cr);
+extern int zfs_readdir(struct inode *ip, zpl_dir_context_t *ctx, cred_t *cr);
 extern int zfs_fsync(struct inode *ip, int syncflag, cred_t *cr);
 extern int zfs_getattr(struct inode *ip, vattr_t *vap, int flag, cred_t *cr);
 extern int zfs_getattr_fast(struct inode *ip, struct kstat *sp);
index 1f97f2511a37d97e78c21f03561481201139217a..65ed4313603545988644cf67065f78d8e914d99f 100644 (file)
@@ -125,56 +125,63 @@ extern const struct inode_operations zpl_ops_shares;
 
 #if defined(HAVE_VFS_ITERATE) || defined(HAVE_VFS_ITERATE_SHARED)
 
-#define        DIR_CONTEXT_INIT(_dirent, _actor, _pos) {       \
+#define        ZPL_DIR_CONTEXT_INIT(_dirent, _actor, _pos) {   \
        .actor = _actor,                                \
        .pos = _pos,                                    \
 }
 
+typedef struct dir_context zpl_dir_context_t;
+
+#define        zpl_dir_emit            dir_emit
+#define        zpl_dir_emit_dot        dir_emit_dot
+#define        zpl_dir_emit_dotdot     dir_emit_dotdot
+#define        zpl_dir_emit_dots       dir_emit_dots
+
 #else
 
-typedef struct dir_context {
+typedef struct zpl_dir_context {
        void *dirent;
        const filldir_t actor;
        loff_t pos;
-} dir_context_t;
+} zpl_dir_context_t;
 
-#define        DIR_CONTEXT_INIT(_dirent, _actor, _pos) {       \
+#define        ZPL_DIR_CONTEXT_INIT(_dirent, _actor, _pos) {   \
        .dirent = _dirent,                              \
        .actor = _actor,                                \
        .pos = _pos,                                    \
 }
 
 static inline bool
-dir_emit(struct dir_context *ctx, const char *name, int namelen,
+zpl_dir_emit(zpl_dir_context_t *ctx, const char *name, int namelen,
     uint64_t ino, unsigned type)
 {
        return (!ctx->actor(ctx->dirent, name, namelen, ctx->pos, ino, type));
 }
 
 static inline bool
-dir_emit_dot(struct file *file, struct dir_context *ctx)
+zpl_dir_emit_dot(struct file *file, zpl_dir_context_t *ctx)
 {
        return (ctx->actor(ctx->dirent, ".", 1, ctx->pos,
            file_inode(file)->i_ino, DT_DIR) == 0);
 }
 
 static inline bool
-dir_emit_dotdot(struct file *file, struct dir_context *ctx)
+zpl_dir_emit_dotdot(struct file *file, zpl_dir_context_t *ctx)
 {
        return (ctx->actor(ctx->dirent, "..", 2, ctx->pos,
            parent_ino(file_dentry(file)), DT_DIR) == 0);
 }
 
 static inline bool
-dir_emit_dots(struct file *file, struct dir_context *ctx)
+zpl_dir_emit_dots(struct file *file, zpl_dir_context_t *ctx)
 {
        if (ctx->pos == 0) {
-               if (!dir_emit_dot(file, ctx))
+               if (!zpl_dir_emit_dot(file, ctx))
                        return (false);
                ctx->pos = 1;
        }
        if (ctx->pos == 1) {
-               if (!dir_emit_dotdot(file, ctx))
+               if (!zpl_dir_emit_dotdot(file, ctx))
                        return (false);
                ctx->pos = 2;
        }
index 0eeb2bb42dd73c0935b62f4e379c2399b209bb28..d7d73201dbaf8257c15ac794ae6bc5024139f039 100644 (file)
@@ -2273,7 +2273,7 @@ out:
  */
 /* ARGSUSED */
 int
-zfs_readdir(struct inode *ip, struct dir_context *ctx, cred_t *cr)
+zfs_readdir(struct inode *ip, zpl_dir_context_t *ctx, cred_t *cr)
 {
        znode_t         *zp = ITOZ(ip);
        zfsvfs_t        *zfsvfs = ITOZSB(ip);
@@ -2378,7 +2378,7 @@ zfs_readdir(struct inode *ip, struct dir_context *ctx, cred_t *cr)
                        type = ZFS_DIRENT_TYPE(zap.za_first_integer);
                }
 
-               done = !dir_emit(ctx, zap.za_name, strlen(zap.za_name),
+               done = !zpl_dir_emit(ctx, zap.za_name, strlen(zap.za_name),
                    objnum, type);
                if (done)
                        break;
index 1c5fb34e656a02da665d87b2da566910f0f94fbb..6df367b8176a77b7a1f7ff39feaabb2c053e9e39 100644 (file)
@@ -50,27 +50,27 @@ zpl_common_open(struct inode *ip, struct file *filp)
  * Get root directory contents.
  */
 static int
-zpl_root_iterate(struct file *filp, struct dir_context *ctx)
+zpl_root_iterate(struct file *filp, zpl_dir_context_t *ctx)
 {
        zfsvfs_t *zfsvfs = ITOZSB(file_inode(filp));
        int error = 0;
 
        ZFS_ENTER(zfsvfs);
 
-       if (!dir_emit_dots(filp, ctx))
+       if (!zpl_dir_emit_dots(filp, ctx))
                goto out;
 
        if (ctx->pos == 2) {
-               if (!dir_emit(ctx, ZFS_SNAPDIR_NAME, strlen(ZFS_SNAPDIR_NAME),
-                   ZFSCTL_INO_SNAPDIR, DT_DIR))
+               if (!zpl_dir_emit(ctx, ZFS_SNAPDIR_NAME,
+                   strlen(ZFS_SNAPDIR_NAME), ZFSCTL_INO_SNAPDIR, DT_DIR))
                        goto out;
 
                ctx->pos++;
        }
 
        if (ctx->pos == 3) {
-               if (!dir_emit(ctx, ZFS_SHAREDIR_NAME, strlen(ZFS_SHAREDIR_NAME),
-                   ZFSCTL_INO_SHARES, DT_DIR))
+               if (!zpl_dir_emit(ctx, ZFS_SHAREDIR_NAME,
+                   strlen(ZFS_SHAREDIR_NAME), ZFSCTL_INO_SHARES, DT_DIR))
                        goto out;
 
                ctx->pos++;
@@ -85,7 +85,8 @@ out:
 static int
 zpl_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct dir_context ctx = DIR_CONTEXT_INIT(dirent, filldir, filp->f_pos);
+       zpl_dir_context_t ctx =
+           ZPL_DIR_CONTEXT_INIT(dirent, filldir, filp->f_pos);
        int error;
 
        error = zpl_root_iterate(filp, &ctx);
@@ -93,7 +94,7 @@ zpl_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
 
        return (error);
 }
-#endif /* HAVE_VFS_ITERATE */
+#endif /* !HAVE_VFS_ITERATE && !HAVE_VFS_ITERATE_SHARED */
 
 /*
  * Get root directory attributes.
@@ -248,7 +249,7 @@ zpl_snapdir_lookup(struct inode *dip, struct dentry *dentry,
 }
 
 static int
-zpl_snapdir_iterate(struct file *filp, struct dir_context *ctx)
+zpl_snapdir_iterate(struct file *filp, zpl_dir_context_t *ctx)
 {
        zfsvfs_t *zfsvfs = ITOZSB(file_inode(filp));
        fstrans_cookie_t cookie;
@@ -260,7 +261,7 @@ zpl_snapdir_iterate(struct file *filp, struct dir_context *ctx)
        ZFS_ENTER(zfsvfs);
        cookie = spl_fstrans_mark();
 
-       if (!dir_emit_dots(filp, ctx))
+       if (!zpl_dir_emit_dots(filp, ctx))
                goto out;
 
        pos = ctx->pos;
@@ -272,7 +273,7 @@ zpl_snapdir_iterate(struct file *filp, struct dir_context *ctx)
                if (error)
                        goto out;
 
-               if (!dir_emit(ctx, snapname, strlen(snapname),
+               if (!zpl_dir_emit(ctx, snapname, strlen(snapname),
                    ZFSCTL_INO_SHARES - id, DT_DIR))
                        goto out;
 
@@ -292,7 +293,8 @@ out:
 static int
 zpl_snapdir_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct dir_context ctx = DIR_CONTEXT_INIT(dirent, filldir, filp->f_pos);
+       zpl_dir_context_t ctx =
+           ZPL_DIR_CONTEXT_INIT(dirent, filldir, filp->f_pos);
        int error;
 
        error = zpl_snapdir_iterate(filp, &ctx);
@@ -300,7 +302,7 @@ zpl_snapdir_readdir(struct file *filp, void *dirent, filldir_t filldir)
 
        return (error);
 }
-#endif /* HAVE_VFS_ITERATE */
+#endif /* !HAVE_VFS_ITERATE && !HAVE_VFS_ITERATE_SHARED */
 
 static int
 zpl_snapdir_rename2(struct inode *sdip, struct dentry *sdentry,
@@ -463,7 +465,7 @@ zpl_shares_lookup(struct inode *dip, struct dentry *dentry,
 }
 
 static int
-zpl_shares_iterate(struct file *filp, struct dir_context *ctx)
+zpl_shares_iterate(struct file *filp, zpl_dir_context_t *ctx)
 {
        fstrans_cookie_t cookie;
        cred_t *cr = CRED();
@@ -475,7 +477,7 @@ zpl_shares_iterate(struct file *filp, struct dir_context *ctx)
        cookie = spl_fstrans_mark();
 
        if (zfsvfs->z_shares_dir == 0) {
-               dir_emit_dots(filp, ctx);
+               zpl_dir_emit_dots(filp, ctx);
                goto out;
        }
 
@@ -500,7 +502,8 @@ out:
 static int
 zpl_shares_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct dir_context ctx = DIR_CONTEXT_INIT(dirent, filldir, filp->f_pos);
+       zpl_dir_context_t ctx =
+           ZPL_DIR_CONTEXT_INIT(dirent, filldir, filp->f_pos);
        int error;
 
        error = zpl_shares_iterate(filp, &ctx);
@@ -508,7 +511,7 @@ zpl_shares_readdir(struct file *filp, void *dirent, filldir_t filldir)
 
        return (error);
 }
-#endif /* HAVE_VFS_ITERATE */
+#endif /* !HAVE_VFS_ITERATE && !HAVE_VFS_ITERATE_SHARED */
 
 /* ARGSUSED */
 static int
index 1c5f5e4096371d89016b41e483406e6a4093617d..e03a0481cff0dfd589475913134dcc774e538012 100644 (file)
@@ -76,7 +76,7 @@ zpl_release(struct inode *ip, struct file *filp)
 }
 
 static int
-zpl_iterate(struct file *filp, struct dir_context *ctx)
+zpl_iterate(struct file *filp, zpl_dir_context_t *ctx)
 {
        cred_t *cr = CRED();
        int error;
@@ -96,7 +96,8 @@ zpl_iterate(struct file *filp, struct dir_context *ctx)
 static int
 zpl_readdir(struct file *filp, void *dirent, filldir_t filldir)
 {
-       struct dir_context ctx = DIR_CONTEXT_INIT(dirent, filldir, filp->f_pos);
+       zpl_dir_context_t ctx =
+           ZPL_DIR_CONTEXT_INIT(dirent, filldir, filp->f_pos);
        int error;
 
        error = zpl_iterate(filp, &ctx);
@@ -104,7 +105,7 @@ zpl_readdir(struct file *filp, void *dirent, filldir_t filldir)
 
        return (error);
 }
-#endif /* HAVE_VFS_ITERATE */
+#endif /* !HAVE_VFS_ITERATE && !HAVE_VFS_ITERATE_SHARED */
 
 #if defined(HAVE_FSYNC_WITH_DENTRY)
 /*
@@ -965,7 +966,7 @@ const struct file_operations zpl_file_operations = {
 const struct file_operations zpl_dir_file_operations = {
        .llseek         = generic_file_llseek,
        .read           = generic_read_dir,
-#ifdef HAVE_VFS_ITERATE_SHARED
+#if defined(HAVE_VFS_ITERATE_SHARED)
        .iterate_shared = zpl_iterate,
 #elif defined(HAVE_VFS_ITERATE)
        .iterate        = zpl_iterate,