Skip to content

Commit 35df59d

Browse files
author
Trond Myklebust
committed
NFS: Reduce number of RPC calls when doing uncached readdir
If we're doing uncached readdir, allocate multiple pages in order to try to avoid duplicate RPC calls for the same getdents() call. Signed-off-by: Trond Myklebust <[email protected]> Reviewed-by: Benjamin Coddington <[email protected]> Tested-by: Benjamin Coddington <[email protected]> Tested-by: Dave Wysochanski <[email protected]>
1 parent 762567b commit 35df59d

File tree

1 file changed

+69
-36
lines changed

1 file changed

+69
-36
lines changed

fs/nfs/dir.c

Lines changed: 69 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,23 @@ void nfs_readdir_clear_array(struct page *page)
199199
kunmap_atomic(array);
200200
}
201201

202+
static struct page *
203+
nfs_readdir_page_array_alloc(u64 last_cookie, gfp_t gfp_flags)
204+
{
205+
struct page *page = alloc_page(gfp_flags);
206+
if (page)
207+
nfs_readdir_page_init_array(page, last_cookie);
208+
return page;
209+
}
210+
211+
static void nfs_readdir_page_array_free(struct page *page)
212+
{
213+
if (page) {
214+
nfs_readdir_clear_array(page);
215+
put_page(page);
216+
}
217+
}
218+
202219
static void nfs_readdir_array_set_eof(struct nfs_cache_array *array)
203220
{
204221
array->page_is_eof = 1;
@@ -694,12 +711,14 @@ void nfs_prime_dcache(struct dentry *parent, struct nfs_entry *entry,
694711
static int nfs_readdir_page_filler(struct nfs_readdir_descriptor *desc,
695712
struct nfs_entry *entry,
696713
struct page **xdr_pages,
697-
struct page *fillme, unsigned int buflen)
714+
unsigned int buflen,
715+
struct page **arrays,
716+
size_t narrays)
698717
{
699718
struct address_space *mapping = desc->file->f_mapping;
700719
struct xdr_stream stream;
701720
struct xdr_buf buf;
702-
struct page *scratch, *new, *page = fillme;
721+
struct page *scratch, *new, *page = *arrays;
703722
int status;
704723

705724
scratch = alloc_page(GFP_KERNEL);
@@ -725,15 +744,25 @@ static int nfs_readdir_page_filler(struct nfs_readdir_descriptor *desc,
725744
if (status != -ENOSPC)
726745
continue;
727746

728-
if (page->mapping != mapping)
729-
break;
730-
new = nfs_readdir_page_get_next(mapping, page->index + 1,
731-
entry->prev_cookie);
732-
if (!new)
733-
break;
734-
if (page != fillme)
735-
nfs_readdir_page_unlock_and_put(page);
736-
page = new;
747+
if (page->mapping != mapping) {
748+
if (!--narrays)
749+
break;
750+
new = nfs_readdir_page_array_alloc(entry->prev_cookie,
751+
GFP_KERNEL);
752+
if (!new)
753+
break;
754+
arrays++;
755+
*arrays = page = new;
756+
} else {
757+
new = nfs_readdir_page_get_next(mapping,
758+
page->index + 1,
759+
entry->prev_cookie);
760+
if (!new)
761+
break;
762+
if (page != *arrays)
763+
nfs_readdir_page_unlock_and_put(page);
764+
page = new;
765+
}
737766
status = nfs_readdir_add_to_array(entry, page);
738767
} while (!status && !entry->eof);
739768

@@ -750,7 +779,7 @@ static int nfs_readdir_page_filler(struct nfs_readdir_descriptor *desc,
750779
break;
751780
}
752781

753-
if (page != fillme)
782+
if (page != *arrays)
754783
nfs_readdir_page_unlock_and_put(page);
755784

756785
put_page(scratch);
@@ -790,10 +819,11 @@ static struct page **nfs_readdir_alloc_pages(size_t npages)
790819
}
791820

792821
static int nfs_readdir_xdr_to_array(struct nfs_readdir_descriptor *desc,
793-
struct page *page, __be32 *verf_arg,
794-
__be32 *verf_res)
822+
__be32 *verf_arg, __be32 *verf_res,
823+
struct page **arrays, size_t narrays)
795824
{
796825
struct page **pages;
826+
struct page *page = *arrays;
797827
struct nfs_entry *entry;
798828
size_t array_size;
799829
struct inode *inode = file_inode(desc->file);
@@ -835,7 +865,8 @@ static int nfs_readdir_xdr_to_array(struct nfs_readdir_descriptor *desc,
835865
break;
836866
}
837867

838-
status = nfs_readdir_page_filler(desc, entry, pages, page, pglen);
868+
status = nfs_readdir_page_filler(desc, entry, pages, pglen,
869+
arrays, narrays);
839870
} while (!status && nfs_readdir_page_needs_filling(page));
840871

841872
nfs_readdir_free_pages(pages, array_size);
@@ -884,8 +915,8 @@ static int find_and_lock_cache_page(struct nfs_readdir_descriptor *desc)
884915
if (!desc->page)
885916
return -ENOMEM;
886917
if (nfs_readdir_page_needs_filling(desc->page)) {
887-
res = nfs_readdir_xdr_to_array(desc, desc->page,
888-
nfsi->cookieverf, verf);
918+
res = nfs_readdir_xdr_to_array(desc, nfsi->cookieverf, verf,
919+
&desc->page, 1);
889920
if (res < 0) {
890921
nfs_readdir_page_unlock_and_put_cached(desc);
891922
if (res == -EBADCOOKIE || res == -ENOTSYNC) {
@@ -976,37 +1007,39 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc)
9761007
*/
9771008
static int uncached_readdir(struct nfs_readdir_descriptor *desc)
9781009
{
979-
struct page *page = NULL;
1010+
struct page **arrays;
1011+
size_t i, sz = 512;
9801012
__be32 verf[NFS_DIR_VERIFIER_SIZE];
981-
int status;
1013+
int status = -ENOMEM;
9821014

983-
dfprintk(DIRCACHE, "NFS: uncached_readdir() searching for cookie %Lu\n",
1015+
dfprintk(DIRCACHE, "NFS: uncached_readdir() searching for cookie %llu\n",
9841016
(unsigned long long)desc->dir_cookie);
9851017

986-
page = alloc_page(GFP_HIGHUSER);
987-
if (!page) {
988-
status = -ENOMEM;
1018+
arrays = kcalloc(sz, sizeof(*arrays), GFP_KERNEL);
1019+
if (!arrays)
1020+
goto out;
1021+
arrays[0] = nfs_readdir_page_array_alloc(desc->dir_cookie, GFP_KERNEL);
1022+
if (!arrays[0])
9891023
goto out;
990-
}
9911024

9921025
desc->page_index = 0;
9931026
desc->last_cookie = desc->dir_cookie;
994-
desc->page = page;
9951027
desc->duped = 0;
9961028

997-
nfs_readdir_page_init_array(page, desc->dir_cookie);
998-
status = nfs_readdir_xdr_to_array(desc, page, desc->verf, verf);
999-
if (status < 0)
1000-
goto out_release;
1029+
status = nfs_readdir_xdr_to_array(desc, desc->verf, verf, arrays, sz);
10011030

1002-
nfs_do_filldir(desc);
1031+
for (i = 0; !desc->eof && i < sz && arrays[i]; i++) {
1032+
desc->page = arrays[i];
1033+
nfs_do_filldir(desc);
1034+
}
1035+
desc->page = NULL;
10031036

1004-
out_release:
1005-
nfs_readdir_clear_array(desc->page);
1006-
nfs_readdir_page_put(desc);
1007-
out:
1008-
dfprintk(DIRCACHE, "NFS: %s: returns %d\n",
1009-
__func__, status);
1037+
1038+
for (i = 0; i < sz && arrays[i]; i++)
1039+
nfs_readdir_page_array_free(arrays[i]);
1040+
out:
1041+
kfree(arrays);
1042+
dfprintk(DIRCACHE, "NFS: %s: returns %d\n", __func__, status);
10101043
return status;
10111044
}
10121045

0 commit comments

Comments
 (0)