[readdir] switch dcache_readdir() users to ->iterate()
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 16 May 2013 00:23:06 +0000 (20:23 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sat, 29 Jun 2013 08:46:48 +0000 (12:46 +0400)
new helpers - dir_emit_dot(file, ctx, dentry), dir_emit_dotdot(file, ctx),
dir_emit_dots(file, ctx).

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
arch/powerpc/platforms/cell/spufs/inode.c
fs/autofs4/root.c
fs/libfs.c
include/linux/fs.h

index 35f77a4..f390042 100644 (file)
@@ -238,7 +238,7 @@ const struct file_operations spufs_context_fops = {
        .release        = spufs_dir_close,
        .llseek         = dcache_dir_lseek,
        .read           = generic_read_dir,
-       .readdir        = dcache_readdir,
+       .iterate        = dcache_readdir,
        .fsync          = noop_fsync,
 };
 EXPORT_SYMBOL_GPL(spufs_context_fops);
index 085da86..ca8e555 100644 (file)
@@ -41,7 +41,7 @@ const struct file_operations autofs4_root_operations = {
        .open           = dcache_dir_open,
        .release        = dcache_dir_close,
        .read           = generic_read_dir,
-       .readdir        = dcache_readdir,
+       .iterate        = dcache_readdir,
        .llseek         = dcache_dir_lseek,
        .unlocked_ioctl = autofs4_root_ioctl,
 #ifdef CONFIG_COMPAT
@@ -53,7 +53,7 @@ const struct file_operations autofs4_dir_operations = {
        .open           = autofs4_dir_open,
        .release        = dcache_dir_close,
        .read           = generic_read_dir,
-       .readdir        = dcache_readdir,
+       .iterate        = dcache_readdir,
        .llseek         = dcache_dir_lseek,
 };
 
index 916da8c..c3a0837 100644 (file)
@@ -135,60 +135,40 @@ static inline unsigned char dt_type(struct inode *inode)
  * both impossible due to the lock on directory.
  */
 
-int dcache_readdir(struct file * filp, void * dirent, filldir_t filldir)
+int dcache_readdir(struct file *file, struct dir_context *ctx)
 {
-       struct dentry *dentry = filp->f_path.dentry;
-       struct dentry *cursor = filp->private_data;
+       struct dentry *dentry = file->f_path.dentry;
+       struct dentry *cursor = file->private_data;
        struct list_head *p, *q = &cursor->d_u.d_child;
-       ino_t ino;
-       int i = filp->f_pos;
 
-       switch (i) {
-               case 0:
-                       ino = dentry->d_inode->i_ino;
-                       if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
-                               break;
-                       filp->f_pos++;
-                       i++;
-                       /* fallthrough */
-               case 1:
-                       ino = parent_ino(dentry);
-                       if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
-                               break;
-                       filp->f_pos++;
-                       i++;
-                       /* fallthrough */
-               default:
-                       spin_lock(&dentry->d_lock);
-                       if (filp->f_pos == 2)
-                               list_move(q, &dentry->d_subdirs);
-
-                       for (p=q->next; p != &dentry->d_subdirs; p=p->next) {
-                               struct dentry *next;
-                               next = list_entry(p, struct dentry, d_u.d_child);
-                               spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
-                               if (!simple_positive(next)) {
-                                       spin_unlock(&next->d_lock);
-                                       continue;
-                               }
+       if (!dir_emit_dots(file, ctx))
+               return 0;
+       spin_lock(&dentry->d_lock);
+       if (ctx->pos == 2)
+               list_move(q, &dentry->d_subdirs);
+
+       for (p = q->next; p != &dentry->d_subdirs; p = p->next) {
+               struct dentry *next = list_entry(p, struct dentry, d_u.d_child);
+               spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
+               if (!simple_positive(next)) {
+                       spin_unlock(&next->d_lock);
+                       continue;
+               }
 
-                               spin_unlock(&next->d_lock);
-                               spin_unlock(&dentry->d_lock);
-                               if (filldir(dirent, next->d_name.name, 
-                                           next->d_name.len, filp->f_pos, 
-                                           next->d_inode->i_ino, 
-                                           dt_type(next->d_inode)) < 0)
-                                       return 0;
-                               spin_lock(&dentry->d_lock);
-                               spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
-                               /* next is still alive */
-                               list_move(q, p);
-                               spin_unlock(&next->d_lock);
-                               p = q;
-                               filp->f_pos++;
-                       }
-                       spin_unlock(&dentry->d_lock);
+               spin_unlock(&next->d_lock);
+               spin_unlock(&dentry->d_lock);
+               if (!dir_emit(ctx, next->d_name.name, next->d_name.len,
+                             next->d_inode->i_ino, dt_type(next->d_inode)))
+                       return 0;
+               spin_lock(&dentry->d_lock);
+               spin_lock_nested(&next->d_lock, DENTRY_D_LOCK_NESTED);
+               /* next is still alive */
+               list_move(q, p);
+               spin_unlock(&next->d_lock);
+               p = q;
+               ctx->pos++;
        }
+       spin_unlock(&dentry->d_lock);
        return 0;
 }
 
@@ -202,7 +182,7 @@ const struct file_operations simple_dir_operations = {
        .release        = dcache_dir_close,
        .llseek         = dcache_dir_lseek,
        .read           = generic_read_dir,
-       .readdir        = dcache_readdir,
+       .iterate        = dcache_readdir,
        .fsync          = noop_fsync,
 };
 
index b9641ae..40293a6 100644 (file)
@@ -1511,12 +1511,6 @@ struct dir_context {
        loff_t pos;
 };
 
-static inline bool dir_emit(struct dir_context *ctx,
-                           const char *name, int namelen,
-                           u64 ino, unsigned type)
-{
-       return ctx->actor(ctx, name, namelen, ctx->pos, ino, type) == 0;
-}
 struct block_device_operations;
 
 /* These macros are for out of kernel modules to test that
@@ -2537,7 +2531,7 @@ extern void iterate_supers_type(struct file_system_type *,
 extern int dcache_dir_open(struct inode *, struct file *);
 extern int dcache_dir_close(struct inode *, struct file *);
 extern loff_t dcache_dir_lseek(struct file *, loff_t, int);
-extern int dcache_readdir(struct file *, void *, filldir_t);
+extern int dcache_readdir(struct file *, struct dir_context *);
 extern int simple_setattr(struct dentry *, struct iattr *);
 extern int simple_getattr(struct vfsmount *, struct dentry *, struct kstat *);
 extern int simple_statfs(struct dentry *, struct kstatfs *);
@@ -2701,4 +2695,35 @@ static inline void inode_has_no_xattr(struct inode *inode)
                inode->i_flags |= S_NOSEC;
 }
 
+static inline bool dir_emit(struct dir_context *ctx,
+                           const char *name, int namelen,
+                           u64 ino, unsigned type)
+{
+       return ctx->actor(ctx, name, namelen, ctx->pos, ino, type) == 0;
+}
+static inline bool dir_emit_dot(struct file *file, struct dir_context *ctx)
+{
+       return ctx->actor(ctx, ".", 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, "..", 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 /* _LINUX_FS_H */