summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Thumshirn <johannes.thumshirn@wdc.com>2024-10-30 12:02:53 +0100
committerMartin K. Petersen <martin.petersen@oracle.com>2024-11-02 20:37:01 -0400
commit7ce3e6107103214d354a16729a472f588be60572 (patch)
tree3cadc8579004883f757e6810a7074859e5ae6103
parentcb7e509c4e0197f63717fee54fb41c4990ba8d3a (diff)
scsi: sd_zbc: Use kvzalloc() to allocate REPORT ZONES buffer
We have two reports of failed memory allocation in btrfs' code which is calling into report zones. Both of these reports have the following signature coming from __vmalloc_area_node(): kworker/u17:5: vmalloc error: size 0, failed to allocate pages, mode:0x10dc2(GFP_KERNEL|__GFP_HIGHMEM|__GFP_NORETRY|__GFP_ZERO), nodemask=(null),cpuset=/,mems_allowed=0 Further debugging showed these where allocations of one sector (512 bytes) and at least one of the reporter's systems where low on memory, so going through the overhead of allocating a vm area failed. Switching the allocation from __vmalloc() to kvzalloc() avoids the overhead of vmalloc() on small allocations and succeeds. Note: the buffer is already freed using kvfree() so there's no need to adjust the free path. Cc: Qu Wenru <wqu@suse.com> Cc: Naohiro Aota <naohiro.aota@wdc.com> Link: https://github.com/kdave/btrfs-progs/issues/779 Link: https://github.com/kdave/btrfs-progs/issues/915 Fixes: 23a50861adda ("scsi: sd_zbc: Cleanup sd_zbc_alloc_report_buffer()") Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com> Link: https://lore.kernel.org/r/20241030110253.11718-1-jth@kernel.org Reviewed-by: Damien Le Moal <dlemoal@kernel.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/sd_zbc.c3
1 files changed, 1 insertions, 2 deletions
diff --git a/drivers/scsi/sd_zbc.c b/drivers/scsi/sd_zbc.c
index c8b9654d30f0..a4d17f3da25d 100644
--- a/drivers/scsi/sd_zbc.c
+++ b/drivers/scsi/sd_zbc.c
@@ -188,8 +188,7 @@ static void *sd_zbc_alloc_report_buffer(struct scsi_disk *sdkp,
bufsize = min_t(size_t, bufsize, queue_max_segments(q) << PAGE_SHIFT);
while (bufsize >= SECTOR_SIZE) {
- buf = __vmalloc(bufsize,
- GFP_KERNEL | __GFP_ZERO | __GFP_NORETRY);
+ buf = kvzalloc(bufsize, GFP_KERNEL | __GFP_NORETRY);
if (buf) {
*buflen = bufsize;
return buf;