Message ID | da314182610b43632ca81ba78ff73fac5ae1bf06.1671820088.git.fdmanana@suse.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | btrfs: fix off-by-one in delalloc search during lseek | expand |
Tested-by: Joan Bruguera Micó <joanbrugueram@gmail.com>
On Fri, Dec 23, 2022 at 06:28:53PM +0000, fdmanana@kernel.org wrote: > From: Filipe Manana <fdmanana@suse.com> > > During lseek, when searching for delalloc in a range that represents a > hole and that range has a length of 1 byte, we end up not doing the actual > delalloc search in the inode's io tree, resulting in not correctly > reporting the offset with data or a hole. This actually only happens when > the start offset is 0 because with any other start offset we round it down > by sector size. > > Reproducer: > > $ mkfs.btrfs -f /dev/sdc > $ mount /dev/sdc /mnt/sdc > > $ xfs_io -f -c "pwrite -q 0 1" /mnt/sdc/foo > > $ xfs_io -c "seek -d 0" /mnt/sdc/foo > Whence Result > DATA EOF > > It should have reported an offset of 0 instead of EOF. > > Fix this by updating btrfs_find_delalloc_in_range() and count_range_bits() > to deal with inclusive ranges properly. These functions are already > suppossed to work with inclusive end offsets, they just got it wrong in a > couple places due to off-by-one mistakes. > > A test case for fstests will be added later. > > Reported-by: Joan Bruguera Micó <joanbrugueram@gmail.com> > Link: https://lore.kernel.org/linux-btrfs/20221223020509.457113-1-joanbrugueram@gmail.com/ > Fixes: b6e833567ea1 ("btrfs: make hole and data seeking a lot more efficient") > Signed-off-by: Filipe Manana <fdmanana@suse.com> Added to misc-next, thanks.
diff --git a/fs/btrfs/extent-io-tree.c b/fs/btrfs/extent-io-tree.c index 9ae9cd1e7035..3c7766dfaa69 100644 --- a/fs/btrfs/extent-io-tree.c +++ b/fs/btrfs/extent-io-tree.c @@ -1551,7 +1551,7 @@ u64 count_range_bits(struct extent_io_tree *tree, u64 last = 0; int found = 0; - if (WARN_ON(search_end <= cur_start)) + if (WARN_ON(search_end < cur_start)) return 0; spin_lock(&tree->lock); diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c index 91b00eb2440e..834bbcb91102 100644 --- a/fs/btrfs/file.c +++ b/fs/btrfs/file.c @@ -3354,7 +3354,7 @@ bool btrfs_find_delalloc_in_range(struct btrfs_inode *inode, u64 start, u64 end, bool search_io_tree = true; bool ret = false; - while (cur_offset < end) { + while (cur_offset <= end) { u64 delalloc_start; u64 delalloc_end; bool delalloc;