diff options
author | Jeff Mahoney <jeffm@suse.com> | 2016-11-05 20:26:35 +0300 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2016-11-30 15:45:19 +0300 |
commit | d2fbb2b589ece9060635b43c2b2333d0b0a0fbf2 (patch) | |
tree | 0c966e4f6fd1b7115944f3a44c9c4c75adcc1b0d /fs/btrfs/delayed-inode.h | |
parent | c2951f32d36c28d96acf95f0d83116facbec48a2 (diff) | |
download | linux-d2fbb2b589ece9060635b43c2b2333d0b0a0fbf2.tar.xz |
btrfs: increment ctx->pos for every emitted or skipped dirent in readdir
If we process the last item in the leaf and hit an I/O error while
reading the next leaf, we return -EIO without having adjusted the
position. Since we have emitted dirents, getdents() will return
the byte count to the user instead of the error. Subsequent callers
will emit the last successful dirent again, and return -EIO again,
with the same result. Callers loop forever.
Instead, if we always increment ctx->pos after emitting or skipping
the dirent, we'll be sure that we won't hit the same one again. When
we go to process the next leaf, we won't have emitted any dirents
and the -EIO will be returned to the user properly. We also don't
need to track if we've emitted a dirent already or if we've changed
the position yet.
Signed-off-by: Jeff Mahoney <jeffm@suse.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs/delayed-inode.h')
-rw-r--r-- | fs/btrfs/delayed-inode.h | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/fs/btrfs/delayed-inode.h b/fs/btrfs/delayed-inode.h index 2495b3d4075f..2c1cbe245104 100644 --- a/fs/btrfs/delayed-inode.h +++ b/fs/btrfs/delayed-inode.h @@ -146,7 +146,7 @@ void btrfs_readdir_put_delayed_items(struct inode *inode, int btrfs_should_delete_dir_index(struct list_head *del_list, u64 index); int btrfs_readdir_delayed_dir_index(struct dir_context *ctx, - struct list_head *ins_list, bool *emitted); + struct list_head *ins_list); /* for init */ int __init btrfs_delayed_inode_init(void); |