1 /* fscache.h: NFS filesystem cache interface definitions
3 * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
12 #ifndef _NFS_FSCACHE_H
13 #define _NFS_FSCACHE_H
15 #include <linux/nfs_fs.h>
16 #include <linux/nfs_mount.h>
17 #include <linux/nfs4_mount.h>
19 #ifdef CONFIG_NFS_FSCACHE
20 #include <linux/fscache.h>
22 extern struct fscache_netfs nfs_cache_netfs;
23 extern struct fscache_cookie_def nfs_cache_server_index_def;
24 extern struct fscache_cookie_def nfs_cache_fh_index_def;
25 extern struct vm_operations_struct nfs_fs_vm_operations;
27 extern void nfs_invalidatepage(struct page *, unsigned long);
28 extern int nfs_releasepage(struct page *, gfp_t);
30 extern atomic_t nfs_fscache_to_pages;
31 extern atomic_t nfs_fscache_from_pages;
32 extern atomic_t nfs_fscache_uncache_page;
33 extern int nfs_fscache_from_error;
34 extern int nfs_fscache_to_error;
37 * register NFS for caching
39 static inline int nfs_fscache_register(void)
41 return fscache_register_netfs(&nfs_cache_netfs);
45 * unregister NFS for caching
47 static inline void nfs_fscache_unregister(void)
49 fscache_unregister_netfs(&nfs_cache_netfs);
53 * get the per-client index cookie for an NFS client if the appropriate mount
55 * - we always try and get an index cookie for the client, but get filehandle
56 * cookies on a per-superblock basis, depending on the mount flags
58 static inline void nfs_fscache_get_client_cookie(struct nfs_client *clp)
60 /* create a cache index for looking up filehandles */
61 clp->fscache = fscache_acquire_cookie(nfs_cache_netfs.primary_index,
62 &nfs_cache_server_index_def,
64 dfprintk(FSCACHE,"NFS: get client cookie (0x%p/0x%p)\n",
69 * dispose of a per-client cookie
71 static inline void nfs_fscache_release_client_cookie(struct nfs_client *clp)
73 dfprintk(FSCACHE,"NFS: releasing client cookie (0x%p/0x%p)\n",
76 fscache_relinquish_cookie(clp->fscache, 0);
81 * indicate the client caching state as readable text
83 static inline const char *nfs_server_fscache_state(struct nfs_server *server)
85 if (server->nfs_client->fscache && (server->flags & NFS_MOUNT_FSCACHE))
91 * get the per-filehandle cookie for an NFS inode
93 static inline void nfs_fscache_get_fh_cookie(struct super_block *sb,
94 struct nfs_inode *nfsi,
98 if (maycache && (NFS_SB(sb)->flags & NFS_MOUNT_FSCACHE)) {
99 nfsi->fscache = fscache_acquire_cookie(
100 NFS_SB(sb)->nfs_client->fscache,
101 &nfs_cache_fh_index_def,
104 fscache_set_i_size(nfsi->fscache, nfsi->vfs_inode.i_size);
106 dfprintk(FSCACHE, "NFS: get FH cookie (0x%p/0x%p/0x%p)\n",
107 sb, nfsi, nfsi->fscache);
112 * change the filesize associated with a per-filehandle cookie
114 static inline void nfs_fscache_set_size(struct nfs_server *server,
115 struct nfs_inode *nfsi,
118 fscache_set_i_size(nfsi->fscache, i_size);
122 * replace a per-filehandle cookie due to revalidation detecting a file having
123 * changed on the server
125 static inline void nfs_fscache_renew_fh_cookie(struct nfs_server *server,
126 struct nfs_inode *nfsi)
128 struct fscache_cookie *old = nfsi->fscache;
131 /* retire the current fscache cache and get a new one */
132 fscache_relinquish_cookie(nfsi->fscache, 1);
134 nfsi->fscache = fscache_acquire_cookie(
135 server->nfs_client->fscache,
136 &nfs_cache_fh_index_def,
138 fscache_set_i_size(nfsi->fscache, nfsi->vfs_inode.i_size);
141 "NFS: revalidation new cookie (0x%p/0x%p/0x%p/0x%p)\n",
142 server, nfsi, old, nfsi->fscache);
147 * release a per-filehandle cookie
149 static inline void nfs_fscache_release_fh_cookie(struct nfs_server *server,
150 struct nfs_inode *nfsi)
152 dfprintk(FSCACHE, "NFS: clear cookie (0x%p/0x%p)\n",
153 nfsi, nfsi->fscache);
155 fscache_relinquish_cookie(nfsi->fscache, 0);
156 nfsi->fscache = NULL;
160 * retire a per-filehandle cookie, destroying the data attached to it
162 static inline void nfs_fscache_zap_fh_cookie(struct nfs_server *server,
163 struct nfs_inode *nfsi)
165 dfprintk(FSCACHE,"NFS: zapping cookie (0x%p/0x%p)\n",
166 nfsi, nfsi->fscache);
168 fscache_relinquish_cookie(nfsi->fscache, 1);
169 nfsi->fscache = NULL;
173 * turn off the cache with regard to a filehandle cookie if opened for writing,
174 * invalidating all the pages in the page cache relating to the associated
175 * inode to clear the per-page caching
177 static inline void nfs_fscache_disable_fh_cookie(struct inode *inode)
179 if (NFS_I(inode)->fscache) {
181 "NFS: nfsi 0x%p turning cache off\n", NFS_I(inode));
183 /* Need to invalided any mapped pages that were read in before
184 * turning off the cache.
186 if (inode->i_mapping && inode->i_mapping->nrpages)
187 invalidate_inode_pages2(inode->i_mapping);
189 nfs_fscache_zap_fh_cookie(NFS_SERVER(inode), NFS_I(inode));
194 * install the VM ops for mmap() of an NFS file so that we can hold up writes
195 * to pages on shared writable mappings until the store to the cache is
198 static inline void nfs_fscache_install_vm_ops(struct inode *inode,
199 struct vm_area_struct *vma)
201 if (NFS_I(inode)->fscache)
202 vma->vm_ops = &nfs_fs_vm_operations;
206 * release the caching state associated with a page
208 static void nfs_fscache_release_page(struct page *page)
210 if (PageNfsCached(page)) {
211 struct nfs_inode *nfsi = NFS_I(page->mapping->host);
213 BUG_ON(nfsi->fscache == NULL);
215 dfprintk(FSCACHE, "NFS: fscache releasepage (0x%p/0x%p/0x%p)\n",
216 nfsi->fscache, page, nfsi);
218 wait_on_page_fs_misc(page);
219 fscache_uncache_page(nfsi->fscache, page);
220 atomic_inc(&nfs_fscache_uncache_page);
221 ClearPageNfsCached(page);
226 * release the caching state associated with a page if undergoing complete page
229 static inline void nfs_fscache_invalidate_page(struct page *page,
231 unsigned long offset)
233 if (PageNfsCached(page)) {
234 struct nfs_inode *nfsi = NFS_I(page->mapping->host);
236 BUG_ON(!nfsi->fscache);
239 "NFS: fscache invalidatepage (0x%p/0x%p/0x%p)\n",
240 nfsi->fscache, page, nfsi);
243 BUG_ON(!PageLocked(page));
244 if (!PageWriteback(page))
245 nfs_fscache_release_page(page);
251 * store a newly fetched page in fscache
253 extern void nfs_readpage_to_fscache_complete(struct page *, void *, int);
255 static inline void nfs_readpage_to_fscache(struct inode *inode,
261 if (PageNfsCached(page)) {
264 "readpage_to_fscache(fsc:%p/p:%p(i:%lx f:%lx)/%d)\n",
265 NFS_I(inode)->fscache, page, page->index, page->flags,
268 if (TestSetPageFsMisc(page))
271 ret = fscache_write_page(NFS_I(inode)->fscache, page,
272 nfs_readpage_to_fscache_complete,
276 "readpage_to_fscache: p:%p(i:%lu f:%lx) ret %d\n",
277 page, page->index, page->flags, ret);
280 fscache_uncache_page(NFS_I(inode)->fscache, page);
281 atomic_inc(&nfs_fscache_uncache_page);
282 ClearPageNfsCached(page);
283 end_page_fs_misc(page);
284 nfs_fscache_to_error = ret;
286 atomic_inc(&nfs_fscache_to_pages);
292 * retrieve a page from fscache
294 extern void nfs_readpage_from_fscache_complete(struct page *, void *, int);
297 int nfs_readpage_from_fscache(struct nfs_open_context *ctx,
303 if (!NFS_I(inode)->fscache)
307 "NFS: readpage_from_fscache(fsc:%p/p:%p(i:%lx f:%lx)/0x%p)\n",
308 NFS_I(inode)->fscache, page, page->index, page->flags, inode);
310 ret = fscache_read_or_alloc_page(NFS_I(inode)->fscache,
312 nfs_readpage_from_fscache_complete,
317 case 0: /* read BIO submitted (page in fscache) */
319 "NFS: readpage_from_fscache: BIO submitted\n");
320 atomic_inc(&nfs_fscache_from_pages);
323 case -ENOBUFS: /* inode not in cache */
324 case -ENODATA: /* page not in cache */
326 "NFS: readpage_from_fscache error %d\n", ret);
330 dfprintk(FSCACHE, "NFS: readpage_from_fscache %d\n", ret);
331 nfs_fscache_from_error = ret;
337 * retrieve a set of pages from fscache
339 static inline int nfs_readpages_from_fscache(struct nfs_open_context *ctx,
341 struct address_space *mapping,
342 struct list_head *pages,
345 int ret, npages = *nr_pages;
347 if (!NFS_I(inode)->fscache)
351 "NFS: nfs_getpages_from_fscache (0x%p/%u/0x%p)\n",
352 NFS_I(inode)->fscache, *nr_pages, inode);
354 ret = fscache_read_or_alloc_pages(NFS_I(inode)->fscache,
355 mapping, pages, nr_pages,
356 nfs_readpage_from_fscache_complete,
358 mapping_gfp_mask(mapping));
362 case 0: /* read BIO submitted (page in fscache) */
363 BUG_ON(!list_empty(pages));
364 BUG_ON(*nr_pages != 0);
366 "NFS: nfs_getpages_from_fscache: BIO submitted\n");
368 atomic_add(npages, &nfs_fscache_from_pages);
371 case -ENOBUFS: /* inode not in cache */
372 case -ENODATA: /* page not in cache */
374 "NFS: nfs_getpages_from_fscache: no page: %d\n", ret);
379 "NFS: nfs_getpages_from_fscache: ret %d\n", ret);
380 nfs_fscache_from_error = ret;
387 * store an updated page in fscache
389 extern void nfs_writepage_to_fscache_complete(struct page *page, void *data, int error);
391 static inline void nfs_writepage_to_fscache(struct inode *inode,
396 if (PageNfsCached(page) && NFS_I(inode)->fscache) {
398 "NFS: writepage_to_fscache (0x%p/0x%p/0x%p)\n",
399 NFS_I(inode)->fscache, page, inode);
401 error = fscache_write_page(NFS_I(inode)->fscache, page,
402 nfs_writepage_to_fscache_complete,
406 "NFS: fscache_write_page error %d\n",
408 fscache_uncache_page(NFS_I(inode)->fscache, page);
413 #else /* CONFIG_NFS_FSCACHE */
414 static inline int nfs_fscache_register(void) { return 0; }
415 static inline void nfs_fscache_unregister(void) {}
416 static inline void nfs_fscache_get_client_cookie(struct nfs_client *clp) {}
417 static inline void nfs4_fscache_get_client_cookie(struct nfs_client *clp) {}
418 static inline void nfs_fscache_release_client_cookie(struct nfs_client *clp) {}
419 static inline const char *nfs_server_fscache_state(struct nfs_server *server) { return "no "; }
421 static inline void nfs_fscache_get_fh_cookie(struct super_block *sb,
422 struct nfs_inode *nfsi,
426 static inline void nfs_fscache_set_size(struct nfs_server *server,
427 struct nfs_inode *nfsi,
431 static inline void nfs_fscache_release_fh_cookie(struct nfs_server *server,
432 struct nfs_inode *nfsi)
435 static inline void nfs_fscache_zap_fh_cookie(struct nfs_server *server, struct nfs_inode *nfsi) {}
436 static inline void nfs_fscache_renew_fh_cookie(struct nfs_server *server, struct nfs_inode *nfsi) {}
437 static inline void nfs_fscache_disable_fh_cookie(struct inode *inode) {}
438 static inline void nfs_fscache_install_vm_ops(struct inode *inode, struct vm_area_struct *vma) {}
439 static inline void nfs_fscache_release_page(struct page *page) {}
440 static inline void nfs_fscache_invalidate_page(struct page *page,
442 unsigned long offset)
445 static inline void nfs_readpage_to_fscache(struct inode *inode, struct page *page, int sync) {}
446 static inline int nfs_readpage_from_fscache(struct nfs_open_context *ctx,
447 struct inode *inode, struct page *page)
451 static inline int nfs_readpages_from_fscache(struct nfs_open_context *ctx,
453 struct address_space *mapping,
454 struct list_head *pages,
460 static inline void nfs_writepage_to_fscache(struct inode *inode, struct page *page)
462 BUG_ON(PageNfsCached(page));
465 #endif /* CONFIG_NFS_FSCACHE */
466 #endif /* _NFS_FSCACHE_H */