Commit 762567b7 authored by Trond Myklebust's avatar Trond Myklebust

NFS: Optimisations for monotonically increasing readdir cookies

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: default avatarTrond Myklebust <trond.myklebust@hammerspace.com>
Reviewed-by: default avatarBenjamin Coddington <bcodding@redhat.com>
Tested-by: default avatarBenjamin Coddington <bcodding@redhat.com>
Tested-by: default avatarDave Wysochanski <dwysocha@redhat.com>
parent b593c09f
...@@ -140,7 +140,8 @@ struct nfs_cache_array { ...@@ -140,7 +140,8 @@ struct nfs_cache_array {
u64 last_cookie; u64 last_cookie;
unsigned int size; unsigned int size;
unsigned char page_full : 1, unsigned char page_full : 1,
page_is_eof : 1; page_is_eof : 1,
cookies_are_ordered : 1;
struct nfs_cache_array_entry array[]; struct nfs_cache_array_entry array[];
}; };
...@@ -178,6 +179,7 @@ static void nfs_readdir_page_init_array(struct page *page, u64 last_cookie) ...@@ -178,6 +179,7 @@ static void nfs_readdir_page_init_array(struct page *page, u64 last_cookie)
array = kmap_atomic(page); array = kmap_atomic(page);
nfs_readdir_array_init(array); nfs_readdir_array_init(array);
array->last_cookie = last_cookie; array->last_cookie = last_cookie;
array->cookies_are_ordered = 1;
kunmap_atomic(array); kunmap_atomic(array);
} }
...@@ -269,6 +271,8 @@ int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page) ...@@ -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_len = entry->len;
cache_entry->name = name; cache_entry->name = name;
array->last_cookie = entry->cookie; array->last_cookie = entry->cookie;
if (array->last_cookie <= cache_entry->cookie)
array->cookies_are_ordered = 0;
array->size++; array->size++;
if (entry->eof != 0) if (entry->eof != 0)
nfs_readdir_array_set_eof(array); nfs_readdir_array_set_eof(array);
...@@ -395,6 +399,19 @@ nfs_readdir_inode_mapping_valid(struct nfs_inode *nfsi) ...@@ -395,6 +399,19 @@ nfs_readdir_inode_mapping_valid(struct nfs_inode *nfsi)
return !test_bit(NFS_INO_INVALIDATING, &nfsi->flags); 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, static int nfs_readdir_search_for_cookie(struct nfs_cache_array *array,
struct nfs_readdir_descriptor *desc) struct nfs_readdir_descriptor *desc)
{ {
...@@ -402,6 +419,9 @@ static int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, ...@@ -402,6 +419,9 @@ static int nfs_readdir_search_for_cookie(struct nfs_cache_array *array,
loff_t new_pos; loff_t new_pos;
int status = -EAGAIN; int status = -EAGAIN;
if (!nfs_readdir_array_cookie_in_range(array, desc->dir_cookie))
goto check_eof;
for (i = 0; i < array->size; i++) { for (i = 0; i < array->size; i++) {
if (array->array[i].cookie == desc->dir_cookie) { if (array->array[i].cookie == desc->dir_cookie) {
struct nfs_inode *nfsi = NFS_I(file_inode(desc->file)); struct nfs_inode *nfsi = NFS_I(file_inode(desc->file));
...@@ -435,6 +455,7 @@ static int nfs_readdir_search_for_cookie(struct nfs_cache_array *array, ...@@ -435,6 +455,7 @@ static int nfs_readdir_search_for_cookie(struct nfs_cache_array *array,
return 0; return 0;
} }
} }
check_eof:
if (array->page_is_eof) { if (array->page_is_eof) {
status = -EBADCOOKIE; status = -EBADCOOKIE;
if (desc->dir_cookie == array->last_cookie) if (desc->dir_cookie == array->last_cookie)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment