summaryrefslogtreecommitdiffstats
path: root/fs/nfs/fscache.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2009-04-03 16:42:44 +0100
committerDavid Howells <dhowells@redhat.com>2009-04-03 16:42:44 +0100
commit545db45f0fc0d4203b045047798ce156972a3056 (patch)
tree783db1091f5d6f21dafece81f6c94caf0aec98b8 /fs/nfs/fscache.c
parent6a51091d0775cdc4a923f2172c61925ad416aa32 (diff)
downloadlinux-545db45f0fc0d4203b045047798ce156972a3056.tar.gz
linux-545db45f0fc0d4203b045047798ce156972a3056.tar.bz2
linux-545db45f0fc0d4203b045047798ce156972a3056.zip
NFS: FS-Cache page management
FS-Cache page management for NFS. This includes hooking the releasing and invalidation of pages marked with PG_fscache (aka PG_private_2) and waiting for completion of the write-to-cache flag (PG_fscache_write aka PG_owner_priv_2). Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: Steve Dickson <steved@redhat.com> Acked-by: Trond Myklebust <Trond.Myklebust@netapp.com> Acked-by: Al Viro <viro@zeniv.linux.org.uk> Tested-by: Daire Byrne <Daire.Byrne@framestore.com>
Diffstat (limited to 'fs/nfs/fscache.c')
-rw-r--r--fs/nfs/fscache.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
index e3816eb53fb8..f673d35d8b89 100644
--- a/fs/nfs/fscache.c
+++ b/fs/nfs/fscache.c
@@ -19,6 +19,7 @@
#include <linux/seq_file.h>
#include "internal.h"
+#include "iostat.h"
#include "fscache.h"
#define NFSDBG_FACILITY NFSDBG_FSCACHE
@@ -328,3 +329,55 @@ void nfs_fscache_reset_inode_cookie(struct inode *inode)
}
nfs_fscache_inode_unlock(inode);
}
+
+/*
+ * Release the caching state associated with a page, if the page isn't busy
+ * interacting with the cache.
+ * - Returns true (can release page) or false (page busy).
+ */
+int nfs_fscache_release_page(struct page *page, gfp_t gfp)
+{
+ struct nfs_inode *nfsi = NFS_I(page->mapping->host);
+ struct fscache_cookie *cookie = nfsi->fscache;
+
+ BUG_ON(!cookie);
+
+ if (fscache_check_page_write(cookie, page)) {
+ if (!(gfp & __GFP_WAIT))
+ return 0;
+ fscache_wait_on_page_write(cookie, page);
+ }
+
+ if (PageFsCache(page)) {
+ dfprintk(FSCACHE, "NFS: fscache releasepage (0x%p/0x%p/0x%p)\n",
+ cookie, page, nfsi);
+
+ fscache_uncache_page(cookie, page);
+ nfs_add_fscache_stats(page->mapping->host,
+ NFSIOS_FSCACHE_PAGES_UNCACHED, 1);
+ }
+
+ return 1;
+}
+
+/*
+ * Release the caching state associated with a page if undergoing complete page
+ * invalidation.
+ */
+void __nfs_fscache_invalidate_page(struct page *page, struct inode *inode)
+{
+ struct nfs_inode *nfsi = NFS_I(inode);
+ struct fscache_cookie *cookie = nfsi->fscache;
+
+ BUG_ON(!cookie);
+
+ dfprintk(FSCACHE, "NFS: fscache invalidatepage (0x%p/0x%p/0x%p)\n",
+ cookie, page, nfsi);
+
+ fscache_wait_on_page_write(cookie, page);
+
+ BUG_ON(!PageLocked(page));
+ fscache_uncache_page(cookie, page);
+ nfs_add_fscache_stats(page->mapping->host,
+ NFSIOS_FSCACHE_PAGES_UNCACHED, 1);
+}