aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2009-04-03 11:42:44 -0400
committerDavid Howells <dhowells@redhat.com>2009-04-03 11:42:44 -0400
commit9a9fc1c03315f1606596e55b4096d39e2079a041 (patch)
tree0eb9a2d9844a821e515baeb59e6d5e38384d5915 /fs/nfs
parentf42b293d6d5259043a8944b556eeab427c695d57 (diff)
NFS: Read pages from FS-Cache into an NFS inode
Read pages from an FS-Cache data storage object representing an inode into an NFS inode. 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')
-rw-r--r--fs/nfs/fscache.c112
-rw-r--r--fs/nfs/fscache.h47
-rw-r--r--fs/nfs/read.c18
3 files changed, 177 insertions, 0 deletions
diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
index f673d35d8b89..3a3056657858 100644
--- a/fs/nfs/fscache.c
+++ b/fs/nfs/fscache.c
@@ -381,3 +381,115 @@ void __nfs_fscache_invalidate_page(struct page *page, struct inode *inode)
381 nfs_add_fscache_stats(page->mapping->host, 381 nfs_add_fscache_stats(page->mapping->host,
382 NFSIOS_FSCACHE_PAGES_UNCACHED, 1); 382 NFSIOS_FSCACHE_PAGES_UNCACHED, 1);
383} 383}
384
385/*
386 * Handle completion of a page being read from the cache.
387 * - Called in process (keventd) context.
388 */
389static void nfs_readpage_from_fscache_complete(struct page *page,
390 void *context,
391 int error)
392{
393 dfprintk(FSCACHE,
394 "NFS: readpage_from_fscache_complete (0x%p/0x%p/%d)\n",
395 page, context, error);
396
397 /* if the read completes with an error, we just unlock the page and let
398 * the VM reissue the readpage */
399 if (!error) {
400 SetPageUptodate(page);
401 unlock_page(page);
402 } else {
403 error = nfs_readpage_async(context, page->mapping->host, page);
404 if (error)
405 unlock_page(page);
406 }
407}
408
409/*
410 * Retrieve a page from fscache
411 */
412int __nfs_readpage_from_fscache(struct nfs_open_context *ctx,
413 struct inode *inode, struct page *page)
414{
415 int ret;
416
417 dfprintk(FSCACHE,
418 "NFS: readpage_from_fscache(fsc:%p/p:%p(i:%lx f:%lx)/0x%p)\n",
419 NFS_I(inode)->fscache, page, page->index, page->flags, inode);
420
421 ret = fscache_read_or_alloc_page(NFS_I(inode)->fscache,
422 page,
423 nfs_readpage_from_fscache_complete,
424 ctx,
425 GFP_KERNEL);
426
427 switch (ret) {
428 case 0: /* read BIO submitted (page in fscache) */
429 dfprintk(FSCACHE,
430 "NFS: readpage_from_fscache: BIO submitted\n");
431 nfs_add_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_READ_OK, 1);
432 return ret;
433
434 case -ENOBUFS: /* inode not in cache */
435 case -ENODATA: /* page not in cache */
436 nfs_add_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_READ_FAIL, 1);
437 dfprintk(FSCACHE,
438 "NFS: readpage_from_fscache %d\n", ret);
439 return 1;
440
441 default:
442 dfprintk(FSCACHE, "NFS: readpage_from_fscache %d\n", ret);
443 nfs_add_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_READ_FAIL, 1);
444 }
445 return ret;
446}
447
448/*
449 * Retrieve a set of pages from fscache
450 */
451int __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 int ret, npages = *nr_pages;
458
459 dfprintk(FSCACHE, "NFS: nfs_getpages_from_fscache (0x%p/%u/0x%p)\n",
460 NFS_I(inode)->fscache, npages, inode);
461
462 ret = fscache_read_or_alloc_pages(NFS_I(inode)->fscache,
463 mapping, pages, nr_pages,
464 nfs_readpage_from_fscache_complete,
465 ctx,
466 mapping_gfp_mask(mapping));
467 if (*nr_pages < npages)
468 nfs_add_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_READ_OK,
469 npages);
470 if (*nr_pages > 0)
471 nfs_add_fscache_stats(inode, NFSIOS_FSCACHE_PAGES_READ_FAIL,
472 *nr_pages);
473
474 switch (ret) {
475 case 0: /* read submitted to the cache for all pages */
476 BUG_ON(!list_empty(pages));
477 BUG_ON(*nr_pages != 0);
478 dfprintk(FSCACHE,
479 "NFS: nfs_getpages_from_fscache: submitted\n");
480
481 return ret;
482
483 case -ENOBUFS: /* some pages aren't cached and can't be */
484 case -ENODATA: /* some pages aren't cached */
485 dfprintk(FSCACHE,
486 "NFS: nfs_getpages_from_fscache: no page: %d\n", ret);
487 return 1;
488
489 default:
490 dfprintk(FSCACHE,
491 "NFS: nfs_getpages_from_fscache: ret %d\n", ret);
492 }
493
494 return ret;
495}
diff --git a/fs/nfs/fscache.h b/fs/nfs/fscache.h
index e29613a8cbd2..099349c171ca 100644
--- a/fs/nfs/fscache.h
+++ b/fs/nfs/fscache.h
@@ -86,6 +86,12 @@ extern void nfs_fscache_reset_inode_cookie(struct inode *);
86extern void __nfs_fscache_invalidate_page(struct page *, struct inode *); 86extern void __nfs_fscache_invalidate_page(struct page *, struct inode *);
87extern int nfs_fscache_release_page(struct page *, gfp_t); 87extern int nfs_fscache_release_page(struct page *, gfp_t);
88 88
89extern int __nfs_readpage_from_fscache(struct nfs_open_context *,
90 struct inode *, struct page *);
91extern int __nfs_readpages_from_fscache(struct nfs_open_context *,
92 struct inode *, struct address_space *,
93 struct list_head *, unsigned *);
94
89/* 95/*
90 * wait for a page to complete writing to the cache 96 * wait for a page to complete writing to the cache
91 */ 97 */
@@ -107,6 +113,32 @@ static inline void nfs_fscache_invalidate_page(struct page *page,
107 __nfs_fscache_invalidate_page(page, inode); 113 __nfs_fscache_invalidate_page(page, inode);
108} 114}
109 115
116/*
117 * Retrieve a page from an inode data storage object.
118 */
119static inline int nfs_readpage_from_fscache(struct nfs_open_context *ctx,
120 struct inode *inode,
121 struct page *page)
122{
123 if (NFS_I(inode)->fscache)
124 return __nfs_readpage_from_fscache(ctx, inode, page);
125 return -ENOBUFS;
126}
127
128/*
129 * Retrieve a set of pages from an inode data storage object.
130 */
131static inline int nfs_readpages_from_fscache(struct nfs_open_context *ctx,
132 struct inode *inode,
133 struct address_space *mapping,
134 struct list_head *pages,
135 unsigned *nr_pages)
136{
137 if (NFS_I(inode)->fscache)
138 return __nfs_readpages_from_fscache(ctx, inode, mapping, pages,
139 nr_pages);
140 return -ENOBUFS;
141}
110 142
111#else /* CONFIG_NFS_FSCACHE */ 143#else /* CONFIG_NFS_FSCACHE */
112static inline int nfs_fscache_register(void) { return 0; } 144static inline int nfs_fscache_register(void) { return 0; }
@@ -138,5 +170,20 @@ static inline void nfs_fscache_invalidate_page(struct page *page,
138static inline void nfs_fscache_wait_on_page_write(struct nfs_inode *nfsi, 170static inline void nfs_fscache_wait_on_page_write(struct nfs_inode *nfsi,
139 struct page *page) {} 171 struct page *page) {}
140 172
173static inline int nfs_readpage_from_fscache(struct nfs_open_context *ctx,
174 struct inode *inode,
175 struct page *page)
176{
177 return -ENOBUFS;
178}
179static inline int nfs_readpages_from_fscache(struct nfs_open_context *ctx,
180 struct inode *inode,
181 struct address_space *mapping,
182 struct list_head *pages,
183 unsigned *nr_pages)
184{
185 return -ENOBUFS;
186}
187
141#endif /* CONFIG_NFS_FSCACHE */ 188#endif /* CONFIG_NFS_FSCACHE */
142#endif /* _NFS_FSCACHE_H */ 189#endif /* _NFS_FSCACHE_H */
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 98b74009c9d7..e18ba792872f 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -24,6 +24,7 @@
24 24
25#include "internal.h" 25#include "internal.h"
26#include "iostat.h" 26#include "iostat.h"
27#include "fscache.h"
27 28
28#define NFSDBG_FACILITY NFSDBG_PAGECACHE 29#define NFSDBG_FACILITY NFSDBG_PAGECACHE
29 30
@@ -510,8 +511,15 @@ int nfs_readpage(struct file *file, struct page *page)
510 } else 511 } else
511 ctx = get_nfs_open_context(nfs_file_open_context(file)); 512 ctx = get_nfs_open_context(nfs_file_open_context(file));
512 513
514 if (!IS_SYNC(inode)) {
515 error = nfs_readpage_from_fscache(ctx, inode, page);
516 if (error == 0)
517 goto out;
518 }
519
513 error = nfs_readpage_async(ctx, inode, page); 520 error = nfs_readpage_async(ctx, inode, page);
514 521
522out:
515 put_nfs_open_context(ctx); 523 put_nfs_open_context(ctx);
516 return error; 524 return error;
517out_unlock: 525out_unlock:
@@ -584,6 +592,15 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
584 return -EBADF; 592 return -EBADF;
585 } else 593 } else
586 desc.ctx = get_nfs_open_context(nfs_file_open_context(filp)); 594 desc.ctx = get_nfs_open_context(nfs_file_open_context(filp));
595
596 /* attempt to read as many of the pages as possible from the cache
597 * - this returns -ENOBUFS immediately if the cookie is negative
598 */
599 ret = nfs_readpages_from_fscache(desc.ctx, inode, mapping,
600 pages, &nr_pages);
601 if (ret == 0)
602 goto read_complete; /* all pages were read */
603
587 if (rsize < PAGE_CACHE_SIZE) 604 if (rsize < PAGE_CACHE_SIZE)
588 nfs_pageio_init(&pgio, inode, nfs_pagein_multi, rsize, 0); 605 nfs_pageio_init(&pgio, inode, nfs_pagein_multi, rsize, 0);
589 else 606 else
@@ -594,6 +611,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
594 nfs_pageio_complete(&pgio); 611 nfs_pageio_complete(&pgio);
595 npages = (pgio.pg_bytes_written + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; 612 npages = (pgio.pg_bytes_written + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
596 nfs_add_stats(inode, NFSIOS_READPAGES, npages); 613 nfs_add_stats(inode, NFSIOS_READPAGES, npages);
614read_complete:
597 put_nfs_open_context(desc.ctx); 615 put_nfs_open_context(desc.ctx);
598out: 616out:
599 return ret; 617 return ret;