summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorDavid Sterba <dsterba@suse.com>2016-02-26 15:38:32 +0100
committerDavid Sterba <dsterba@suse.com>2016-02-26 15:38:32 +0100
commit675d276b322b45e7bf7c616a2847bdc425745b99 (patch)
treec61e7108034bf1230024880ec8ae46a9617077c2 /fs/btrfs/inode.c
parentMerge branch 'foreign/josef/space-updates' into for-chris-4.6 (diff)
parentBtrfs: fix lockdep deadlock warning due to dev_replace (diff)
downloadlinux-675d276b322b45e7bf7c616a2847bdc425745b99.tar.xz
linux-675d276b322b45e7bf7c616a2847bdc425745b99.zip
Merge branch 'foreign/liubo/replace-lockup' into for-chris-4.6
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 350b77220153..d4381f5ef52d 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -5731,6 +5731,7 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
char *name_ptr;
int name_len;
int is_curr = 0; /* ctx->pos points to the current index? */
+ bool emitted;
/* FIXME, use a real flag for deciding about the key type */
if (root->fs_info->tree_root == root)
@@ -5759,6 +5760,7 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
if (ret < 0)
goto err;
+ emitted = false;
while (1) {
leaf = path->nodes[0];
slot = path->slots[0];
@@ -5838,6 +5840,7 @@ skip:
if (over)
goto nopos;
+ emitted = true;
di_len = btrfs_dir_name_len(leaf, di) +
btrfs_dir_data_len(leaf, di) + sizeof(*di);
di_cur += di_len;
@@ -5850,11 +5853,20 @@ next:
if (key_type == BTRFS_DIR_INDEX_KEY) {
if (is_curr)
ctx->pos++;
- ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list);
+ ret = btrfs_readdir_delayed_dir_index(ctx, &ins_list, &emitted);
if (ret)
goto nopos;
}
+ /*
+ * If we haven't emitted any dir entry, we must not touch ctx->pos as
+ * it was was set to the termination value in previous call. We assume
+ * that "." and ".." were emitted if we reach this point and set the
+ * termination value as well for an empty directory.
+ */
+ if (ctx->pos > 2 && !emitted)
+ goto nopos;
+
/* Reached end of directory/root. Bump pos past the last item. */
ctx->pos++;