aboutsummaryrefslogtreecommitdiffstats
path: root/include/sys
diff options
context:
space:
mode:
authorRichard Yao <[email protected]>2013-08-07 08:53:45 -0400
committerBrian Behlendorf <[email protected]>2013-08-15 16:19:07 -0700
commit0f37d0c8bed442dd0d2c1b1dddd68653fa6eec66 (patch)
treebbd56b426b2b72bed0e3f81afaab2ddf5e613e3e /include/sys
parent34e143323e359b42bc9d06dd19cc4b1f13091283 (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 'include/sys')
-rw-r--r--include/sys/zfs_vnops.h4
-rw-r--r--include/sys/zpl.h59
2 files changed, 61 insertions, 2 deletions
diff --git a/include/sys/zfs_vnops.h b/include/sys/zfs_vnops.h
index 75f7c128b..c9fecf8ba 100644
--- a/include/sys/zfs_vnops.h
+++ b/include/sys/zfs_vnops.h
@@ -31,6 +31,7 @@
#include <sys/cred.h>
#include <sys/fcntl.h>
#include <sys/pathname.h>
+#include <sys/zpl.h>
#ifdef __cplusplus
extern "C" {
@@ -51,8 +52,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, void *dirent, filldir_t filldir,
- loff_t *pos, cred_t *cr);
+extern int zfs_readdir(struct inode *ip, struct dir_context *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 61a57ef29..89cf8240c 100644
--- a/include/sys/zpl.h
+++ b/include/sys/zpl.h
@@ -89,4 +89,63 @@ extern const struct inode_operations zpl_ops_snapdirs;
extern const struct file_operations zpl_fops_shares;
extern const struct inode_operations zpl_ops_shares;
+#ifdef HAVE_VFS_ITERATE
+
+#define DIR_CONTEXT_INIT(_dirent, _actor, _pos) { \
+ .actor = _actor, \
+ .pos = _pos, \
+}
+
+#else
+
+typedef struct dir_context {
+ void *dirent;
+ const filldir_t actor;
+ loff_t pos;
+} dir_context_t;
+
+#define 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,
+ uint64_t ino, unsigned type)
+{
+ return ctx->actor(ctx->dirent, name, namelen, ctx->pos, ino, type) == 0;
+}
+
+static inline bool
+dir_emit_dot(struct file *file, struct dir_context *ctx)
+{
+ return ctx->actor(ctx->dirent, ".", 1, ctx->pos,
+ file->f_path.dentry->d_inode->i_ino, DT_DIR) == 0;
+}
+
+static inline bool
+dir_emit_dotdot(struct file *file, struct dir_context *ctx)
+{
+ return ctx->actor(ctx->dirent, "..", 2, ctx->pos,
+ parent_ino(file->f_path.dentry), DT_DIR) == 0;
+}
+
+static inline bool
+dir_emit_dots(struct file *file, struct dir_context *ctx)
+{
+ if (ctx->pos == 0) {
+ if (!dir_emit_dot(file, ctx))
+ return false;
+ ctx->pos = 1;
+ }
+ if (ctx->pos == 1) {
+ if (!dir_emit_dotdot(file, ctx))
+ return false;
+ ctx->pos = 2;
+ }
+ return true;
+}
+#endif /* HAVE_VFS_ITERATE */
+
#endif /* _SYS_ZPL_H */