]> rtime.felk.cvut.cz Git - linux-imx.git/blobdiff - fs/ext4/inline.c
Merge tag 'ext4_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso...
[linux-imx.git] / fs / ext4 / inline.c
index b8a07466144f62f837479b90431b26f793673797..d9ecbf1113a75798f4d2a5903fd2fc522ce00dba 100644 (file)
@@ -1404,16 +1404,15 @@ out:
  * offset as if '.' and '..' really take place.
  *
  */
-int ext4_read_inline_dir(struct file *filp,
-                        void *dirent, filldir_t filldir,
+int ext4_read_inline_dir(struct file *file,
+                        struct dir_context *ctx,
                         int *has_inline_data)
 {
-       int error = 0;
        unsigned int offset, parent_ino;
-       int i, stored;
+       int i;
        struct ext4_dir_entry_2 *de;
        struct super_block *sb;
-       struct inode *inode = file_inode(filp);
+       struct inode *inode = file_inode(file);
        int ret, inline_size = 0;
        struct ext4_iloc iloc;
        void *dir_buf = NULL;
@@ -1444,9 +1443,8 @@ int ext4_read_inline_dir(struct file *filp,
                goto out;
 
        sb = inode->i_sb;
-       stored = 0;
        parent_ino = le32_to_cpu(((struct ext4_dir_entry_2 *)dir_buf)->inode);
-       offset = filp->f_pos;
+       offset = ctx->pos;
 
        /*
         * dotdot_offset and dotdot_size is the real offset and
@@ -1460,104 +1458,74 @@ int ext4_read_inline_dir(struct file *filp,
        extra_offset = dotdot_size - EXT4_INLINE_DOTDOT_SIZE;
        extra_size = extra_offset + inline_size;
 
-       while (!error && !stored && filp->f_pos < extra_size) {
-revalidate:
-               /*
-                * If the version 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 inline
-                * dir to make sure.
-                */
-               if (filp->f_version != inode->i_version) {
-                       for (i = 0; i < extra_size && i < offset;) {
-                               /*
-                                * "." is with offset 0 and
-                                * ".." is dotdot_offset.
-                                */
-                               if (!i) {
-                                       i = dotdot_offset;
-                                       continue;
-                               } else if (i == dotdot_offset) {
-                                       i = dotdot_size;
-                                       continue;
-                               }
-                               /* for other entry, the real offset in
-                                * the buf has to be tuned accordingly.
-                                */
-                               de = (struct ext4_dir_entry_2 *)
-                                       (dir_buf + i - extra_offset);
-                               /* It's too expensive to do a full
-                                * dirent test each time round this
-                                * loop, but we do have to test at
-                                * least that it is non-zero.  A
-                                * failure will be detected in the
-                                * dirent test below. */
-                               if (ext4_rec_len_from_disk(de->rec_len,
-                                       extra_size) < EXT4_DIR_REC_LEN(1))
-                                       break;
-                               i += ext4_rec_len_from_disk(de->rec_len,
-                                                           extra_size);
-                       }
-                       offset = i;
-                       filp->f_pos = offset;
-                       filp->f_version = inode->i_version;
-               }
-
-               while (!error && filp->f_pos < extra_size) {
-                       if (filp->f_pos == 0) {
-                               error = filldir(dirent, ".", 1, 0, inode->i_ino,
-                                               DT_DIR);
-                               if (error)
-                                       break;
-                               stored++;
-                               filp->f_pos = dotdot_offset;
+       /*
+        * If the version 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 inline
+        * dir to make sure.
+        */
+       if (file->f_version != inode->i_version) {
+               for (i = 0; i < extra_size && i < offset;) {
+                       /*
+                        * "." is with offset 0 and
+                        * ".." is dotdot_offset.
+                        */
+                       if (!i) {
+                               i = dotdot_offset;
+                               continue;
+                       } else if (i == dotdot_offset) {
+                               i = dotdot_size;
                                continue;
                        }
+                       /* for other entry, the real offset in
+                        * the buf has to be tuned accordingly.
+                        */
+                       de = (struct ext4_dir_entry_2 *)
+                               (dir_buf + i - extra_offset);
+                       /* It's too expensive to do a full
+                        * dirent test each time round this
+                        * loop, but we do have to test at
+                        * least that it is non-zero.  A
+                        * failure will be detected in the
+                        * dirent test below. */
+                       if (ext4_rec_len_from_disk(de->rec_len, extra_size)
+                               < EXT4_DIR_REC_LEN(1))
+                               break;
+                       i += ext4_rec_len_from_disk(de->rec_len,
+                                                   extra_size);
+               }
+               offset = i;
+               ctx->pos = offset;
+               file->f_version = inode->i_version;
+       }
 
-                       if (filp->f_pos == dotdot_offset) {
-                               error = filldir(dirent, "..", 2,
-                                               dotdot_offset,
-                                               parent_ino, DT_DIR);
-                               if (error)
-                                       break;
-                               stored++;
+       while (ctx->pos < extra_size) {
+               if (ctx->pos == 0) {
+                       if (!dir_emit(ctx, ".", 1, inode->i_ino, DT_DIR))
+                               goto out;
+                       ctx->pos = dotdot_offset;
+                       continue;
+               }
 
-                               filp->f_pos = dotdot_size;
-                               continue;
-                       }
+               if (ctx->pos == dotdot_offset) {
+                       if (!dir_emit(ctx, "..", 2, parent_ino, DT_DIR))
+                               goto out;
+                       ctx->pos = dotdot_size;
+                       continue;
+               }
 
-                       de = (struct ext4_dir_entry_2 *)
-                               (dir_buf + filp->f_pos - extra_offset);
-                       if (ext4_check_dir_entry(inode, filp, de,
-                                                iloc.bh, dir_buf,
-                                                extra_size, filp->f_pos)) {
-                               ret = stored;
+               de = (struct ext4_dir_entry_2 *)
+                       (dir_buf + ctx->pos - extra_offset);
+               if (ext4_check_dir_entry(inode, file, de, iloc.bh, dir_buf,
+                                        extra_size, ctx->pos))
+                       goto out;
+               if (le32_to_cpu(de->inode)) {
+                       if (!dir_emit(ctx, de->name, de->name_len,
+                                     le32_to_cpu(de->inode),
+                                     get_dtype(sb, de->file_type)))
                                goto out;
-                       }
-                       if (le32_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 = filp->f_version;
-
-                               error = filldir(dirent, de->name,
-                                               de->name_len,
-                                               filp->f_pos,
-                                               le32_to_cpu(de->inode),
-                                               get_dtype(sb, de->file_type));
-                               if (error)
-                                       break;
-                               if (version != filp->f_version)
-                                       goto revalidate;
-                               stored++;
-                       }
-                       filp->f_pos += ext4_rec_len_from_disk(de->rec_len,
-                                                             extra_size);
                }
+               ctx->pos += ext4_rec_len_from_disk(de->rec_len, extra_size);
        }
 out:
        kfree(dir_buf);