diff options
author | Sweet Tea Dorminy <sweettea-kernel@dorminy.me> | 2022-03-30 16:11:23 -0400 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2022-05-16 17:03:11 +0200 |
commit | 91d6ac1d62c3dc0f102986318f4027ccfa22c638 (patch) | |
tree | dec40c8a71ce428f4ff34057043f31924df4082a /fs/btrfs/extent_io.c | |
parent | dd137dd1f2d719682b522d4eabe6dec461b7d6fa (diff) |
btrfs: allocate page arrays using bulk page allocator
While calling alloc_page() in a loop is an effective way to populate an
array of pages, the MM subsystem provides a method to allocate pages in
bulk. alloc_pages_bulk_array() populates the NULL slots in a page
array, trying to grab more than one page at a time.
Unfortunately, it doesn't guarantee allocating all slots in the array,
but it's easy to call it in a loop and return an error if no progress
occurs.
Reviewed-by: Nikolay Borisov <nborisov@suse.com>
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>
Diffstat (limited to 'fs/btrfs/extent_io.c')
-rw-r--r-- | fs/btrfs/extent_io.c | 19 |
1 files changed, 11 insertions, 8 deletions
diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index e472886c3b22..cfcbfd5a5467 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -3146,17 +3146,20 @@ readpage_ok: */ int btrfs_alloc_page_array(unsigned int nr_pages, struct page **page_array) { - int i; + unsigned int allocated; - for (i = 0; i < nr_pages; i++) { - struct page *page; + for (allocated = 0; allocated < nr_pages;) { + unsigned int last = allocated; - if (page_array[i]) - continue; - page = alloc_page(GFP_NOFS); - if (!page) + allocated = alloc_pages_bulk_array(GFP_NOFS, nr_pages, page_array); + + /* + * During this iteration, no page could be allocated, even + * though alloc_pages_bulk_array() falls back to alloc_page() + * if it could not bulk-allocate. So we must be out of memory. + */ + if (allocated == last) return -ENOMEM; - page_array[i] = page; } return 0; } |