[PATCH v2 2/4] nfs/blocklayout: Use bulk page allocation APIs

cel
2024-06-21T16:22:46Z

From: Chuck Lever <chuck.lever@oracle.com>

nfs4_get_device_info() frequently requests more than a few pages
when provisioning a nfs4_deviceid_node object. Make this more
efficient by using alloc_pages_bulk_array(). This API is known to be
several times faster than an open-coded loop around alloc_page().

release_pages() is folio-enabled so it is also more efficient than
repeatedly invoking __free_pages().

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
---
fs/nfs/pnfs_dev.c | 15 ++++++---------
1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/fs/nfs/pnfs_dev.c b/fs/nfs/pnfs_dev.c
index 178001c90156..26a78d69acab 100644
--- a/fs/nfs/pnfs_dev.c
+++ b/fs/nfs/pnfs_dev.c
@@ -101,9 +101,8 @@ nfs4_get_device_info(struct nfs_server *server,
struct nfs4_deviceid_node *d = NULL;
struct pnfs_device *pdev = NULL;
struct page **pages = NULL;
+ int rc, i, max_pages;
u32 max_resp_sz;
- int max_pages;
- int rc, i;

/*
* Use the session max response size as the basis for setting
@@ -125,11 +124,9 @@ nfs4_get_device_info(struct nfs_server *server,
if (!pages)
goto out_free_pdev;

- for (i = 0; i < max_pages; i++) {
- pages[i] = alloc_page(gfp_flags);
- if (!pages[i])
- goto out_free_pages;
- }
+ i = alloc_pages_bulk_array(GFP_KERNEL, max_pages, pages);
+ if (i != max_pages)
+ goto out_free_pages;

memcpy(&pdev->dev_id, dev_id, sizeof(*dev_id));
pdev->layout_type = server->pnfs_curr_ld->id;
@@ -154,8 +151,8 @@ nfs4_get_device_info(struct nfs_server *server,
set_bit(NFS_DEVICEID_NOCACHE, &d->flags);

out_free_pages:
- while (--i >= 0)
- __free_page(pages[i]);
+ if (i)
+ release_pages(pages, i);
kfree(pages);
out_free_pdev:
kfree(pdev);
--
2.45.1