diff options
author | Brian Behlendorf <[email protected]> | 2018-05-02 15:01:24 -0700 |
---|---|---|
committer | GitHub <[email protected]> | 2018-05-02 15:01:24 -0700 |
commit | 9464b9591ea5cd61a4d6ef8e29c4597b48d16a77 (patch) | |
tree | 549b75c9d264a4b1da403268ccbb49f20e4ef4e6 /include/sys | |
parent | bc8a6a60e9f0fd219e10f355384d87a41d4f5882 (diff) |
RHEL 7.5 compat: FMODE_KABI_ITERATE
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 <[email protected]>
Reviewed-by: Tony Hutter <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Closes #7460
Closes #7463
Diffstat (limited to 'include/sys')
-rw-r--r-- | include/sys/zfs_vnops.h | 2 | ||||
-rw-r--r-- | include/sys/zpl.h | 27 |
2 files changed, 18 insertions, 11 deletions
diff --git a/include/sys/zfs_vnops.h b/include/sys/zfs_vnops.h index f2f4d13f4..767cba10d 100644 --- a/include/sys/zfs_vnops.h +++ b/include/sys/zfs_vnops.h @@ -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); diff --git a/include/sys/zpl.h b/include/sys/zpl.h index 1f97f2511..65ed43136 100644 --- a/include/sys/zpl.h +++ b/include/sys/zpl.h @@ -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; } |