[readdir] convert omfs
authorAl Viro <viro@zeniv.linux.org.uk>
Fri, 17 May 2013 19:05:25 +0000 (15:05 -0400)
committerAl Viro <viro@zeniv.linux.org.uk>
Sat, 29 Jun 2013 08:56:37 +0000 (12:56 +0400)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/omfs/dir.c

index acbaebc..1b8e9e8 100644 (file)
@@ -327,26 +327,23 @@ int omfs_is_bad(struct omfs_sb_info *sbi, struct omfs_header *header,
        return is_bad;
 }
 
-static int omfs_fill_chain(struct file *filp, void *dirent, filldir_t filldir,
+static bool omfs_fill_chain(struct inode *dir, struct dir_context *ctx,
                u64 fsblock, int hindex)
 {
-       struct inode *dir = file_inode(filp);
-       struct buffer_head *bh;
-       struct omfs_inode *oi;
-       u64 self;
-       int res = 0;
-       unsigned char d_type;
-
        /* follow chain in this bucket */
        while (fsblock != ~0) {
-               bh = omfs_bread(dir->i_sb, fsblock);
+               struct buffer_head *bh = omfs_bread(dir->i_sb, fsblock);
+               struct omfs_inode *oi;
+               u64 self;
+               unsigned char d_type;
+
                if (!bh)
-                       goto out;
+                       return true;
 
                oi = (struct omfs_inode *) bh->b_data;
                if (omfs_is_bad(OMFS_SB(dir->i_sb), &oi->i_head, fsblock)) {
                        brelse(bh);
-                       goto out;
+                       return true;
                }
 
                self = fsblock;
@@ -361,15 +358,16 @@ static int omfs_fill_chain(struct file *filp, void *dirent, filldir_t filldir,
 
                d_type = (oi->i_type == OMFS_DIR) ? DT_DIR : DT_REG;
 
-               res = filldir(dirent, oi->i_name, strnlen(oi->i_name,
-                       OMFS_NAMELEN), filp->f_pos, self, d_type);
+               if (!dir_emit(ctx, oi->i_name,
+                             strnlen(oi->i_name, OMFS_NAMELEN),
+                             self, d_type)) {
+                       brelse(bh);
+                       return false;
+               }
                brelse(bh);
-               if (res < 0)
-                       break;
-               filp->f_pos++;
+               ctx->pos++;
        }
-out:
-       return res;
+       return true;
 }
 
 static int omfs_rename(struct inode *old_dir, struct dentry *old_dentry,
@@ -403,60 +401,44 @@ out:
        return err;
 }
 
-static int omfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
+static int omfs_readdir(struct file *file, struct dir_context *ctx)
 {
-       struct inode *dir = file_inode(filp);
+       struct inode *dir = file_inode(file);
        struct buffer_head *bh;
-       loff_t offset, res;
+       __be64 *p;
        unsigned int hchain, hindex;
        int nbuckets;
-       u64 fsblock;
-       int ret = -EINVAL;
-
-       if (filp->f_pos >> 32)
-               goto success;
-
-       switch ((unsigned long) filp->f_pos) {
-       case 0:
-               if (filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR) < 0)
-                       goto success;
-               filp->f_pos++;
-               /* fall through */
-       case 1:
-               if (filldir(dirent, "..", 2, 1,
-                   parent_ino(filp->f_dentry), DT_DIR) < 0)
-                       goto success;
-               filp->f_pos = 1 << 20;
-               /* fall through */
+
+       if (ctx->pos >> 32)
+               return -EINVAL;
+
+       if (ctx->pos < 1 << 20) {
+               if (!dir_emit_dots(file, ctx))
+                       return 0;
+               ctx->pos = 1 << 20;
        }
 
        nbuckets = (dir->i_size - OMFS_DIR_START) / 8;
 
        /* high 12 bits store bucket + 1 and low 20 bits store hash index */
-       hchain = (filp->f_pos >> 20) - 1;
-       hindex = filp->f_pos & 0xfffff;
+       hchain = (ctx->pos >> 20) - 1;
+       hindex = ctx->pos & 0xfffff;
 
        bh = omfs_bread(dir->i_sb, dir->i_ino);
        if (!bh)
-               goto out;
+               return -EINVAL;
 
-       offset = OMFS_DIR_START + hchain * 8;
+       p = (__be64 *)(bh->b_data + OMFS_DIR_START) + hchain;
 
-       for (; hchain < nbuckets; hchain++, offset += 8) {
-               fsblock = be64_to_cpu(*((__be64 *) &bh->b_data[offset]));
-
-               res = omfs_fill_chain(filp, dirent, filldir, fsblock, hindex);
-               hindex = 0;
-               if (res < 0)
+       for (; hchain < nbuckets; hchain++) {
+               __u64 fsblock = be64_to_cpu(*p++);
+               if (!omfs_fill_chain(dir, ctx, fsblock, hindex))
                        break;
-
-               filp->f_pos = (hchain+2) << 20;
+               hindex = 0;
+               ctx->pos = (hchain+2) << 20;
        }
        brelse(bh);
-success:
-       ret = 0;
-out:
-       return ret;
+       return 0;
 }
 
 const struct inode_operations omfs_dir_inops = {
@@ -470,6 +452,6 @@ const struct inode_operations omfs_dir_inops = {
 
 const struct file_operations omfs_dir_operations = {
        .read = generic_read_dir,
-       .readdir = omfs_readdir,
+       .iterate = omfs_readdir,
        .llseek = generic_file_llseek,
 };