Skip to content

Commit 1a34c8c

Browse files
author
Trond Myklebust
committed
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>
1 parent a52a8a6 commit 1a34c8c

File tree

3 files changed

+21
-22
lines changed

3 files changed

+21
-22
lines changed

fs/nfs/client.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -781,8 +781,8 @@ static void nfs_server_set_fsinfo(struct nfs_server *server,
781781
server->wtmult = nfs_block_bits(fsinfo->wtmult, NULL);
782782

783783
server->dtsize = nfs_block_size(fsinfo->dtpref, NULL);
784-
if (server->dtsize > PAGE_SIZE * NFS_MAX_READDIR_PAGES)
785-
server->dtsize = PAGE_SIZE * NFS_MAX_READDIR_PAGES;
784+
if (server->dtsize > NFS_MAX_FILE_IO_SIZE)
785+
server->dtsize = NFS_MAX_FILE_IO_SIZE;
786786
if (server->dtsize > server->rsize)
787787
server->dtsize = server->rsize;
788788

fs/nfs/dir.c

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -727,44 +727,47 @@ static int nfs_readdir_page_filler(struct nfs_readdir_descriptor *desc,
727727
return status;
728728
}
729729

730-
static
731-
void nfs_readdir_free_pages(struct page **pages, unsigned int npages)
730+
static void nfs_readdir_free_pages(struct page **pages, size_t npages)
732731
{
733-
unsigned int i;
734-
for (i = 0; i < npages; i++)
735-
put_page(pages[i]);
732+
while (npages--)
733+
put_page(pages[npages]);
734+
kfree(pages);
736735
}
737736

738737
/*
739738
* nfs_readdir_alloc_pages() will allocate pages that must be freed with a call
740739
* to nfs_readdir_free_pages()
741740
*/
742-
static
743-
int nfs_readdir_alloc_pages(struct page **pages, unsigned int npages)
741+
static struct page **nfs_readdir_alloc_pages(size_t npages)
744742
{
745-
unsigned int i;
743+
struct page **pages;
744+
size_t i;
746745

746+
pages = kmalloc_array(npages, sizeof(*pages), GFP_KERNEL);
747+
if (!pages)
748+
return NULL;
747749
for (i = 0; i < npages; i++) {
748750
struct page *page = alloc_page(GFP_KERNEL);
749751
if (page == NULL)
750752
goto out_freepages;
751753
pages[i] = page;
752754
}
753-
return 0;
755+
return pages;
754756

755757
out_freepages:
756758
nfs_readdir_free_pages(pages, i);
757-
return -ENOMEM;
759+
return NULL;
758760
}
759761

760762
static
761763
int nfs_readdir_xdr_to_array(nfs_readdir_descriptor_t *desc, struct page *page, struct inode *inode)
762764
{
763-
struct page *pages[NFS_MAX_READDIR_PAGES];
765+
struct page **pages;
764766
struct nfs_entry entry;
765767
struct file *file = desc->file;
768+
size_t array_size;
769+
size_t dtsize = NFS_SERVER(inode)->dtsize;
766770
int status = -ENOMEM;
767-
unsigned int array_size = ARRAY_SIZE(pages);
768771

769772
entry.prev_cookie = 0;
770773
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,
781784
goto out;
782785
}
783786

784-
status = nfs_readdir_alloc_pages(pages, array_size);
785-
if (status < 0)
787+
array_size = (dtsize + PAGE_SIZE - 1) >> PAGE_SHIFT;
788+
pages = nfs_readdir_alloc_pages(array_size);
789+
if (!pages)
786790
goto out_release_label;
791+
787792
do {
788793
unsigned int pglen;
789794
status = nfs_readdir_xdr_filler(pages, desc, &entry, file, inode);

fs/nfs/internal.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,6 @@ static inline bool nfs_lookup_is_soft_revalidate(const struct dentry *dentry)
5656
#define NFS_UNSPEC_RETRANS (UINT_MAX)
5757
#define NFS_UNSPEC_TIMEO (UINT_MAX)
5858

59-
/*
60-
* Maximum number of pages that readdir can use for creating
61-
* a vmapped array of pages.
62-
*/
63-
#define NFS_MAX_READDIR_PAGES 8
64-
6559
struct nfs_client_initdata {
6660
unsigned long init_flags;
6761
const char *hostname; /* Hostname of the server */

0 commit comments

Comments
 (0)