This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / fs / nfs / fscache.h
1 /* fscache.h: NFS filesystem cache interface definitions
2  *
3  * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
4  * Written by David Howells (dhowells@redhat.com)
5  *
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.
10  */
11
12 #ifndef _NFS_FSCACHE_H
13 #define _NFS_FSCACHE_H
14
15 #include <linux/nfs_fs.h>
16 #include <linux/nfs_mount.h>
17 #include <linux/nfs4_mount.h>
18
19 #ifdef CONFIG_NFS_FSCACHE
20 #include <linux/fscache.h>
21
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;
26
27 extern void nfs_invalidatepage(struct page *, unsigned long);
28 extern int nfs_releasepage(struct page *, gfp_t);
29
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;
35
36 /*
37  * register NFS for caching
38  */
39 static inline int nfs_fscache_register(void)
40 {
41         return fscache_register_netfs(&nfs_cache_netfs);
42 }
43
44 /*
45  * unregister NFS for caching
46  */
47 static inline void nfs_fscache_unregister(void)
48 {
49         fscache_unregister_netfs(&nfs_cache_netfs);
50 }
51
52 /*
53  * get the per-client index cookie for an NFS client if the appropriate mount
54  * flag was set
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
57  */
58 static inline void nfs_fscache_get_client_cookie(struct nfs_client *clp)
59 {
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,
63                                               clp);
64         dfprintk(FSCACHE,"NFS: get client cookie (0x%p/0x%p)\n",
65                  clp, clp->fscache);
66 }
67
68 /*
69  * dispose of a per-client cookie
70  */
71 static inline void nfs_fscache_release_client_cookie(struct nfs_client *clp)
72 {
73         dfprintk(FSCACHE,"NFS: releasing client cookie (0x%p/0x%p)\n",
74                 clp, clp->fscache);
75
76         fscache_relinquish_cookie(clp->fscache, 0);
77         clp->fscache = NULL;
78 }
79
80 /*
81  * indicate the client caching state as readable text
82  */
83 static inline const char *nfs_server_fscache_state(struct nfs_server *server)
84 {
85         if (server->nfs_client->fscache && (server->flags & NFS_MOUNT_FSCACHE))
86                 return "yes";
87         return "no ";
88 }
89
90 /*
91  * get the per-filehandle cookie for an NFS inode
92  */
93 static inline void nfs_fscache_get_fh_cookie(struct super_block *sb,
94                                              struct nfs_inode *nfsi,
95                                              int maycache)
96 {
97         nfsi->fscache = NULL;
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,
102                         nfsi);
103
104                 fscache_set_i_size(nfsi->fscache, nfsi->vfs_inode.i_size);
105
106                 dfprintk(FSCACHE, "NFS: get FH cookie (0x%p/0x%p/0x%p)\n",
107                          sb, nfsi, nfsi->fscache);
108         }
109 }
110
111 /*
112  * change the filesize associated with a per-filehandle cookie
113  */
114 static inline void nfs_fscache_set_size(struct nfs_server *server,
115                                         struct nfs_inode *nfsi,
116                                         loff_t i_size)
117 {
118         fscache_set_i_size(nfsi->fscache, i_size);
119 }
120
121 /*
122  * replace a per-filehandle cookie due to revalidation detecting a file having
123  * changed on the server
124  */
125 static inline void nfs_fscache_renew_fh_cookie(struct nfs_server *server,
126                                                struct nfs_inode *nfsi)
127 {
128         struct fscache_cookie *old = nfsi->fscache;
129
130         if (nfsi->fscache) {
131                 /* retire the current fscache cache and get a new one */
132                 fscache_relinquish_cookie(nfsi->fscache, 1);
133
134                 nfsi->fscache = fscache_acquire_cookie(
135                         server->nfs_client->fscache,
136                         &nfs_cache_fh_index_def,
137                         nfsi);
138                 fscache_set_i_size(nfsi->fscache, nfsi->vfs_inode.i_size);
139
140                 dfprintk(FSCACHE,
141                          "NFS: revalidation new cookie (0x%p/0x%p/0x%p/0x%p)\n",
142                          server, nfsi, old, nfsi->fscache);
143         }
144 }
145
146 /*
147  * release a per-filehandle cookie
148  */
149 static inline void nfs_fscache_release_fh_cookie(struct nfs_server *server,
150                                                  struct nfs_inode *nfsi)
151 {
152         dfprintk(FSCACHE, "NFS: clear cookie (0x%p/0x%p)\n",
153                  nfsi, nfsi->fscache);
154
155         fscache_relinquish_cookie(nfsi->fscache, 0);
156         nfsi->fscache = NULL;
157 }
158
159 /*
160  * retire a per-filehandle cookie, destroying the data attached to it
161  */
162 static inline void nfs_fscache_zap_fh_cookie(struct nfs_server *server,
163                                              struct nfs_inode *nfsi)
164 {
165         dfprintk(FSCACHE,"NFS: zapping cookie (0x%p/0x%p)\n",
166                 nfsi, nfsi->fscache);
167
168         fscache_relinquish_cookie(nfsi->fscache, 1);
169         nfsi->fscache = NULL;
170 }
171
172 /*
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
176  */
177 static inline void nfs_fscache_disable_fh_cookie(struct inode *inode)
178 {
179         if (NFS_I(inode)->fscache) {
180                 dfprintk(FSCACHE,
181                          "NFS: nfsi 0x%p turning cache off\n", NFS_I(inode));
182
183                 /* Need to invalided any mapped pages that were read in before
184                  * turning off the cache.
185                  */
186                 if (inode->i_mapping && inode->i_mapping->nrpages)
187                         invalidate_inode_pages2(inode->i_mapping);
188
189                 nfs_fscache_zap_fh_cookie(NFS_SERVER(inode), NFS_I(inode));
190         }
191 }
192
193 /*
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
196  * complete
197  */
198 static inline void nfs_fscache_install_vm_ops(struct inode *inode,
199                                               struct vm_area_struct *vma)
200 {
201         if (NFS_I(inode)->fscache)
202                 vma->vm_ops = &nfs_fs_vm_operations;
203 }
204
205 /*
206  * release the caching state associated with a page
207  */
208 static void nfs_fscache_release_page(struct page *page)
209 {
210         if (PageNfsCached(page)) {
211                 struct nfs_inode *nfsi = NFS_I(page->mapping->host);
212
213                 BUG_ON(nfsi->fscache == NULL);
214
215                 dfprintk(FSCACHE, "NFS: fscache releasepage (0x%p/0x%p/0x%p)\n",
216                          nfsi->fscache, page, nfsi);
217
218                 wait_on_page_fs_misc(page);
219                 fscache_uncache_page(nfsi->fscache, page);
220                 atomic_inc(&nfs_fscache_uncache_page);
221                 ClearPageNfsCached(page);
222         }
223 }
224
225 /*
226  * release the caching state associated with a page if undergoing complete page
227  * invalidation
228  */
229 static inline void nfs_fscache_invalidate_page(struct page *page,
230                                                struct inode *inode,
231                                                unsigned long offset)
232 {
233         if (PageNfsCached(page)) {
234                 struct nfs_inode *nfsi = NFS_I(page->mapping->host);
235
236                 BUG_ON(!nfsi->fscache);
237
238                 dfprintk(FSCACHE,
239                          "NFS: fscache invalidatepage (0x%p/0x%p/0x%p)\n",
240                          nfsi->fscache, page, nfsi);
241
242                 if (offset == 0) {
243                         BUG_ON(!PageLocked(page));
244                         if (!PageWriteback(page))
245                                 nfs_fscache_release_page(page);
246                 }
247         }
248 }
249
250 /*
251  * store a newly fetched page in fscache
252  */
253 extern void nfs_readpage_to_fscache_complete(struct page *, void *, int);
254
255 static inline void nfs_readpage_to_fscache(struct inode *inode,
256                                            struct page *page,
257                                            int sync)
258 {
259         int ret;
260
261         if (PageNfsCached(page)) {
262                 dfprintk(FSCACHE,
263                          "NFS: "
264                          "readpage_to_fscache(fsc:%p/p:%p(i:%lx f:%lx)/%d)\n",
265                          NFS_I(inode)->fscache, page, page->index, page->flags,
266                          sync);
267
268                 if (TestSetPageFsMisc(page))
269                         BUG();
270
271                 ret = fscache_write_page(NFS_I(inode)->fscache, page,
272                                          nfs_readpage_to_fscache_complete,
273                                          NULL, GFP_KERNEL);
274                 dfprintk(FSCACHE,
275                          "NFS:     "
276                          "readpage_to_fscache: p:%p(i:%lu f:%lx) ret %d\n",
277                          page, page->index, page->flags, ret);
278
279                 if (ret != 0) {
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;
285                 } else {
286                         atomic_inc(&nfs_fscache_to_pages);
287                 }
288         }
289 }
290
291 /*
292  * retrieve a page from fscache
293  */
294 extern void nfs_readpage_from_fscache_complete(struct page *, void *, int);
295
296 static inline
297 int nfs_readpage_from_fscache(struct nfs_open_context *ctx,
298                               struct inode *inode,
299                               struct page *page)
300 {
301         int ret;
302
303         if (!NFS_I(inode)->fscache)
304                 return 1;
305
306         dfprintk(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);
309
310         ret = fscache_read_or_alloc_page(NFS_I(inode)->fscache,
311                                          page,
312                                          nfs_readpage_from_fscache_complete,
313                                          ctx,
314                                          GFP_KERNEL);
315
316         switch (ret) {
317         case 0: /* read BIO submitted (page in fscache) */
318                 dfprintk(FSCACHE,
319                          "NFS:    readpage_from_fscache: BIO submitted\n");
320                 atomic_inc(&nfs_fscache_from_pages);
321                 return ret;
322
323         case -ENOBUFS: /* inode not in cache */
324         case -ENODATA: /* page not in cache */
325                 dfprintk(FSCACHE,
326                          "NFS:    readpage_from_fscache error %d\n", ret);
327                 return 1;
328
329         default:
330                 dfprintk(FSCACHE, "NFS:    readpage_from_fscache %d\n", ret);
331                 nfs_fscache_from_error = ret;
332         }
333         return ret;
334 }
335
336 /*
337  * retrieve a set of pages from fscache
338  */
339 static inline int nfs_readpages_from_fscache(struct nfs_open_context *ctx,
340                                              struct inode *inode,
341                                              struct address_space *mapping,
342                                              struct list_head *pages,
343                                              unsigned *nr_pages)
344 {
345         int ret, npages = *nr_pages;
346
347         if (!NFS_I(inode)->fscache)
348                 return 1;
349
350         dfprintk(FSCACHE,
351                  "NFS: nfs_getpages_from_fscache (0x%p/%u/0x%p)\n",
352                  NFS_I(inode)->fscache, *nr_pages, inode);
353
354         ret = fscache_read_or_alloc_pages(NFS_I(inode)->fscache,
355                                           mapping, pages, nr_pages,
356                                           nfs_readpage_from_fscache_complete,
357                                           ctx,
358                                           mapping_gfp_mask(mapping));
359
360
361         switch (ret) {
362         case 0: /* read BIO submitted (page in fscache) */
363                 BUG_ON(!list_empty(pages));
364                 BUG_ON(*nr_pages != 0);
365                 dfprintk(FSCACHE,
366                          "NFS: nfs_getpages_from_fscache: BIO submitted\n");
367
368                 atomic_add(npages, &nfs_fscache_from_pages);
369                 return ret;
370
371         case -ENOBUFS: /* inode not in cache */
372         case -ENODATA: /* page not in cache */
373                 dfprintk(FSCACHE,
374                          "NFS: nfs_getpages_from_fscache: no page: %d\n", ret);
375                 return 1;
376
377         default:
378                 dfprintk(FSCACHE,
379                          "NFS: nfs_getpages_from_fscache: ret  %d\n", ret);
380                 nfs_fscache_from_error = ret;
381         }
382
383         return ret;
384 }
385
386 /*
387  * store an updated page in fscache
388  */
389 extern void nfs_writepage_to_fscache_complete(struct page *page, void *data, int error);
390
391 static inline void nfs_writepage_to_fscache(struct inode *inode,
392                                             struct page *page)
393 {
394         int error;
395
396         if (PageNfsCached(page) && NFS_I(inode)->fscache) {
397                 dfprintk(FSCACHE,
398                          "NFS: writepage_to_fscache (0x%p/0x%p/0x%p)\n",
399                          NFS_I(inode)->fscache, page, inode);
400
401                 error = fscache_write_page(NFS_I(inode)->fscache, page,
402                                            nfs_writepage_to_fscache_complete,
403                                            NULL, GFP_KERNEL);
404                 if (error != 0) {
405                         dfprintk(FSCACHE,
406                                  "NFS:    fscache_write_page error %d\n",
407                                  error);
408                         fscache_uncache_page(NFS_I(inode)->fscache, page);
409                 }
410         }
411 }
412
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 "; }
420
421 static inline void nfs_fscache_get_fh_cookie(struct super_block *sb,
422                                              struct nfs_inode *nfsi,
423                                              int maycache)
424 {
425 }
426 static inline void nfs_fscache_set_size(struct nfs_server *server,
427                                         struct nfs_inode *nfsi,
428                                         loff_t i_size)
429 {
430 }
431 static inline void nfs_fscache_release_fh_cookie(struct nfs_server *server,
432                                                  struct nfs_inode *nfsi)
433 {
434 }
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,
441                                                struct inode *inode,
442                                                unsigned long offset)
443 {
444 }
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)
448 {
449         return -ENOBUFS;
450 }
451 static inline int nfs_readpages_from_fscache(struct nfs_open_context *ctx,
452                                              struct inode *inode,
453                                              struct address_space *mapping,
454                                              struct list_head *pages,
455                                              unsigned *nr_pages)
456 {
457         return -ENOBUFS;
458 }
459
460 static inline void nfs_writepage_to_fscache(struct inode *inode, struct page *page)
461 {
462         BUG_ON(PageNfsCached(page));
463 }
464
465 #endif /* CONFIG_NFS_FSCACHE */
466 #endif /* _NFS_FSCACHE_H */