diff options
author | David Sterba <dsterba@suse.com> | 2016-02-26 15:38:32 +0100 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2016-02-26 15:38:32 +0100 |
commit | 675d276b322b45e7bf7c616a2847bdc425745b99 (patch) | |
tree | c61e7108034bf1230024880ec8ae46a9617077c2 /fs/btrfs/inode.c | |
parent | Merge branch 'foreign/josef/space-updates' into for-chris-4.6 (diff) | |
parent | Btrfs: fix lockdep deadlock warning due to dev_replace (diff) | |
download | linux-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.c | 14 |
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++; |