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 <[email protected]>
---
fs/nfs/dir.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)
diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c
index ef827ae193d2..ade73ca42a52 100644
--- a/fs/nfs/dir.c
+++ b/fs/nfs/dir.c
@@ -53,6 +53,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 = {
@@ -65,6 +68,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,
};
@@ -181,6 +186,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);
}
/*
@@ -744,6 +770,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;
@@ -770,10 +798,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;
--
2.25.4