1
0
Fork 0
mirror of synced 2025-03-06 20:59:54 +01:00

NFS: Support larger readdir buffers

Support readdir buffers of up to 1MB in size so that we can read
large directories using few RPC calls.

Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Reviewed-by: Benjamin Coddington <bcodding@redhat.com>
Tested-by: Benjamin Coddington <bcodding@redhat.com>
Tested-by: Dave Wysochanski <dwysocha@redhat.com>
This commit is contained in:
Trond Myklebust 2020-11-01 14:26:47 -05:00
parent a52a8a6ada
commit 1a34c8c9a4
3 changed files with 21 additions and 22 deletions

View file

@ -781,8 +781,8 @@ static void nfs_server_set_fsinfo(struct nfs_server *server,
server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL); server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL);
server->dtsize = nfs_block_size(fsinfo->dtpref, NULL); server->dtsize = nfs_block_size(fsinfo->dtpref, NULL);
if (server->dtsize > PAGE_SIZE * NFS_MAX_READDIR_PAGES) if (server->dtsize > NFS_MAX_FILE_IO_SIZE)
server->dtsize = PAGE_SIZE * NFS_MAX_READDIR_PAGES; server->dtsize = NFS_MAX_FILE_IO_SIZE;
if (server->dtsize > server->rsize) if (server->dtsize > server->rsize)
server->dtsize = server->rsize; server->dtsize = server->rsize;

View file

@ -727,44 +727,47 @@ static int nfs_readdir_page_filler(struct nfs_readdir_descriptor *desc,
return status; return status;
} }
static static void nfs_readdir_free_pages(struct page **pages, size_t npages)
void nfs_readdir_free_pages(struct page **pages, unsigned int npages)
{ {
unsigned int i; while (npages--)
for (i = 0; i < npages; i++) put_page(pages[npages]);
put_page(pages[i]); kfree(pages);
} }
/* /*
* nfs_readdir_alloc_pages() will allocate pages that must be freed with a call * nfs_readdir_alloc_pages() will allocate pages that must be freed with a call
* to nfs_readdir_free_pages() * to nfs_readdir_free_pages()
*/ */
static static struct page **nfs_readdir_alloc_pages(size_t npages)
int nfs_readdir_alloc_pages(struct page **pages, unsigned int npages)
{ {
unsigned int i; struct page **pages;
size_t i;
pages = kmalloc_array(npages, sizeof(*pages), GFP_KERNEL);
if (!pages)
return NULL;
for (i = 0; i < npages; i++) { for (i = 0; i < npages; i++) {
struct page *page = alloc_page(GFP_KERNEL); struct page *page = alloc_page(GFP_KERNEL);
if (page == NULL) if (page == NULL)
goto out_freepages; goto out_freepages;
pages[i] = page; pages[i] = page;
} }
return 0; return pages;
out_freepages: out_freepages:
nfs_readdir_free_pages(pages, i); nfs_readdir_free_pages(pages, i);
return -ENOMEM; return NULL;
} }
static static
int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, struct inode *inode) int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, struct inode *inode)
{ {
struct page *pages[NFS_MAX_READDIR_PAGES]; struct page **pages;
struct nfs_entry entry; struct nfs_entry entry;
struct file *file = desc->file; struct file *file = desc->file;
size_t array_size;
size_t dtsize = NFS_SERVER(inode)->dtsize;
int status = -ENOMEM; int status = -ENOMEM;
unsigned int array_size = ARRAY_SIZE(pages);
entry.prev_cookie = 0; entry.prev_cookie = 0;
entry.cookie = nfs_readdir_page_last_cookie(page); entry.cookie = nfs_readdir_page_last_cookie(page);
@ -781,9 +784,11 @@ int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page,
goto out; goto out;
} }
status = nfs_readdir_alloc_pages(pages, array_size); array_size = (dtsize + PAGE_SIZE - 1) >> PAGE_SHIFT;
if (status < 0) pages = nfs_readdir_alloc_pages(array_size);
if (!pages)
goto out_release_label; goto out_release_label;
do { do {
unsigned int pglen; unsigned int pglen;
status = nfs_readdir_xdr_filler(pages, desc, &entry, file, inode); status = nfs_readdir_xdr_filler(pages, desc, &entry, file, inode);

View file

@ -56,12 +56,6 @@ static inline bool nfs_lookup_is_soft_revalidate(const struct dentry *dentry)
#define NFS_UNSPEC_RETRANS (UINT_MAX) #define NFS_UNSPEC_RETRANS (UINT_MAX)
#define NFS_UNSPEC_TIMEO (UINT_MAX) #define NFS_UNSPEC_TIMEO (UINT_MAX)
/*
* Maximum number of pages that readdir can use for creating
* a vmapped array of pages.
*/
#define NFS_MAX_READDIR_PAGES 8
struct nfs_client_initdata { struct nfs_client_initdata {
unsigned long init_flags; unsigned long init_flags;
const char *hostname; /* Hostname of the server */ const char *hostname; /* Hostname of the server */