Message ID | 9cbd861d3b302e19b990848ea747d2ea91d01aed.1648497027.git.sweettea-kernel@dorminy.me (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | btrfs: Allocate page arrays more efficiently. | expand |
On 28.03.22 г. 23:14 ч., Sweet Tea Dorminy wrote: > While calling alloc_page() in a loop is an effective way to populate an > array of pages, the kernel 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. Similar code can be found in xfs/xfs_buf.c:xfs_buf_alloc_pages(). > > Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me> Reviewed-by: Nikolay Borisov <nborisov@suse.com>
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 4e81e75c8e7c..37711a66e726 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -102,17 +102,24 @@ void btrfs_free_path(struct btrfs_path *p) */ int btrfs_alloc_page_array(unsigned long nr_pages, struct page **page_array) { - int i; - for (i = 0; i < nr_pages; i++) { - struct page *page; - if (page_array[i]) + long allocated = 0; + for (;;) { + long last = allocated; + + allocated = alloc_pages_bulk_array(GFP_NOFS, nr_pages, + page_array); + if (allocated == nr_pages) + return 0; + + if (allocated != last) continue; - page = alloc_page(GFP_NOFS); - if (!page) - return -ENOMEM; - page_array[i] = page; + /* + * 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. + */ + return -ENOMEM; } - return 0; } /*
While calling alloc_page() in a loop is an effective way to populate an array of pages, the kernel 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. Similar code can be found in xfs/xfs_buf.c:xfs_buf_alloc_pages(). Signed-off-by: Sweet Tea Dorminy <sweettea-kernel@dorminy.me> --- fs/btrfs/ctree.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-)