Skip to content

Commit

Permalink
NFS: Optimisations for monotonically increasing readdir cookies
Browse files Browse the repository at this point in the history
If the server is handing out monotonically increasing readdir cookie values,
then we can optimise away searches through pages that contain cookies that
lie outside our search range.

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>
  • Loading branch information
Trond Myklebust committed Dec 2, 2020
1 parent b593c09 commit 762567b
Showing 1 changed file with 22 additions and 1 deletion.
23 changes: 22 additions & 1 deletion fs/nfs/dir.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ struct nfs_cache_array {
u64 last_cookie;
unsigned int size;
unsigned char page_full : 1,
page_is_eof : 1;
page_is_eof : 1,
cookies_are_ordered : 1;
struct nfs_cache_array_entry array[];
};

Expand Down Expand Up @@ -178,6 +179,7 @@ static void nfs_readdir_page_init_array(struct page *page, u64 last_cookie)
array = kmap_atomic(page);
nfs_readdir_array_init(array);
array->last_cookie = last_cookie;
array->cookies_are_ordered = 1;
kunmap_atomic(array);
}

Expand Down Expand Up @@ -269,6 +271,8 @@ int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page)
cache_entry->name_len = entry->len;
cache_entry->name = name;
array->last_cookie = entry->cookie;
if (array->last_cookie <= cache_entry->cookie)
array->cookies_are_ordered = 0;
array->size++;
if (entry->eof != 0)
nfs_readdir_array_set_eof(array);
Expand Down Expand Up @@ -395,13 +399,29 @@ nfs_readdir_inode_mapping_valid(struct nfs_inode *nfsi)
return !test_bit(NFS_INO_INVALIDATING, &nfsi->flags);
}

static bool nfs_readdir_array_cookie_in_range(struct nfs_cache_array *array,
u64 cookie)
{
if (!array->cookies_are_ordered)
return true;
/* Optimisation for monotonically increasing cookies */
if (cookie >= array->last_cookie)
return false;
if (array->size && cookie < array->array[0].cookie)
return false;
return true;
}

static int nfs_readdir_search_for_cookie(struct nfs_cache_array *array,
struct nfs_readdir_descriptor *desc)
{
int i;
loff_t new_pos;
int status = -EAGAIN;

if (!nfs_readdir_array_cookie_in_range(array, desc->dir_cookie))
goto check_eof;

for (i = 0; i < array->size; i++) {
if (array->array[i].cookie == desc->dir_cookie) {
struct nfs_inode *nfsi = NFS_I(file_inode(desc->file));
Expand Down Expand Up @@ -435,6 +455,7 @@ static int nfs_readdir_search_for_cookie(struct nfs_cache_array *array,
return 0;
}
}
check_eof:
if (array->page_is_eof) {
status = -EBADCOOKIE;
if (desc->dir_cookie == array->last_cookie)
Expand Down

0 comments on commit 762567b

Please sign in to comment.