@@ -54,6 +54,9 @@ static int nfs_closedir(struct inode *, struct file *);
static int nfs_readdir(struct file *, struct dir_context *);
static int nfs_fsync_dir(struct file *, loff_t, loff_t, int);
static loff_t nfs_llseek_dir(struct file *, loff_t, int);
+static void nfs_readdir_invalidatepage(struct page *,
+ unsigned int, unsigned int);
+static int nfs_readdir_clear_page(struct page*, gfp_t);
static void nfs_readdir_clear_array(struct page*);
const struct file_operations nfs_dir_operations = {
@@ -66,6 +69,8 @@ const struct file_operations nfs_dir_operations = {
};
const struct address_space_operations nfs_dir_aops = {
+ .invalidatepage = nfs_readdir_invalidatepage,
+ .releasepage = nfs_readdir_clear_page,
.freepage = nfs_readdir_clear_array,
};
@@ -212,6 +217,27 @@ static void nfs_readdir_page_init_array(struct page *page, u64 last_cookie)
array->last_cookie = last_cookie;
array->cookies_are_ordered = 1;
kunmap_atomic(array);
+ set_page_private(page, 0);
+}
+
+static int
+nfs_readdir_clear_page(struct page *page, gfp_t gfp_mask)
+{
+ detach_page_private(page);
+ return 1;
+}
+
+static void
+nfs_readdir_invalidatepage(struct page *page, unsigned int offset,
+ unsigned int length)
+{
+ nfs_readdir_clear_page(page, GFP_KERNEL);
+}
+
+static void
+nfs_readdir_set_page_verifier(struct page *page, unsigned long verf)
+{
+ attach_page_private(page, (void *)verf);
}
/*
@@ -794,6 +820,8 @@ static int nfs_readdir_page_filler(struct nfs_readdir_descriptor *desc,
if (status != -ENOSPC)
continue;
+ nfs_readdir_set_page_verifier(page, desc->dir_verifier);
+
if (page->mapping != mapping) {
if (!--narrays)
break;
@@ -822,10 +850,13 @@ static int nfs_readdir_page_filler(struct nfs_readdir_descriptor *desc,
case -EBADCOOKIE:
if (entry->eof) {
nfs_readdir_page_set_eof(page);
+ nfs_readdir_set_page_verifier(page, desc->dir_verifier);
status = 0;
}
break;
case -ENOSPC:
+ nfs_readdir_set_page_verifier(page, desc->dir_verifier);
+ fallthrough;
case -EAGAIN:
status = 0;
break;
After a pagecache page has been filled with entries, set PagePrivate and the directory's change attribute on the page. This will help us perform per-page invalidations in a later patch. Signed-off-by: Benjamin Coddington <bcodding@redhat.com> --- fs/nfs/dir.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+)