xref: /openbmc/linux/fs/nfs/fscache.h (revision 16f2f4e6)
1b4d0d230SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */
28ec442aeSDavid Howells /* NFS filesystem cache interface definitions
38ec442aeSDavid Howells  *
48ec442aeSDavid Howells  * Copyright (C) 2008 Red Hat, Inc. All Rights Reserved.
58ec442aeSDavid Howells  * Written by David Howells (dhowells@redhat.com)
68ec442aeSDavid Howells  */
78ec442aeSDavid Howells 
88ec442aeSDavid Howells #ifndef _NFS_FSCACHE_H
98ec442aeSDavid Howells #define _NFS_FSCACHE_H
108ec442aeSDavid Howells 
118ec442aeSDavid Howells #include <linux/nfs_fs.h>
128ec442aeSDavid Howells #include <linux/nfs_mount.h>
138ec442aeSDavid Howells #include <linux/nfs4_mount.h>
148ec442aeSDavid Howells #include <linux/fscache.h>
15a6b5a28eSDave Wysochanski #include <linux/iversion.h>
168ec442aeSDavid Howells 
178ec442aeSDavid Howells #ifdef CONFIG_NFS_FSCACHE
188ec442aeSDavid Howells 
198ec442aeSDavid Howells /*
20402cb8ddSDavid Howells  * Definition of the auxiliary data attached to NFS inode storage objects
21402cb8ddSDavid Howells  * within the cache.
22402cb8ddSDavid Howells  *
23402cb8ddSDavid Howells  * The contents of this struct are recorded in the on-disk local cache in the
24402cb8ddSDavid Howells  * auxiliary data attached to the data storage object backing an inode.  This
25402cb8ddSDavid Howells  * permits coherency to be managed when a new inode binds to an already extant
26402cb8ddSDavid Howells  * cache object.
27402cb8ddSDavid Howells  */
28402cb8ddSDavid Howells struct nfs_fscache_inode_auxdata {
296e31ded6SArnd Bergmann 	s64	mtime_sec;
306e31ded6SArnd Bergmann 	s64	mtime_nsec;
316e31ded6SArnd Bergmann 	s64	ctime_sec;
326e31ded6SArnd Bergmann 	s64	ctime_nsec;
33402cb8ddSDavid Howells 	u64	change_attr;
34402cb8ddSDavid Howells };
35402cb8ddSDavid Howells 
36402cb8ddSDavid Howells /*
3714727281SDavid Howells  * fscache.c
3814727281SDavid Howells  */
39a6b5a28eSDave Wysochanski extern int nfs_fscache_get_super_cookie(struct super_block *, const char *, int);
4008734048SDavid Howells extern void nfs_fscache_release_super_cookie(struct super_block *);
4108734048SDavid Howells 
42f1fe29b4SDavid Howells extern void nfs_fscache_init_inode(struct inode *);
43f1fe29b4SDavid Howells extern void nfs_fscache_clear_inode(struct inode *);
44f1fe29b4SDavid Howells extern void nfs_fscache_open_file(struct inode *, struct file *);
45a6b5a28eSDave Wysochanski extern void nfs_fscache_release_file(struct inode *, struct file *);
46ef79c097SDavid Howells 
47*16f2f4e6SDavid Howells extern int __nfs_readpage_from_fscache(struct inode *, struct page *);
48*16f2f4e6SDavid Howells extern void __nfs_read_completion_to_fscache(struct nfs_pgio_header *hdr,
49*16f2f4e6SDavid Howells 					     unsigned long bytes);
50*16f2f4e6SDavid Howells extern void __nfs_readpage_to_fscache(struct inode *, struct page *);
519a9fc1c0SDavid Howells 
52a6b5a28eSDave Wysochanski static inline int nfs_fscache_release_page(struct page *page, gfp_t gfp)
53545db45fSDavid Howells {
54a6b5a28eSDave Wysochanski 	if (PageFsCache(page)) {
55a6b5a28eSDave Wysochanski 		if (!gfpflags_allow_blocking(gfp) || !(gfp & __GFP_FS))
56a6b5a28eSDave Wysochanski 			return false;
57a6b5a28eSDave Wysochanski 		wait_on_page_fscache(page);
58a6b5a28eSDave Wysochanski 		fscache_note_page_release(nfs_i_fscache(page->mapping->host));
59a6b5a28eSDave Wysochanski 		nfs_inc_fscache_stats(page->mapping->host,
60a6b5a28eSDave Wysochanski 				      NFSIOS_FSCACHE_PAGES_UNCACHED);
61545db45fSDavid Howells 	}
62a6b5a28eSDave Wysochanski 	return true;
63545db45fSDavid Howells }
64545db45fSDavid Howells 
659a9fc1c0SDavid Howells /*
669a9fc1c0SDavid Howells  * Retrieve a page from an inode data storage object.
679a9fc1c0SDavid Howells  */
68*16f2f4e6SDavid Howells static inline int nfs_readpage_from_fscache(struct inode *inode,
699a9fc1c0SDavid Howells 					    struct page *page)
709a9fc1c0SDavid Howells {
719a9fc1c0SDavid Howells 	if (NFS_I(inode)->fscache)
72*16f2f4e6SDavid Howells 		return __nfs_readpage_from_fscache(inode, page);
739a9fc1c0SDavid Howells 	return -ENOBUFS;
749a9fc1c0SDavid Howells }
75545db45fSDavid Howells 
767f8e05f6SDavid Howells /*
777f8e05f6SDavid Howells  * Store a page newly fetched from the server in an inode data storage object
787f8e05f6SDavid Howells  * in the cache.
797f8e05f6SDavid Howells  */
807f8e05f6SDavid Howells static inline void nfs_readpage_to_fscache(struct inode *inode,
81*16f2f4e6SDavid Howells 					   struct page *page)
827f8e05f6SDavid Howells {
83*16f2f4e6SDavid Howells 	if (NFS_I(inode)->fscache)
84*16f2f4e6SDavid Howells 		__nfs_readpage_to_fscache(inode, page);
857f8e05f6SDavid Howells }
867f8e05f6SDavid Howells 
87a6b5a28eSDave Wysochanski static inline void nfs_fscache_update_auxdata(struct nfs_fscache_inode_auxdata *auxdata,
88a6b5a28eSDave Wysochanski 					      struct nfs_inode *nfsi)
89de242c0bSDavid Howells {
90a6b5a28eSDave Wysochanski 	memset(auxdata, 0, sizeof(*auxdata));
91a6b5a28eSDave Wysochanski 	auxdata->mtime_sec  = nfsi->vfs_inode.i_mtime.tv_sec;
92a6b5a28eSDave Wysochanski 	auxdata->mtime_nsec = nfsi->vfs_inode.i_mtime.tv_nsec;
93a6b5a28eSDave Wysochanski 	auxdata->ctime_sec  = nfsi->vfs_inode.i_ctime.tv_sec;
94a6b5a28eSDave Wysochanski 	auxdata->ctime_nsec = nfsi->vfs_inode.i_ctime.tv_nsec;
95a6b5a28eSDave Wysochanski 
96a6b5a28eSDave Wysochanski 	if (NFS_SERVER(&nfsi->vfs_inode)->nfs_client->rpc_ops->version == 4)
97a6b5a28eSDave Wysochanski 		auxdata->change_attr = inode_peek_iversion_raw(&nfsi->vfs_inode);
98de242c0bSDavid Howells }
99de242c0bSDavid Howells 
100de242c0bSDavid Howells /*
101a6b5a28eSDave Wysochanski  * Invalidate the contents of fscache for this inode.  This will not sleep.
102de242c0bSDavid Howells  */
103a6b5a28eSDave Wysochanski static inline void nfs_fscache_invalidate(struct inode *inode, int flags)
104de242c0bSDavid Howells {
105a6b5a28eSDave Wysochanski 	struct nfs_fscache_inode_auxdata auxdata;
106a6b5a28eSDave Wysochanski 	struct nfs_inode *nfsi = NFS_I(inode);
107a6b5a28eSDave Wysochanski 
108a6b5a28eSDave Wysochanski 	if (nfsi->fscache) {
109a6b5a28eSDave Wysochanski 		nfs_fscache_update_auxdata(&auxdata, nfsi);
110a6b5a28eSDave Wysochanski 		fscache_invalidate(nfsi->fscache, &auxdata,
111a6b5a28eSDave Wysochanski 				   i_size_read(&nfsi->vfs_inode), flags);
112a6b5a28eSDave Wysochanski 	}
113de242c0bSDavid Howells }
114de242c0bSDavid Howells 
115de242c0bSDavid Howells /*
1165d1acff1SDavid Howells  * indicate the client caching state as readable text
1175d1acff1SDavid Howells  */
1185d1acff1SDavid Howells static inline const char *nfs_server_fscache_state(struct nfs_server *server)
1195d1acff1SDavid Howells {
120dea1bb35STrond Myklebust 	if (server->fscache)
1215d1acff1SDavid Howells 		return "yes";
1225d1acff1SDavid Howells 	return "no ";
1235d1acff1SDavid Howells }
1245d1acff1SDavid Howells 
1258ec442aeSDavid Howells #else /* CONFIG_NFS_FSCACHE */
12608734048SDavid Howells static inline void nfs_fscache_release_super_cookie(struct super_block *sb) {}
12708734048SDavid Howells 
128f1fe29b4SDavid Howells static inline void nfs_fscache_init_inode(struct inode *inode) {}
129f1fe29b4SDavid Howells static inline void nfs_fscache_clear_inode(struct inode *inode) {}
130f1fe29b4SDavid Howells static inline void nfs_fscache_open_file(struct inode *inode,
131ef79c097SDavid Howells 					 struct file *filp) {}
132a6b5a28eSDave Wysochanski static inline void nfs_fscache_release_file(struct inode *inode, struct file *file) {}
133ef79c097SDavid Howells 
134545db45fSDavid Howells static inline int nfs_fscache_release_page(struct page *page, gfp_t gfp)
135545db45fSDavid Howells {
136545db45fSDavid Howells 	return 1; /* True: may release page */
137545db45fSDavid Howells }
138*16f2f4e6SDavid Howells static inline int nfs_readpage_from_fscache(struct inode *inode,
1399a9fc1c0SDavid Howells 					    struct page *page)
1409a9fc1c0SDavid Howells {
1419a9fc1c0SDavid Howells 	return -ENOBUFS;
1429a9fc1c0SDavid Howells }
1437f8e05f6SDavid Howells static inline void nfs_readpage_to_fscache(struct inode *inode,
144*16f2f4e6SDavid Howells 					   struct page *page) {}
1459a9fc1c0SDavid Howells 
146de242c0bSDavid Howells 
147a6b5a28eSDave Wysochanski static inline void nfs_fscache_invalidate(struct inode *inode, int flags) {}
148de242c0bSDavid Howells 
1495d1acff1SDavid Howells static inline const char *nfs_server_fscache_state(struct nfs_server *server)
1505d1acff1SDavid Howells {
1515d1acff1SDavid Howells 	return "no ";
1525d1acff1SDavid Howells }
1535d1acff1SDavid Howells 
1548ec442aeSDavid Howells #endif /* CONFIG_NFS_FSCACHE */
1558ec442aeSDavid Howells #endif /* _NFS_FSCACHE_H */
156