@@ -154,6 +154,10 @@ struct nfs_cache_array {
struct nfs_cache_array_entry array[];
};
+static const int cache_entries_per_page =
+ (PAGE_SIZE - sizeof(struct nfs_cache_array)) /
+ sizeof(struct nfs_cache_array_entry);
+
struct nfs_readdir_descriptor {
struct file *file;
struct page *page;
@@ -282,6 +286,21 @@ static bool nfs_readdir_array_is_full(struct nfs_cache_array *array)
return array->page_full;
}
+static void nfs_readdir_set_cursor(struct nfs_readdir_descriptor *desc, int index)
+{
+ desc->pgc.entry_index = index;
+ desc->pgc.index_cookie = desc->dir_cookie;
+}
+
+static void nfs_readdir_cursor_next(struct nfs_dir_page_cursor *pgc, u64 cookie)
+{
+ pgc->index_cookie = cookie;
+ if (++pgc->entry_index == cache_entries_per_page) {
+ pgc->entry_index = 0;
+ pgc->page_index++;
+ }
+}
+
/*
* the caller is responsible for freeing qstr.name
* when called by nfs_readdir_add_to_array, the strings will be freed in
@@ -455,7 +474,7 @@ static int nfs_readdir_search_for_pos(struct nfs_cache_array *array,
index = (unsigned int)diff;
desc->dir_cookie = array->array[index].cookie;
- desc->pgc.entry_index = index;
+ nfs_readdir_set_cursor(desc, index);
return 0;
out_eof:
desc->eof = true;
@@ -524,7 +543,7 @@ static int nfs_readdir_search_for_cookie(struct nfs_cache_array *array,
else
desc->ctx->pos = new_pos;
desc->prev_index = new_pos;
- desc->pgc.entry_index = i;
+ nfs_readdir_set_cursor(desc, i);
return 0;
}
}
@@ -551,9 +570,9 @@ static int nfs_readdir_search_array(struct nfs_readdir_descriptor *desc)
status = nfs_readdir_search_for_cookie(array, desc);
if (status == -EAGAIN) {
- desc->pgc.index_cookie = array->last_cookie;
+ desc->pgc.entry_index = array->size - 1;
+ nfs_readdir_cursor_next(&desc->pgc, array->last_cookie);
desc->current_index += array->size;
- desc->pgc.page_index++;
}
kunmap_atomic(array);
return status;
@@ -1084,6 +1103,8 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc,
desc->eof = !desc->eob;
kunmap(desc->page);
+ desc->pgc.entry_index = i-1;
+ nfs_readdir_cursor_next(&desc->pgc, desc->dir_cookie);
dfprintk(DIRCACHE, "NFS: nfs_do_filldir() filling ended @ cookie %llu\n",
(unsigned long long)desc->dir_cookie);
}
@@ -1118,8 +1139,7 @@ static int uncached_readdir(struct nfs_readdir_descriptor *desc)
goto out;
desc->pgc.page_index = 0;
- desc->pgc.entry_index = 0;
- desc->pgc.index_cookie = desc->dir_cookie;
+ nfs_readdir_set_cursor(desc, 0);
desc->duped = 0;
desc->page_index_max = 0;
Whenever we successfully locate our dir_cookie within the pagecache, or finish emitting entries to userspace, update the pagecache cursor. These updates provide marker points to validate pagecache pages in a future patch. Signed-off-by: Benjamin Coddington <bcodding@redhat.com> --- fs/nfs/dir.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-)