[readdir] convert coda
authorAl Viro <viro@zeniv.linux.org.uk>
Thu, 23 May 2013 01:15:30 +0000 (21:15 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sat, 29 Jun 2013 08:57:03 +0000 (12:57 +0400)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/coda/dir.c

index fc66861..87e0ee9 100644 (file)
@@ -43,15 +43,14 @@ static int coda_rename(struct inode *old_inode, struct dentry *old_dentry,
                        struct inode *new_inode, struct dentry *new_dentry);
 
 /* dir file-ops */
-static int coda_readdir(struct file *file, void *buf, filldir_t filldir);
+static int coda_readdir(struct file *file, struct dir_context *ctx);
 
 /* dentry ops */
 static int coda_dentry_revalidate(struct dentry *de, unsigned int flags);
 static int coda_dentry_delete(const struct dentry *);
 
 /* support routines */
-static int coda_venus_readdir(struct file *coda_file, void *buf,
-                             filldir_t filldir);
+static int coda_venus_readdir(struct file *, struct dir_context *);
 
 /* same as fs/bad_inode.c */
 static int coda_return_EIO(void)
@@ -85,7 +84,7 @@ const struct inode_operations coda_dir_inode_operations =
 const struct file_operations coda_dir_operations = {
        .llseek         = generic_file_llseek,
        .read           = generic_read_dir,
-       .readdir        = coda_readdir,
+       .iterate        = coda_readdir,
        .open           = coda_open,
        .release        = coda_release,
        .fsync          = coda_fsync,
@@ -378,7 +377,7 @@ static int coda_rename(struct inode *old_dir, struct dentry *old_dentry,
 
 
 /* file operations for directories */
-static int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir)
+static int coda_readdir(struct file *coda_file, struct dir_context *ctx)
 {
        struct coda_file_info *cfi;
        struct file *host_file;
@@ -391,28 +390,8 @@ static int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir)
        if (!host_file->f_op)
                return -ENOTDIR;
 
-       if (host_file->f_op->readdir) {
-               /* potemkin case: we were handed a directory inode.
-                * We can't use vfs_readdir because we have to keep the file
-                * position in sync between the coda_file and the host_file.
-                * and as such we need grab the inode mutex. */
+       if (host_file->f_op->iterate) {
                struct inode *host_inode = file_inode(host_file);
-
-               mutex_lock(&host_inode->i_mutex);
-               host_file->f_pos = coda_file->f_pos;
-
-               ret = -ENOENT;
-               if (!IS_DEADDIR(host_inode)) {
-                       ret = host_file->f_op->readdir(host_file, buf, filldir);
-                       file_accessed(host_file);
-               }
-
-               coda_file->f_pos = host_file->f_pos;
-               mutex_unlock(&host_inode->i_mutex);
-       } else if (host_file->f_op->iterate) {
-               struct inode *host_inode = file_inode(host_file);
-               struct dir_context *ctx = buf;
-
                mutex_lock(&host_inode->i_mutex);
                ret = -ENOENT;
                if (!IS_DEADDIR(host_inode)) {
@@ -420,12 +399,10 @@ static int coda_readdir(struct file *coda_file, void *buf, filldir_t filldir)
                        file_accessed(host_file);
                }
                mutex_unlock(&host_inode->i_mutex);
-
-               coda_file->f_pos = ctx->pos;
-       } else /* Venus: we must read Venus dirents from a file */
-               ret = coda_venus_readdir(coda_file, buf, filldir);
-
-       return ret;
+               return ret;
+       }
+       /* Venus: we must read Venus dirents from a file */
+       return coda_venus_readdir(coda_file, ctx);
 }
 
 static inline unsigned int CDT2DT(unsigned char cdt)
@@ -448,10 +425,8 @@ static inline unsigned int CDT2DT(unsigned char cdt)
 }
 
 /* support routines */
-static int coda_venus_readdir(struct file *coda_file, void *buf,
-                             filldir_t filldir)
+static int coda_venus_readdir(struct file *coda_file, struct dir_context *ctx)
 {
-       int result = 0; /* # of entries returned */
        struct coda_file_info *cfi;
        struct coda_inode_info *cii;
        struct file *host_file;
@@ -473,23 +448,12 @@ static int coda_venus_readdir(struct file *coda_file, void *buf,
        vdir = kmalloc(sizeof(*vdir), GFP_KERNEL);
        if (!vdir) return -ENOMEM;
 
-       if (coda_file->f_pos == 0) {
-               ret = filldir(buf, ".", 1, 0, de->d_inode->i_ino, DT_DIR);
-               if (ret < 0)
-                       goto out;
-               result++;
-               coda_file->f_pos++;
-       }
-       if (coda_file->f_pos == 1) {
-               ret = filldir(buf, "..", 2, 1, parent_ino(de), DT_DIR);
-               if (ret < 0)
-                       goto out;
-               result++;
-               coda_file->f_pos++;
-       }
+       if (!dir_emit_dots(coda_file, ctx))
+               goto out;
+
        while (1) {
                /* read entries from the directory file */
-               ret = kernel_read(host_file, coda_file->f_pos - 2, (char *)vdir,
+               ret = kernel_read(host_file, ctx->pos - 2, (char *)vdir,
                                  sizeof(*vdir));
                if (ret < 0) {
                        printk(KERN_ERR "coda readdir: read dir %s failed %d\n",
@@ -518,7 +482,7 @@ static int coda_venus_readdir(struct file *coda_file, void *buf,
 
                /* Make sure we skip '.' and '..', we already got those */
                if (name.name[0] == '.' && (name.len == 1 ||
-                   (vdir->d_name[1] == '.' && name.len == 2)))
+                   (name.name[1] == '.' && name.len == 2)))
                        vdir->d_fileno = name.len = 0;
 
                /* skip null entries */
@@ -531,19 +495,16 @@ static int coda_venus_readdir(struct file *coda_file, void *buf,
                        if (!ino) ino = vdir->d_fileno;
 
                        type = CDT2DT(vdir->d_type);
-                       ret = filldir(buf, name.name, name.len,
-                                     coda_file->f_pos, ino, type);
-                       /* failure means no space for filling in this round */
-                       if (ret < 0) break;
-                       result++;
+                       if (!dir_emit(ctx, name.name, name.len, ino, type))
+                               break;
                }
                /* we'll always have progress because d_reclen is unsigned and
                 * we've already established it is non-zero. */
-               coda_file->f_pos += vdir->d_reclen;
+               ctx->pos += vdir->d_reclen;
        }
 out:
        kfree(vdir);
-       return result ? result : ret;
+       return 0;
 }
 
 /* called when a cache lookup succeeds */