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

index f1e1aed..eb760d8 100644 (file)
@@ -1761,11 +1761,10 @@ bail:
 
 static int ocfs2_dir_foreach_blk_id(struct inode *inode,
                                    u64 *f_version,
-                                   loff_t *f_pos, void *priv,
-                                   filldir_t filldir, int *filldir_err)
+                                   struct dir_context *ctx)
 {
-       int ret, i, filldir_ret;
-       unsigned long offset = *f_pos;
+       int ret, i;
+       unsigned long offset = ctx->pos;
        struct buffer_head *di_bh = NULL;
        struct ocfs2_dinode *di;
        struct ocfs2_inline_data *data;
@@ -1781,8 +1780,7 @@ static int ocfs2_dir_foreach_blk_id(struct inode *inode,
        di = (struct ocfs2_dinode *)di_bh->b_data;
        data = &di->id2.i_data;
 
-       while (*f_pos < i_size_read(inode)) {
-revalidate:
+       while (ctx->pos < i_size_read(inode)) {
                /* If the dir block has changed since the last call to
                 * readdir(2), then we might be pointing to an invalid
                 * dirent right now.  Scan from the start of the block
@@ -1802,50 +1800,31 @@ revalidate:
                                        break;
                                i += le16_to_cpu(de->rec_len);
                        }
-                       *f_pos = offset = i;
+                       ctx->pos = offset = i;
                        *f_version = inode->i_version;
                }
 
-               de = (struct ocfs2_dir_entry *) (data->id_data + *f_pos);
-               if (!ocfs2_check_dir_entry(inode, de, di_bh, *f_pos)) {
+               de = (struct ocfs2_dir_entry *) (data->id_data + ctx->pos);
+               if (!ocfs2_check_dir_entry(inode, de, di_bh, ctx->pos)) {
                        /* On error, skip the f_pos to the end. */
-                       *f_pos = i_size_read(inode);
-                       goto out;
+                       ctx->pos = i_size_read(inode);
+                       break;
                }
                offset += le16_to_cpu(de->rec_len);
                if (le64_to_cpu(de->inode)) {
-                       /* We might block in the next section
-                        * if the data destination is
-                        * currently swapped out.  So, use a
-                        * version stamp to detect whether or
-                        * not the directory has been modified
-                        * during the copy operation.
-                        */
-                       u64 version = *f_version;
                        unsigned char d_type = DT_UNKNOWN;
 
                        if (de->file_type < OCFS2_FT_MAX)
                                d_type = ocfs2_filetype_table[de->file_type];
 
-                       filldir_ret = filldir(priv, de->name,
-                                             de->name_len,
-                                             *f_pos,
-                                             le64_to_cpu(de->inode),
-                                             d_type);
-                       if (filldir_ret) {
-                               if (filldir_err)
-                                       *filldir_err = filldir_ret;
-                               break;
-                       }
-                       if (version != *f_version)
-                               goto revalidate;
+                       if (!dir_emit(ctx, de->name, de->name_len,
+                                     le64_to_cpu(de->inode), d_type))
+                               goto out;
                }
-               *f_pos += le16_to_cpu(de->rec_len);
+               ctx->pos += le16_to_cpu(de->rec_len);
        }
-
 out:
        brelse(di_bh);
-
        return 0;
 }
 
@@ -1855,27 +1834,26 @@ out:
  */
 static int ocfs2_dir_foreach_blk_el(struct inode *inode,
                                    u64 *f_version,
-                                   loff_t *f_pos, void *priv,
-                                   filldir_t filldir, int *filldir_err)
+                                   struct dir_context *ctx,
+                                   bool persist)
 {
-       int error = 0;
        unsigned long offset, blk, last_ra_blk = 0;
-       int i, stored;
+       int i;
        struct buffer_head * bh, * tmp;
        struct ocfs2_dir_entry * de;
        struct super_block * sb = inode->i_sb;
        unsigned int ra_sectors = 16;
+       int stored = 0;
 
-       stored = 0;
        bh = NULL;
 
-       offset = (*f_pos) & (sb->s_blocksize - 1);
+       offset = ctx->pos & (sb->s_blocksize - 1);
 
-       while (!error && !stored && *f_pos < i_size_read(inode)) {
-               blk = (*f_pos) >> sb->s_blocksize_bits;
+       while (ctx->pos < i_size_read(inode)) {
+               blk = ctx->pos >> sb->s_blocksize_bits;
                if (ocfs2_read_dir_block(inode, blk, &bh, 0)) {
                        /* Skip the corrupt dirblock and keep trying */
-                       *f_pos += sb->s_blocksize - offset;
+                       ctx->pos += sb->s_blocksize - offset;
                        continue;
                }
 
@@ -1897,7 +1875,6 @@ static int ocfs2_dir_foreach_blk_el(struct inode *inode,
                        ra_sectors = 8;
                }
 
-revalidate:
                /* If the dir block has changed since the last call to
                 * readdir(2), then we might be pointing to an invalid
                 * dirent right now.  Scan from the start of the block
@@ -1917,93 +1894,64 @@ revalidate:
                                i += le16_to_cpu(de->rec_len);
                        }
                        offset = i;
-                       *f_pos = ((*f_pos) & ~(sb->s_blocksize - 1))
+                       ctx->pos = (ctx->pos & ~(sb->s_blocksize - 1))
                                | offset;
                        *f_version = inode->i_version;
                }
 
-               while (!error && *f_pos < i_size_read(inode)
+               while (ctx->pos < i_size_read(inode)
                       && offset < sb->s_blocksize) {
                        de = (struct ocfs2_dir_entry *) (bh->b_data + offset);
                        if (!ocfs2_check_dir_entry(inode, de, bh, offset)) {
                                /* On error, skip the f_pos to the
                                   next block. */
-                               *f_pos = ((*f_pos) | (sb->s_blocksize - 1)) + 1;
+                               ctx->pos = (ctx->pos | (sb->s_blocksize - 1)) + 1;
                                brelse(bh);
-                               goto out;
+                               continue;
                        }
-                       offset += le16_to_cpu(de->rec_len);
                        if (le64_to_cpu(de->inode)) {
-                               /* We might block in the next section
-                                * if the data destination is
-                                * currently swapped out.  So, use a
-                                * version stamp to detect whether or
-                                * not the directory has been modified
-                                * during the copy operation.
-                                */
-                               unsigned long version = *f_version;
                                unsigned char d_type = DT_UNKNOWN;
 
                                if (de->file_type < OCFS2_FT_MAX)
                                        d_type = ocfs2_filetype_table[de->file_type];
-                               error = filldir(priv, de->name,
+                               if (!dir_emit(ctx, de->name,
                                                de->name_len,
-                                               *f_pos,
                                                le64_to_cpu(de->inode),
-                                               d_type);
-                               if (error) {
-                                       if (filldir_err)
-                                               *filldir_err = error;
-                                       break;
+                                               d_type)) {
+                                       brelse(bh);
+                                       return 0;
                                }
-                               if (version != *f_version)
-                                       goto revalidate;
-                               stored ++;
+                               stored++;
                        }
-                       *f_pos += le16_to_cpu(de->rec_len);
+                       offset += le16_to_cpu(de->rec_len);
+                       ctx->pos += le16_to_cpu(de->rec_len);
                }
                offset = 0;
                brelse(bh);
                bh = NULL;
+               if (!persist && stored)
+                       break;
        }
-
-       stored = 0;
-out:
-       return stored;
+       return 0;
 }
 
 static int ocfs2_dir_foreach_blk(struct inode *inode, u64 *f_version,
-                                loff_t *f_pos, void *priv, filldir_t filldir,
-                                int *filldir_err)
+                                struct dir_context *ctx,
+                                bool persist)
 {
        if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
-               return ocfs2_dir_foreach_blk_id(inode, f_version, f_pos, priv,
-                                               filldir, filldir_err);
-
-       return ocfs2_dir_foreach_blk_el(inode, f_version, f_pos, priv, filldir,
-                                       filldir_err);
+               return ocfs2_dir_foreach_blk_id(inode, f_version, ctx);
+       return ocfs2_dir_foreach_blk_el(inode, f_version, ctx, persist);
 }
 
 /*
  * This is intended to be called from inside other kernel functions,
  * so we fake some arguments.
  */
-int ocfs2_dir_foreach(struct inode *inode, loff_t *f_pos, void *priv,
-                     filldir_t filldir)
+int ocfs2_dir_foreach(struct inode *inode, struct dir_context *ctx)
 {
-       int ret = 0, filldir_err = 0;
        u64 version = inode->i_version;
-
-       while (*f_pos < i_size_read(inode)) {
-               ret = ocfs2_dir_foreach_blk(inode, &version, f_pos, priv,
-                                           filldir, &filldir_err);
-               if (ret || filldir_err)
-                       break;
-       }
-
-       if (ret > 0)
-               ret = -EIO;
-
+       ocfs2_dir_foreach_blk(inode, &version, ctx, true);
        return 0;
 }
 
@@ -2011,15 +1959,15 @@ int ocfs2_dir_foreach(struct inode *inode, loff_t *f_pos, void *priv,
  * ocfs2_readdir()
  *
  */
-int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir)
+int ocfs2_readdir(struct file *file, struct dir_context *ctx)
 {
        int error = 0;
-       struct inode *inode = file_inode(filp);
+       struct inode *inode = file_inode(file);
        int lock_level = 0;
 
        trace_ocfs2_readdir((unsigned long long)OCFS2_I(inode)->ip_blkno);
 
-       error = ocfs2_inode_lock_atime(inode, filp->f_path.mnt, &lock_level);
+       error = ocfs2_inode_lock_atime(inode, file->f_path.mnt, &lock_level);
        if (lock_level && error >= 0) {
                /* We release EX lock which used to update atime
                 * and get PR lock again to reduce contention
@@ -2035,8 +1983,7 @@ int ocfs2_readdir(struct file * filp, void * dirent, filldir_t filldir)
                goto bail_nolock;
        }
 
-       error = ocfs2_dir_foreach_blk(inode, &filp->f_version, &filp->f_pos,
-                                     dirent, filldir, NULL);
+       error = ocfs2_dir_foreach_blk(inode, &file->f_version, ctx, false);
 
        ocfs2_inode_unlock(inode, lock_level);
        if (error)
@@ -2120,6 +2067,7 @@ bail:
 }
 
 struct ocfs2_empty_dir_priv {
+       struct dir_context ctx;
        unsigned seen_dot;
        unsigned seen_dot_dot;
        unsigned seen_other;
@@ -2204,8 +2152,9 @@ out:
 int ocfs2_empty_dir(struct inode *inode)
 {
        int ret;
-       loff_t start = 0;
-       struct ocfs2_empty_dir_priv priv;
+       struct ocfs2_empty_dir_priv priv = {
+               .ctx.actor = ocfs2_empty_dir_filldir
+       };
 
        memset(&priv, 0, sizeof(priv));
 
@@ -2219,7 +2168,7 @@ int ocfs2_empty_dir(struct inode *inode)
                 */
        }
 
-       ret = ocfs2_dir_foreach(inode, &start, &priv, ocfs2_empty_dir_filldir);
+       ret = ocfs2_dir_foreach(inode, &priv.ctx);
        if (ret)
                mlog_errno(ret);
 
index e683f3d..f0344b7 100644 (file)
@@ -92,9 +92,8 @@ int ocfs2_find_files_on_disk(const char *name,
                             struct ocfs2_dir_lookup_result *res);
 int ocfs2_lookup_ino_from_name(struct inode *dir, const char *name,
                               int namelen, u64 *blkno);
-int ocfs2_readdir(struct file *filp, void *dirent, filldir_t filldir);
-int ocfs2_dir_foreach(struct inode *inode, loff_t *f_pos, void *priv,
-                     filldir_t filldir);
+int ocfs2_readdir(struct file *file, struct dir_context *ctx);
+int ocfs2_dir_foreach(struct inode *inode, struct dir_context *ctx);
 int ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb,
                                 struct inode *dir,
                                 struct buffer_head *parent_fe_bh,
index ff54014..8a38714 100644 (file)
@@ -2712,7 +2712,7 @@ const struct file_operations ocfs2_fops = {
 const struct file_operations ocfs2_dops = {
        .llseek         = generic_file_llseek,
        .read           = generic_read_dir,
-       .readdir        = ocfs2_readdir,
+       .iterate        = ocfs2_readdir,
        .fsync          = ocfs2_sync_file,
        .release        = ocfs2_dir_release,
        .open           = ocfs2_dir_open,
@@ -2759,7 +2759,7 @@ const struct file_operations ocfs2_fops_no_plocks = {
 const struct file_operations ocfs2_dops_no_plocks = {
        .llseek         = generic_file_llseek,
        .read           = generic_read_dir,
-       .readdir        = ocfs2_readdir,
+       .iterate        = ocfs2_readdir,
        .fsync          = ocfs2_sync_file,
        .release        = ocfs2_dir_release,
        .open           = ocfs2_dir_open,
index 8eccfab..242170d 100644 (file)
@@ -1941,6 +1941,7 @@ void ocfs2_orphan_scan_start(struct ocfs2_super *osb)
 }
 
 struct ocfs2_orphan_filldir_priv {
+       struct dir_context      ctx;
        struct inode            *head;
        struct ocfs2_super      *osb;
 };
@@ -1977,11 +1978,11 @@ static int ocfs2_queue_orphans(struct ocfs2_super *osb,
 {
        int status;
        struct inode *orphan_dir_inode = NULL;
-       struct ocfs2_orphan_filldir_priv priv;
-       loff_t pos = 0;
-
-       priv.osb = osb;
-       priv.head = *head;
+       struct ocfs2_orphan_filldir_priv priv = {
+               .ctx.actor = ocfs2_orphan_filldir,
+               .osb = osb,
+               .head = *head
+       };
 
        orphan_dir_inode = ocfs2_get_system_file_inode(osb,
                                                       ORPHAN_DIR_SYSTEM_INODE,
@@ -1999,8 +2000,7 @@ static int ocfs2_queue_orphans(struct ocfs2_super *osb,
                goto out;
        }
 
-       status = ocfs2_dir_foreach(orphan_dir_inode, &pos, &priv,
-                                  ocfs2_orphan_filldir);
+       status = ocfs2_dir_foreach(orphan_dir_inode, &priv.ctx);
        if (status) {
                mlog_errno(status);
                goto out_cluster;