diff options
| -rw-r--r-- | fs/btrfs/delayed-inode.c | 3 | ||||
| -rw-r--r-- | fs/btrfs/delayed-inode.h | 2 | ||||
| -rw-r--r-- | fs/btrfs/inode.c | 14 |
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 | */ |
| 1691 | int btrfs_readdir_delayed_dir_index(struct dir_context *ctx, | 1691 | int 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, | |||
| 144 | int btrfs_should_delete_dir_index(struct list_head *del_list, | 144 | int btrfs_should_delete_dir_index(struct list_head *del_list, |
| 145 | u64 index); | 145 | u64 index); |
| 146 | int btrfs_readdir_delayed_dir_index(struct dir_context *ctx, | 146 | int 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 */ |
| 150 | int __init btrfs_delayed_inode_init(void); | 150 | int __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 | ||
