From: Dave Wysochanski <dwyso...@redhat.com>

Convert nfs_fscache_invalidate to the new FS-Cache API.  Also,
now when invalidating an fscache cookie, be sure to pass the latest
i_size as well as aux_data to fscache.

A few APIs no longer exist so remove them.  We can call directly to
wait_on_page_fscache() because it checks whether a page is an fscache
page before waiting on it.

Since the current NFS fscache implementation is only enabled when a
file is open for read, handle writes with invalidation.  If a write
extends the size of the file and fscache is enabled, we must invalidate
the object with the new size.

We must also invalidate fscache when doing a direct write to avoid
issues seen specifically with NFSv4.x when direct writes are followed
by non-direct (buffered) reads.  Note that we cannot call
fscache_invalidate() while holding inode->i_lock.

Signed-off-by: Dave Wysochanski <dwyso...@redhat.com>
Signed-off-by: David Howells <dhowe...@redhat.com>
cc: Trond Myklebust <trond.mykleb...@hammerspace.com>
cc: Anna Schumaker <anna.schuma...@netapp.com>
cc: linux-...@vger.kernel.org
---

 fs/nfs/direct.c  |    2 ++
 fs/nfs/file.c    |    7 ++++++-
 fs/nfs/fscache.c |   20 --------------------
 fs/nfs/fscache.h |   32 ++++++++++++++++++++++----------
 fs/nfs/inode.c   |    4 ++--
 fs/nfs/write.c   |    1 +
 6 files changed, 33 insertions(+), 33 deletions(-)

diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 2e894fec036b..8b4839ef4b0c 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -59,6 +59,7 @@
 #include "internal.h"
 #include "iostat.h"
 #include "pnfs.h"
+#include "fscache.h"
 
 #define NFSDBG_FACILITY                NFSDBG_VFS
 
@@ -959,6 +960,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct 
iov_iter *iter)
        } else {
                result = requested;
        }
+       nfs_fscache_invalidate(inode, FSCACHE_INVAL_DIO_WRITE);
 out_release:
        nfs_direct_req_release(dreq);
 out:
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 209dac208477..0a7f1e9f1203 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -436,6 +436,7 @@ static int nfs_release_page(struct page *page, gfp_t gfp)
                if (!(gfp & __GFP_DIRECT_RECLAIM) || !(gfp & __GFP_FS))
                        return false;
                wait_on_page_fscache(page);
+               fscache_note_page_release(nfs_i_fscache(page->mapping->host));
        }
        return true;
 }
@@ -559,7 +560,11 @@ static vm_fault_t nfs_vm_page_mkwrite(struct vm_fault *vmf)
        sb_start_pagefault(inode->i_sb);
 
        /* make sure the cache has finished storing the page */
-       wait_on_page_fscache(page);
+       if (PageFsCache(page) &&
+           wait_on_page_fscache_killable(vmf->page) < 0) {
+               ret = VM_FAULT_RETRY;
+               goto out;
+       }
 
        wait_on_bit_action(&NFS_I(inode)->flags, NFS_INO_INVALIDATING,
                        nfs_wait_bit_killable, TASK_KILLABLE);
diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
index 5e584f2e84a9..8250a029759e 100644
--- a/fs/nfs/fscache.c
+++ b/fs/nfs/fscache.c
@@ -234,19 +234,6 @@ void nfs_fscache_release_super_cookie(struct super_block 
*sb)
        }
 }
 
-static void nfs_fscache_update_auxdata(struct nfs_fscache_inode_auxdata 
*auxdata,
-                                 struct nfs_inode *nfsi)
-{
-       memset(auxdata, 0, sizeof(*auxdata));
-       auxdata->mtime_sec  = nfsi->vfs_inode.i_mtime.tv_sec;
-       auxdata->mtime_nsec = nfsi->vfs_inode.i_mtime.tv_nsec;
-       auxdata->ctime_sec  = nfsi->vfs_inode.i_ctime.tv_sec;
-       auxdata->ctime_nsec = nfsi->vfs_inode.i_ctime.tv_nsec;
-
-       if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4)
-               auxdata->change_attr = 
inode_peek_iversion_raw(&nfsi->vfs_inode);
-}
-
 /*
  * Initialise the per-inode cache cookie pointer for an NFS inode.
  */
@@ -293,13 +280,6 @@ void nfs_fscache_clear_inode(struct inode *inode)
        nfsi->fscache = NULL;
 }
 
-static bool nfs_fscache_can_enable(void *data)
-{
-       struct inode *inode = data;
-
-       return !inode_is_open_for_write(inode);
-}
-
 /*
  * Enable or disable caching for a file that is being opened as appropriate.
  * The cookie is allocated when the inode is initialised, but is not enabled at
diff --git a/fs/nfs/fscache.h b/fs/nfs/fscache.h
index 1e30fcb45665..cc94b257059b 100644
--- a/fs/nfs/fscache.h
+++ b/fs/nfs/fscache.h
@@ -13,6 +13,7 @@
 #include <linux/nfs4_mount.h>
 #define FSCACHE_USE_FALLBACK_IO_API
 #include <linux/fscache.h>
+#include <linux/iversion.h>
 
 #ifdef CONFIG_NFS_FSCACHE
 
@@ -118,20 +119,32 @@ static inline void nfs_readpage_to_fscache(struct inode 
*inode,
                __nfs_readpage_to_fscache(inode, page);
 }
 
-/*
- * Invalidate the contents of fscache for this inode.  This will not sleep.
- */
-static inline void nfs_fscache_invalidate(struct inode *inode)
+static inline void nfs_fscache_update_auxdata(struct nfs_fscache_inode_auxdata 
*auxdata,
+                                 struct nfs_inode *nfsi)
 {
-       fscache_invalidate(NFS_I(inode)->fscache);
+       memset(auxdata, 0, sizeof(*auxdata));
+       auxdata->mtime_sec  = nfsi->vfs_inode.i_mtime.tv_sec;
+       auxdata->mtime_nsec = nfsi->vfs_inode.i_mtime.tv_nsec;
+       auxdata->ctime_sec  = nfsi->vfs_inode.i_ctime.tv_sec;
+       auxdata->ctime_nsec = nfsi->vfs_inode.i_ctime.tv_nsec;
+
+       if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4)
+               auxdata->change_attr = 
inode_peek_iversion_raw(&nfsi->vfs_inode);
 }
 
 /*
- * Wait for an object to finish being invalidated.
+ * Invalidate the contents of fscache for this inode.  This will not sleep.
  */
-static inline void nfs_fscache_wait_on_invalidate(struct inode *inode)
+static inline void nfs_fscache_invalidate(struct inode *inode, int flags)
 {
-       fscache_wait_on_invalidate(NFS_I(inode)->fscache);
+       struct nfs_fscache_inode_auxdata auxdata;
+       struct nfs_inode *nfsi = NFS_I(inode);
+
+       if (nfsi->fscache) {
+               nfs_fscache_update_auxdata(&auxdata, nfsi);
+               fscache_invalidate(nfsi->fscache, &auxdata,
+                                  i_size_read(&nfsi->vfs_inode), flags);
+       }
 }
 
 /*
@@ -167,8 +180,7 @@ static inline void nfs_readpage_to_fscache(struct inode 
*inode,
                                           struct page *page) {}
 
 
-static inline void nfs_fscache_invalidate(struct inode *inode) {}
-static inline void nfs_fscache_wait_on_invalidate(struct inode *inode) {}
+static inline void nfs_fscache_invalidate(struct inode *inode, int flags) {}
 
 static inline const char *nfs_server_fscache_state(struct nfs_server *server)
 {
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 853213b3a209..370c49b98646 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -209,7 +209,7 @@ void nfs_set_cache_invalid(struct inode *inode, unsigned 
long flags)
        if (!nfs_has_xattr_cache(nfsi))
                flags &= ~NFS_INO_INVALID_XATTR;
        if (flags & NFS_INO_INVALID_DATA)
-               nfs_fscache_invalidate(inode);
+               nfs_fscache_invalidate(inode, 0);
        if (inode->i_mapping->nrpages == 0)
                flags &= ~(NFS_INO_INVALID_DATA|NFS_INO_DATA_INVAL_DEFER);
        flags &= ~(NFS_INO_REVAL_PAGECACHE | NFS_INO_REVAL_FORCED);
@@ -1281,6 +1281,7 @@ static int nfs_invalidate_mapping(struct inode *inode, 
struct address_space *map
 {
        int ret;
 
+       nfs_fscache_invalidate(inode, 0);
        if (mapping->nrpages != 0) {
                if (S_ISREG(inode->i_mode)) {
                        ret = nfs_sync_mapping(mapping);
@@ -1292,7 +1293,6 @@ static int nfs_invalidate_mapping(struct inode *inode, 
struct address_space *map
                        return ret;
        }
        nfs_inc_stats(inode, NFSIOS_DATAINVALIDATE);
-       nfs_fscache_wait_on_invalidate(inode);
 
        dfprintk(PAGECACHE, "NFS: (%s/%Lu) data cache invalidated\n",
                        inode->i_sb->s_id,
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 466266a96b2a..cbbf400db126 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -293,6 +293,7 @@ static void nfs_grow_file(struct page *page, unsigned int 
offset, unsigned int c
        nfs_inc_stats(inode, NFSIOS_EXTENDWRITE);
 out:
        spin_unlock(&inode->i_lock);
+       nfs_fscache_invalidate(inode, 0);
 }
 
 /* A writeback failed: mark the page as bad, and invalidate the page cache */


--
Linux-cachefs mailing list
Linux-cachefs@redhat.com
https://listman.redhat.com/mailman/listinfo/linux-cachefs

Reply via email to