From a4a636a43741c2706868fb97dff9a83d398ac9e3 Mon Sep 17 00:00:00 2001 From: Qu Wenruo Date: Mon, 17 Mar 2025 17:40:47 +1030 Subject: [PATCH] btrfs: send: prepare put_file_data() for large data folios Currently put_file_data() can only accept a page sized folio. However the function itself is not that complex, it's just copying data from filemap folio into the send buffer. Make it support large data folios: - Change the loop to use file offset instead of page index - Calculate @pg_offset and @cur_len after getting the folio - Remove the "WARN_ON(folio_order(folio));" line Signed-off-by: Qu Wenruo Reviewed-by: David Sterba Signed-off-by: David Sterba --- fs/btrfs/send.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c index 43c29295f477e..116d67ab93dcd 100644 --- a/fs/btrfs/send.c +++ b/fs/btrfs/send.c @@ -5263,10 +5263,9 @@ static int put_file_data(struct send_ctx *sctx, u64 offset, u32 len) { struct btrfs_root *root = sctx->send_root; struct btrfs_fs_info *fs_info = root->fs_info; - struct folio *folio; - pgoff_t index = offset >> PAGE_SHIFT; - pgoff_t last_index; - unsigned pg_offset = offset_in_page(offset); + u64 cur = offset; + const u64 end = offset + len; + const pgoff_t last_index = ((end - 1) >> PAGE_SHIFT); struct address_space *mapping = sctx->cur_inode->i_mapping; int ret; @@ -5274,11 +5273,11 @@ static int put_file_data(struct send_ctx *sctx, u64 offset, u32 len) if (ret) return ret; - last_index = (offset + len - 1) >> PAGE_SHIFT; - - while (index <= last_index) { - unsigned cur_len = min_t(unsigned, len, - PAGE_SIZE - pg_offset); + while (cur < end) { + pgoff_t index = (cur >> PAGE_SHIFT); + unsigned int cur_len; + unsigned int pg_offset; + struct folio *folio; folio = filemap_lock_folio(mapping, index); if (IS_ERR(folio)) { @@ -5292,8 +5291,8 @@ static int put_file_data(struct send_ctx *sctx, u64 offset, u32 len) break; } } - - WARN_ON(folio_order(folio)); + pg_offset = offset_in_folio(folio, cur); + cur_len = min_t(unsigned int, end - cur, folio_size(folio) - pg_offset); if (folio_test_readahead(folio)) page_cache_async_readahead(mapping, &sctx->ra, NULL, folio, @@ -5323,9 +5322,7 @@ static int put_file_data(struct send_ctx *sctx, u64 offset, u32 len) pg_offset, cur_len); folio_unlock(folio); folio_put(folio); - index++; - pg_offset = 0; - len -= cur_len; + cur += cur_len; sctx->send_size += cur_len; } -- 2.47.2