The @src_copy buffer utilized inside overwrite_item() can be as large as
the nodesize.
For an existing btrfs with 64KiB nodesize, it means there is a high
chance to fail the kmalloc() call if there is not enough physically
contiguous pages.
Meanwhile there is really no need for such physically contiguous pages,
as we only use that buffer to compare the content of the item.
Use kvmalloc() to replace the kmalloc() call.
For most cases that kvmalloc() call will be easily fulfilled by regular
kmalloc(), but for really large items and large nodes, kvmalloc() will
have a much higher chance to get memory allocated.
Signed-off-by: Qu Wenruo <redacted>
---
fs/btrfs/tree-log.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index cfb0b0e9e124..7fb476b19eb4 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -503,7 +503,7 @@ static int overwrite_item(struct walk_control *wc)
btrfs_release_path(wc->subvol_path);
return 0;
}
- src_copy = kmalloc(item_size, GFP_NOFS);
+ src_copy = kvmalloc(item_size, GFP_NOFS);
if (!src_copy) {
btrfs_abort_log_replay(wc, -ENOMEM,
"failed to allocate memory for log leaf item");@@ -514,7 +514,7 @@ static int overwrite_item(struct walk_control *wc)
dst_ptr = btrfs_item_ptr_offset(dst_eb, dst_slot);
ret = memcmp_extent_buffer(dst_eb, src_copy, dst_ptr, item_size);
- kfree(src_copy);
+ kvfree(src_copy);
/*
* they have the same contents, just return, this saves
* us from cowing blocks in the destination tree and doing
--
2.55.0