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 <redacted>
---
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,
+ 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);--
2.32.0