Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RHEL 7.5 compat: FMODE_KABI_ITERATE #7463

Merged
merged 1 commit into from
May 2, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions config/kernel-vfs-iterate.m4
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)) = {
Expand All @@ -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)
])
])
])
Expand Down
2 changes: 1 addition & 1 deletion include/sys/zfs_vnops.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
27 changes: 17 additions & 10 deletions include/sys/zpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
4 changes: 2 additions & 2 deletions module/zfs/zfs_vnops.c
Original file line number Diff line number Diff line change
Expand Up @@ -2273,7 +2273,7 @@ zfs_rmdir(struct inode *dip, char *name, struct inode *cwd, cred_t *cr,
*/
/* 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);
Expand Down Expand Up @@ -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;
Expand Down
37 changes: 20 additions & 17 deletions module/zfs/zpl_ctldir.c
Original file line number Diff line number Diff line change
Expand Up @@ -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++;
Expand All @@ -85,15 +85,16 @@ zpl_root_iterate(struct file *filp, struct dir_context *ctx)
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);
filp->f_pos = ctx.pos;

return (error);
}
#endif /* HAVE_VFS_ITERATE */
#endif /* !HAVE_VFS_ITERATE && !HAVE_VFS_ITERATE_SHARED */

/*
* Get root directory attributes.
Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;

Expand All @@ -292,15 +293,16 @@ zpl_snapdir_iterate(struct file *filp, struct dir_context *ctx)
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);
filp->f_pos = ctx.pos;

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,
Expand Down Expand Up @@ -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();
Expand All @@ -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;
}

Expand All @@ -500,15 +502,16 @@ zpl_shares_iterate(struct file *filp, struct dir_context *ctx)
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);
filp->f_pos = ctx.pos;

return (error);
}
#endif /* HAVE_VFS_ITERATE */
#endif /* !HAVE_VFS_ITERATE && !HAVE_VFS_ITERATE_SHARED */

/* ARGSUSED */
static int
Expand Down
9 changes: 5 additions & 4 deletions module/zfs/zpl_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -96,15 +96,16 @@ 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);
filp->f_pos = ctx.pos;

return (error);
}
#endif /* HAVE_VFS_ITERATE */
#endif /* !HAVE_VFS_ITERATE && !HAVE_VFS_ITERATE_SHARED */

#if defined(HAVE_FSYNC_WITH_DENTRY)
/*
Expand Down Expand Up @@ -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,
Expand Down