diff options
author | Richard Yao <[email protected]> | 2013-08-07 08:53:45 -0400 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2013-08-15 16:19:07 -0700 |
commit | 0f37d0c8bed442dd0d2c1b1dddd68653fa6eec66 (patch) | |
tree | bbd56b426b2b72bed0e3f81afaab2ddf5e613e3e /module/zfs/zpl_ctldir.c | |
parent | 34e143323e359b42bc9d06dd19cc4b1f13091283 (diff) |
Linux 3.11 compat: fops->iterate()
Commit torvalds/linux@2233f31aade393641f0eaed43a71110e629bb900
replaced ->readdir() with ->iterate() in struct file_operations.
All filesystems must now use the new ->iterate method.
To handle this the code was reworked to use the new ->iterate
interface. Care was taken to keep the majority of changes
confined to the ZPL layer which is already Linux specific.
However, minor changes were required to the common zfs_readdir()
function.
Compatibility with older kernels was accomplished by adding
versions of the trivial dir_emit* helper functions. Also the
various *_readdir() functions were reworked in to wrappers
which create a dir_context structure to pass to the new
*_iterate() functions.
Unfortunately, the new dir_emit* functions prevent us from
passing a private pointer to the filldir function. The xattr
directory code leveraged this ability through zfs_readdir()
to generate the list of xattr names. Since we can no longer
use zfs_readdir() a simplified zpl_xattr_readdir() function
was added to perform the same task.
Signed-off-by: Richard Yao <[email protected]>
Signed-off-by: Brian Behlendorf <[email protected]>
Closes #1653
Issue #1591
Diffstat (limited to 'module/zfs/zpl_ctldir.c')
-rw-r--r-- | module/zfs/zpl_ctldir.c | 193 |
1 files changed, 89 insertions, 104 deletions
diff --git a/module/zfs/zpl_ctldir.c b/module/zfs/zpl_ctldir.c index 089701707..1bb646fdf 100644 --- a/module/zfs/zpl_ctldir.c +++ b/module/zfs/zpl_ctldir.c @@ -46,79 +46,34 @@ zpl_common_open(struct inode *ip, struct file *filp) return generic_file_open(ip, filp); } -static int -zpl_common_readdir(struct file *filp, void *dirent, filldir_t filldir) -{ - struct dentry *dentry = filp->f_path.dentry; - struct inode *ip = dentry->d_inode; - int error = 0; - - switch (filp->f_pos) { - case 0: - error = filldir(dirent, ".", 1, 0, ip->i_ino, DT_DIR); - if (error) - break; - - filp->f_pos++; - /* fall-thru */ - case 1: - error = filldir(dirent, "..", 2, 1, parent_ino(dentry), DT_DIR); - if (error) - break; - - filp->f_pos++; - /* fall-thru */ - default: - break; - } - - return (error); -} - /* * Get root directory contents. */ static int -zpl_root_readdir(struct file *filp, void *dirent, filldir_t filldir) +zpl_root_iterate(struct file *filp, struct dir_context *ctx) { - struct dentry *dentry = filp->f_path.dentry; - struct inode *ip = dentry->d_inode; - zfs_sb_t *zsb = ITOZSB(ip); + zfs_sb_t *zsb = ITOZSB(filp->f_path.dentry->d_inode); int error = 0; ZFS_ENTER(zsb); - switch (filp->f_pos) { - case 0: - error = filldir(dirent, ".", 1, 0, ip->i_ino, DT_DIR); - if (error) - goto out; + if (!dir_emit_dots(filp, ctx)) + goto out; - filp->f_pos++; - /* fall-thru */ - case 1: - error = filldir(dirent, "..", 2, 1, parent_ino(dentry), DT_DIR); - if (error) + if (ctx->pos == 2) { + if (!dir_emit(ctx, ZFS_SNAPDIR_NAME, strlen(ZFS_SNAPDIR_NAME), + ZFSCTL_INO_SNAPDIR, DT_DIR)) goto out; - filp->f_pos++; - /* fall-thru */ - case 2: - error = filldir(dirent, ZFS_SNAPDIR_NAME, - strlen(ZFS_SNAPDIR_NAME), 2, ZFSCTL_INO_SNAPDIR, DT_DIR); - if (error) - goto out; + ctx->pos++; + } - filp->f_pos++; - /* fall-thru */ - case 3: - error = filldir(dirent, ZFS_SHAREDIR_NAME, - strlen(ZFS_SHAREDIR_NAME), 3, ZFSCTL_INO_SHARES, DT_DIR); - if (error) + if (ctx->pos == 3) { + if (!dir_emit(ctx, ZFS_SHAREDIR_NAME, strlen(ZFS_SHAREDIR_NAME), + ZFSCTL_INO_SHARES, DT_DIR)) goto out; - filp->f_pos++; - /* fall-thru */ + ctx->pos++; } out: ZFS_EXIT(zsb); @@ -126,6 +81,20 @@ out: return (error); } +#if !defined(HAVE_VFS_ITERATE) +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); + int error; + + error = zpl_root_iterate(filp, &ctx); + filp->f_pos = ctx.pos; + + return (error); +} +#endif /* HAVE_VFS_ITERATE */ + /* * Get root directory attributes. */ @@ -175,7 +144,11 @@ const struct file_operations zpl_fops_root = { .open = zpl_common_open, .llseek = generic_file_llseek, .read = generic_read_dir, +#ifdef HAVE_VFS_ITERATE + .iterate = zpl_root_iterate, +#else .readdir = zpl_root_readdir, +#endif }; const struct inode_operations zpl_ops_root = { @@ -273,50 +246,29 @@ zpl_snapdir_lookup(struct inode *dip, struct dentry *dentry, return d_splice_alias(ip, dentry); } -/* ARGSUSED */ static int -zpl_snapdir_readdir(struct file *filp, void *dirent, filldir_t filldir) +zpl_snapdir_iterate(struct file *filp, struct dir_context *ctx) { - struct dentry *dentry = filp->f_path.dentry; - struct inode *dip = dentry->d_inode; - zfs_sb_t *zsb = ITOZSB(dip); + zfs_sb_t *zsb = ITOZSB(filp->f_path.dentry->d_inode); char snapname[MAXNAMELEN]; - uint64_t id, cookie; boolean_t case_conflict; + uint64_t id; int error = 0; ZFS_ENTER(zsb); - cookie = filp->f_pos; - switch (filp->f_pos) { - case 0: - error = filldir(dirent, ".", 1, 0, dip->i_ino, DT_DIR); - if (error) - goto out; + if (!dir_emit_dots(filp, ctx)) + goto out; - filp->f_pos++; - /* fall-thru */ - case 1: - error = filldir(dirent, "..", 2, 1, parent_ino(dentry), DT_DIR); + while (error == 0) { + error = -dmu_snapshot_list_next(zsb->z_os, MAXNAMELEN, + snapname, &id, &(ctx->pos), &case_conflict); if (error) goto out; - filp->f_pos++; - /* fall-thru */ - default: - while (error == 0) { - error = -dmu_snapshot_list_next(zsb->z_os, MAXNAMELEN, - snapname, &id, &cookie, &case_conflict); - if (error) - goto out; - - error = filldir(dirent, snapname, strlen(snapname), - filp->f_pos, ZFSCTL_INO_SHARES - id, DT_DIR); - if (error) - goto out; - - filp->f_pos = cookie; - } + if (!dir_emit(ctx, snapname, strlen(snapname), + ZFSCTL_INO_SHARES - id, DT_DIR)) + goto out; } out: ZFS_EXIT(zsb); @@ -327,6 +279,20 @@ out: return (error); } +#if !defined(HAVE_VFS_ITERATE) +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); + int error; + + error = zpl_snapdir_iterate(filp, &ctx); + filp->f_pos = ctx.pos; + + return (error); +} +#endif /* HAVE_VFS_ITERATE */ + int zpl_snapdir_rename(struct inode *sdip, struct dentry *sdentry, struct inode *tdip, struct dentry *tdentry) @@ -413,7 +379,12 @@ const struct file_operations zpl_fops_snapdir = { .open = zpl_common_open, .llseek = generic_file_llseek, .read = generic_read_dir, +#ifdef HAVE_VFS_ITERATE + .iterate = zpl_snapdir_iterate, +#else .readdir = zpl_snapdir_readdir, +#endif + }; /* @@ -458,42 +429,51 @@ zpl_shares_lookup(struct inode *dip, struct dentry *dentry, return d_splice_alias(ip, dentry); } -/* ARGSUSED */ static int -zpl_shares_readdir(struct file *filp, void *dirent, filldir_t filldir) +zpl_shares_iterate(struct file *filp, struct dir_context *ctx) { cred_t *cr = CRED(); - struct dentry *dentry = filp->f_path.dentry; - struct inode *ip = dentry->d_inode; - zfs_sb_t *zsb = ITOZSB(ip); + zfs_sb_t *zsb = ITOZSB(filp->f_path.dentry->d_inode); znode_t *dzp; - int error; + int error = 0; ZFS_ENTER(zsb); if (zsb->z_shares_dir == 0) { - error = zpl_common_readdir(filp, dirent, filldir); - ZFS_EXIT(zsb); - return (error); + dir_emit_dots(filp, ctx); + goto out; } error = -zfs_zget(zsb, zsb->z_shares_dir, &dzp); - if (error) { - ZFS_EXIT(zsb); - return (error); - } + if (error) + goto out; crhold(cr); - error = -zfs_readdir(ZTOI(dzp), dirent, filldir, &filp->f_pos, cr); + error = -zfs_readdir(ZTOI(dzp), ctx, cr); crfree(cr); iput(ZTOI(dzp)); +out: ZFS_EXIT(zsb); ASSERT3S(error, <=, 0); return (error); } +#if !defined(HAVE_VFS_ITERATE) +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); + int error; + + error = zpl_shares_iterate(filp, &ctx); + filp->f_pos = ctx.pos; + + return (error); +} +#endif /* HAVE_VFS_ITERATE */ + /* ARGSUSED */ static int zpl_shares_getattr(struct vfsmount *mnt, struct dentry *dentry, @@ -532,7 +512,12 @@ const struct file_operations zpl_fops_shares = { .open = zpl_common_open, .llseek = generic_file_llseek, .read = generic_read_dir, +#ifdef HAVE_VFS_ITERATE + .iterate = zpl_shares_iterate, +#else .readdir = zpl_shares_readdir, +#endif + }; /* |