btrfs: wait between incomplete batch memory allocations
authorSweet Tea Dorminy <sweettea-kernel@dorminy.me>
Wed, 6 Apr 2022 18:24:18 +0000 (14:24 -0400)
committerDavid Sterba <dsterba@suse.com>
Mon, 16 May 2022 15:03:11 +0000 (17:03 +0200)
When allocating memory in a loop, each iteration should call
memalloc_retry_wait() in order to prevent starving memory-freeing
processes (and to mark where allocation loops are). Other filesystems do
that as well.

The bulk page allocation is the only place in btrfs with an allocation
retry loop, so add an appropriate call to it.

Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/extent_io.c

index cfcbfd5a54679148fdc85d711898bd9768ac8516..50626f4875997932738f7f6a82e34442ada709a4 100644 (file)
@@ -6,6 +6,7 @@
 #include <linux/mm.h>
 #include <linux/pagemap.h>
 #include <linux/page-flags.h>
+#include <linux/sched/mm.h>
 #include <linux/spinlock.h>
 #include <linux/blkdev.h>
 #include <linux/swap.h>
@@ -3153,6 +3154,9 @@ int btrfs_alloc_page_array(unsigned int nr_pages, struct page **page_array)
 
                allocated = alloc_pages_bulk_array(GFP_NOFS, nr_pages, page_array);
 
+               if (allocated == nr_pages)
+                       return 0;
+
                /*
                 * During this iteration, no page could be allocated, even
                 * though alloc_pages_bulk_array() falls back to alloc_page()
@@ -3160,6 +3164,8 @@ int btrfs_alloc_page_array(unsigned int nr_pages, struct page **page_array)
                 */
                if (allocated == last)
                        return -ENOMEM;
+
+               memalloc_retry_wait(GFP_NOFS);
        }
        return 0;
 }