aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/btrfs/delayed-inode.c3
-rw-r--r--fs/btrfs/delayed-inode.h2
-rw-r--r--fs/btrfs/inode.c14
3 files changed, 16 insertions, 3 deletions
diff --git a/fs/btrfs/delayed-inode.c b/fs/btrfs/delayed-inode.c
index 0be47e4b8136..b57daa895cea 100644
--- a/fs/btrfs/delayed-inode.c
+++ b/fs/btrfs/delayed-inode.c
@@ -1689,7 +1689,7 @@ int btrfs_should_delete_dir_index(struct list_head *del_list,
1689 * 1689 *
1690 */ 1690 */
1691int btrfs_readdir_delayed_dir_index(struct dir_context *ctx, 1691int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
1692 struct list_head *ins_list) 1692 struct list_head *ins_list, bool *emitted)
1693{ 1693{
1694 struct btrfs_dir_item *di; 1694 struct btrfs_dir_item *di;
1695 struct btrfs_delayed_item *curr, *next; 1695 struct btrfs_delayed_item *curr, *next;
@@ -1733,6 +1733,7 @@ int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
1733 1733
1734 if (over) 1734 if (over)
1735 return 1; 1735 return 1;
1736 *emitted = true;
1736 } 1737 }
1737 return 0; 1738 return 0;
1738} 1739}
diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h
index f70119f25421..0167853c84ae 100644
--- a/fs/btrfs/delayed-inode.h
+++ b/fs/btrfs/delayed-inode.h
@@ -144,7 +144,7 @@ void btrfs_put_delayed_items(struct list_head *ins_list,
144int btrfs_should_delete_dir_index(struct list_head *del_list, 144int btrfs_should_delete_dir_index(struct list_head *del_list,
145 u64 index); 145 u64 index);
146int btrfs_readdir_delayed_dir_index(struct dir_context *ctx, 146int btrfs_readdir_delayed_dir_index(struct dir_context *ctx,
147 struct list_head *ins_list); 147 struct list_head *ins_list, bool *emitted);
148 148
149/* for init */ 149/* for init */
150int __init btrfs_delayed_inode_init(void); 150int __init btrfs_delayed_inode_init(void);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index e4565456eb01..600bf0d9ceaf 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -5716,6 +5716,7 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
5716 char *name_ptr; 5716 char *name_ptr;
5717 int name_len; 5717 int name_len;
5718 int is_curr = 0; /* ctx->pos points to the current index? */ 5718 int is_curr = 0; /* ctx->pos points to the current index? */
5719 bool emitted;
5719 5720
5720 /* FIXME, use a real flag for deciding about the key type */ 5721 /* FIXME, use a real flag for deciding about the key type */
5721 if (root->fs_info->tree_root == root) 5722 if (root->fs_info->tree_root == root)
@@ -5744,6 +5745,7 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
5744 if (ret < 0) 5745 if (ret < 0)
5745 goto err; 5746 goto err;
5746 5747
5748 emitted = false;
5747 while (1) { 5749 while (1) {
5748 leaf = path->nodes[0]; 5750 leaf = path->nodes[0];
5749 slot = path->slots[0]; 5751 slot = path->slots[0];
@@ -5823,6 +5825,7 @@ skip:
5823 5825
5824 if (over) 5826 if (over)
5825 goto nopos; 5827 goto nopos;
5828 emitted = true;
5826 di_len = btrfs_dir_name_len(leaf, di) + 5829 di_len = btrfs_dir_name_len(leaf, di) +
5827 btrfs_dir_data_len(leaf, di) + sizeof(*di); 5830 btrfs_dir_data_len(leaf, di) + sizeof(*di);
5828 di_cur += di_len; 5831 di_cur += di_len;
@@ -5835,11 +5838,20 @@ next:
5835 if (key_type == BTRFS_DIR_INDEX_KEY) { 5838 if (key_type == BTRFS_DIR_INDEX_KEY) {
5836 if (is_curr) 5839 if (is_curr)
5837 ctx->pos++; 5840 ctx->pos++;
5838 ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list); 5841 ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list, &emitted);
5839 if (ret) 5842 if (ret)
5840 goto nopos; 5843 goto nopos;
5841 } 5844 }
5842 5845
5846 /*
5847 * If we haven't emitted any dir entry, we must not touch ctx->pos as
5848 * it was was set to the termination value in previous call. We assume
5849 * that "." and ".." were emitted if we reach this point and set the
5850 * termination value as well for an empty directory.
5851 */
5852 if (ctx->pos > 2 && !emitted)
5853 goto nopos;
5854
5843 /* Reached end of directory/root. Bump pos past the last item. */ 5855 /* Reached end of directory/root. Bump pos past the last item. */
5844 ctx->pos++; 5856 ctx->pos++;
5845 5857