diff mbox series

[RFC,7/8] btrfs: make extent_write_locked_range() to be subpage compatible

Message ID 20210623055529.166678-8-wqu@suse.com (mailing list archive)
State New, archived
Headers show
Series btrfs: experimental compression support for subpage | expand

Commit Message

Qu Wenruo June 23, 2021, 5:55 a.m. UTC
Function extent_write_locked_range() gets called when an async range
falls back to regular COW.

In that case, we need to finish the ordered extents for the range.

But the function is still using hardcoded PAGE_SIZE to calculate the
range.

If it get called with a range like this:

  0   16K  32K   48K 64K
  |   |////|/////|  |

Then the range passed to btrfs_writepage_endio_finish_ordered() will be
start == 16K, end == 80K, and the page range will no longer cover it,
triggering an ASSERT().

Fix it by properly calculate the range end by considering both the page
end and range end.

Signed-off-by: Qu Wenruo <wqu@suse.com>
---
 fs/btrfs/extent_io.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

Comments

Qu Wenruo July 5, 2021, 12:43 p.m. UTC | #1
On 2021/6/23 下午1:55, Qu Wenruo wrote:
> Function extent_write_locked_range() gets called when an async range
> falls back to regular COW.
> 
> In that case, we need to finish the ordered extents for the range.
> 
> But the function is still using hardcoded PAGE_SIZE to calculate the
> range.
> 
> If it get called with a range like this:
> 
>    0   16K  32K   48K 64K
>    |   |////|/////|  |
> 
> Then the range passed to btrfs_writepage_endio_finish_ordered() will be
> start == 16K, end == 80K, and the page range will no longer cover it,
> triggering an ASSERT().
> 
> Fix it by properly calculate the range end by considering both the page
> end and range end.
> 
> Signed-off-by: Qu Wenruo <wqu@suse.com>
> ---
>   fs/btrfs/extent_io.c | 7 +++++--
>   1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
> index e244c10074c8..c5491720a346 100644
> --- a/fs/btrfs/extent_io.c
> +++ b/fs/btrfs/extent_io.c
> @@ -5070,16 +5070,19 @@ int extent_write_locked_range(struct inode *inode, u64 start, u64 end,
>   
>   	wbc_attach_fdatawrite_inode(&wbc_writepages, inode);
>   	while (start <= end) {
> +		u64 cur_end = min(round_down(start, PAGE_SIZE) + PAGE_SIZE - 1,

Here it should be round_down(cur, PAGE_SIZE) other than @start.

Fixed in my github repo, as this is makeing tons of weird bugs even for 
x86_64.

Thank god this patch is just an RFC...

Thanks,
Qu
> +				  end);
> +
>   		page = find_get_page(mapping, start >> PAGE_SHIFT);
>   		if (clear_page_dirty_for_io(page))
>   			ret = __extent_writepage(page, &wbc_writepages, &epd);
>   		else {
>   			btrfs_writepage_endio_finish_ordered(BTRFS_I(inode),
> -					page, start, start + PAGE_SIZE - 1, 1);
> +					page, start, cur_end, 1);
>   			unlock_page(page);
>   		}
>   		put_page(page);
> -		start += PAGE_SIZE;
> +		start = cur_end + 1;
>   	}
>   
>   	ASSERT(ret <= 0);
>
diff mbox series

Patch

diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
index e244c10074c8..c5491720a346 100644
--- a/fs/btrfs/extent_io.c
+++ b/fs/btrfs/extent_io.c
@@ -5070,16 +5070,19 @@  int extent_write_locked_range(struct inode *inode, u64 start, u64 end,
 
 	wbc_attach_fdatawrite_inode(&wbc_writepages, inode);
 	while (start <= end) {
+		u64 cur_end = min(round_down(start, PAGE_SIZE) + PAGE_SIZE - 1,
+				  end);
+
 		page = find_get_page(mapping, start >> PAGE_SHIFT);
 		if (clear_page_dirty_for_io(page))
 			ret = __extent_writepage(page, &wbc_writepages, &epd);
 		else {
 			btrfs_writepage_endio_finish_ordered(BTRFS_I(inode),
-					page, start, start + PAGE_SIZE - 1, 1);
+					page, start, cur_end, 1);
 			unlock_page(page);
 		}
 		put_page(page);
-		start += PAGE_SIZE;
+		start = cur_end + 1;
 	}
 
 	ASSERT(ret <= 0);