[PATCH 34/37] NFS: Read pages from FS-Cache into an NFS inode

2008-02-20 Thread David Howells
Read pages from an FS-Cache data storage object representing an inode into an
NFS inode.

Signed-off-by: David Howells [EMAIL PROTECTED]
---

 fs/nfs/fscache.c |  112 ++
 fs/nfs/fscache.h |   47 +++
 fs/nfs/read.c|   18 +
 3 files changed, 176 insertions(+), 1 deletions(-)


diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
index d475ff5..438cc9b 100644
--- a/fs/nfs/fscache.c
+++ b/fs/nfs/fscache.c
@@ -344,5 +344,115 @@ void __nfs_fscache_invalidate_page(struct page *page, 
struct inode *inode)
 
BUG_ON(!PageLocked(page));
fscache_uncache_page(nfsi-fscache, page);
-   nfs_add_stats(page-mapping-host, NFSIOS_FSCACHE_UNCACHE, 1);
+   nfs_add_stats(inode, NFSIOS_FSCACHE_UNCACHE, 1);
+}
+
+/*
+ * Handle completion of a page being read from the cache.
+ * - Called in process (keventd) context.
+ */
+static void nfs_readpage_from_fscache_complete(struct page *page,
+  void *context,
+  int error)
+{
+   dfprintk(FSCACHE,
+NFS: readpage_from_fscache_complete (0x%p/0x%p/%d)\n,
+page, context, error);
+
+   /* if the read completes with an error, we just unlock the page and let
+* the VM reissue the readpage */
+   if (!error) {
+   SetPageUptodate(page);
+   unlock_page(page);
+   } else {
+   error = nfs_readpage_async(context, page-mapping-host, page);
+   if (error)
+   unlock_page(page);
+   }
+}
+
+/*
+ * Retrieve a page from fscache
+ */
+int __nfs_readpage_from_fscache(struct nfs_open_context *ctx,
+   struct inode *inode, struct page *page)
+{
+   int ret;
+
+   dfprintk(FSCACHE,
+NFS: readpage_from_fscache(fsc:%p/p:%p(i:%lx f:%lx)/0x%p)\n,
+NFS_I(inode)-fscache, page, page-index, page-flags, inode);
+
+   ret = fscache_read_or_alloc_page(NFS_I(inode)-fscache,
+page,
+nfs_readpage_from_fscache_complete,
+ctx,
+GFP_KERNEL);
+
+   switch (ret) {
+   case 0: /* read BIO submitted (page in fscache) */
+   dfprintk(FSCACHE,
+NFS:readpage_from_fscache: BIO submitted\n);
+   nfs_add_stats(inode, NFSIOS_FSCACHE_READ_OK, 1);
+   return ret;
+
+   case -ENOBUFS: /* inode not in cache */
+   case -ENODATA: /* page not in cache */
+   nfs_add_stats(inode, NFSIOS_FSCACHE_READ_FAIL, 1);
+   dfprintk(FSCACHE,
+NFS:readpage_from_fscache %d\n, ret);
+   return 1;
+
+   default:
+   dfprintk(FSCACHE, NFS:readpage_from_fscache %d\n, ret);
+   nfs_add_stats(inode, NFSIOS_FSCACHE_READ_FAIL, 1);
+   }
+   return ret;
+}
+
+/*
+ * Retrieve a set of pages from fscache
+ */
+int __nfs_readpages_from_fscache(struct nfs_open_context *ctx,
+struct inode *inode,
+struct address_space *mapping,
+struct list_head *pages,
+unsigned *nr_pages)
+{
+   int ret, npages = *nr_pages;
+
+   dfprintk(FSCACHE, NFS: nfs_getpages_from_fscache (0x%p/%u/0x%p)\n,
+NFS_I(inode)-fscache, npages, inode);
+
+   ret = fscache_read_or_alloc_pages(NFS_I(inode)-fscache,
+ mapping, pages, nr_pages,
+ nfs_readpage_from_fscache_complete,
+ ctx,
+ mapping_gfp_mask(mapping));
+   if (*nr_pages  npages)
+   nfs_add_stats(inode, NFSIOS_FSCACHE_READ_OK, npages);
+   if (*nr_pages  0)
+   nfs_add_stats(inode, NFSIOS_FSCACHE_READ_FAIL, *nr_pages);
+
+   switch (ret) {
+   case 0: /* read submitted to the cache for all pages */
+   BUG_ON(!list_empty(pages));
+   BUG_ON(*nr_pages != 0);
+   dfprintk(FSCACHE,
+NFS: nfs_getpages_from_fscache: submitted\n);
+
+   return ret;
+
+   case -ENOBUFS: /* some pages aren't cached and can't be */
+   case -ENODATA: /* some pages aren't cached */
+   dfprintk(FSCACHE,
+NFS: nfs_getpages_from_fscache: no page: %d\n, ret);
+   return 1;
+
+   default:
+   dfprintk(FSCACHE,
+NFS: nfs_getpages_from_fscache: ret  %d\n, ret);
+   }
+
+   return ret;
 }
diff --git a/fs/nfs/fscache.h b/fs/nfs/fscache.h
index 1cb7d96..4c1e1a8 100644
--- a/fs/nfs/fscache.h
+++ b/fs/nfs/fscache.h
@@ -89,6 +89,12 

[PATCH 34/37] NFS: Read pages from FS-Cache into an NFS inode

2008-02-08 Thread David Howells
Read pages from an FS-Cache data storage object representing an inode into an
NFS inode.

Signed-off-by: David Howells [EMAIL PROTECTED]
---

 fs/nfs/fscache.c |  112 ++
 fs/nfs/fscache.h |   47 +++
 fs/nfs/read.c|   18 +
 3 files changed, 176 insertions(+), 1 deletions(-)


diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
index d475ff5..438cc9b 100644
--- a/fs/nfs/fscache.c
+++ b/fs/nfs/fscache.c
@@ -344,5 +344,115 @@ void __nfs_fscache_invalidate_page(struct page *page, 
struct inode *inode)
 
BUG_ON(!PageLocked(page));
fscache_uncache_page(nfsi-fscache, page);
-   nfs_add_stats(page-mapping-host, NFSIOS_FSCACHE_UNCACHE, 1);
+   nfs_add_stats(inode, NFSIOS_FSCACHE_UNCACHE, 1);
+}
+
+/*
+ * Handle completion of a page being read from the cache.
+ * - Called in process (keventd) context.
+ */
+static void nfs_readpage_from_fscache_complete(struct page *page,
+  void *context,
+  int error)
+{
+   dfprintk(FSCACHE,
+NFS: readpage_from_fscache_complete (0x%p/0x%p/%d)\n,
+page, context, error);
+
+   /* if the read completes with an error, we just unlock the page and let
+* the VM reissue the readpage */
+   if (!error) {
+   SetPageUptodate(page);
+   unlock_page(page);
+   } else {
+   error = nfs_readpage_async(context, page-mapping-host, page);
+   if (error)
+   unlock_page(page);
+   }
+}
+
+/*
+ * Retrieve a page from fscache
+ */
+int __nfs_readpage_from_fscache(struct nfs_open_context *ctx,
+   struct inode *inode, struct page *page)
+{
+   int ret;
+
+   dfprintk(FSCACHE,
+NFS: readpage_from_fscache(fsc:%p/p:%p(i:%lx f:%lx)/0x%p)\n,
+NFS_I(inode)-fscache, page, page-index, page-flags, inode);
+
+   ret = fscache_read_or_alloc_page(NFS_I(inode)-fscache,
+page,
+nfs_readpage_from_fscache_complete,
+ctx,
+GFP_KERNEL);
+
+   switch (ret) {
+   case 0: /* read BIO submitted (page in fscache) */
+   dfprintk(FSCACHE,
+NFS:readpage_from_fscache: BIO submitted\n);
+   nfs_add_stats(inode, NFSIOS_FSCACHE_READ_OK, 1);
+   return ret;
+
+   case -ENOBUFS: /* inode not in cache */
+   case -ENODATA: /* page not in cache */
+   nfs_add_stats(inode, NFSIOS_FSCACHE_READ_FAIL, 1);
+   dfprintk(FSCACHE,
+NFS:readpage_from_fscache %d\n, ret);
+   return 1;
+
+   default:
+   dfprintk(FSCACHE, NFS:readpage_from_fscache %d\n, ret);
+   nfs_add_stats(inode, NFSIOS_FSCACHE_READ_FAIL, 1);
+   }
+   return ret;
+}
+
+/*
+ * Retrieve a set of pages from fscache
+ */
+int __nfs_readpages_from_fscache(struct nfs_open_context *ctx,
+struct inode *inode,
+struct address_space *mapping,
+struct list_head *pages,
+unsigned *nr_pages)
+{
+   int ret, npages = *nr_pages;
+
+   dfprintk(FSCACHE, NFS: nfs_getpages_from_fscache (0x%p/%u/0x%p)\n,
+NFS_I(inode)-fscache, npages, inode);
+
+   ret = fscache_read_or_alloc_pages(NFS_I(inode)-fscache,
+ mapping, pages, nr_pages,
+ nfs_readpage_from_fscache_complete,
+ ctx,
+ mapping_gfp_mask(mapping));
+   if (*nr_pages  npages)
+   nfs_add_stats(inode, NFSIOS_FSCACHE_READ_OK, npages);
+   if (*nr_pages  0)
+   nfs_add_stats(inode, NFSIOS_FSCACHE_READ_FAIL, *nr_pages);
+
+   switch (ret) {
+   case 0: /* read submitted to the cache for all pages */
+   BUG_ON(!list_empty(pages));
+   BUG_ON(*nr_pages != 0);
+   dfprintk(FSCACHE,
+NFS: nfs_getpages_from_fscache: submitted\n);
+
+   return ret;
+
+   case -ENOBUFS: /* some pages aren't cached and can't be */
+   case -ENODATA: /* some pages aren't cached */
+   dfprintk(FSCACHE,
+NFS: nfs_getpages_from_fscache: no page: %d\n, ret);
+   return 1;
+
+   default:
+   dfprintk(FSCACHE,
+NFS: nfs_getpages_from_fscache: ret  %d\n, ret);
+   }
+
+   return ret;
 }
diff --git a/fs/nfs/fscache.h b/fs/nfs/fscache.h
index 1cb7d96..4c1e1a8 100644
--- a/fs/nfs/fscache.h
+++ b/fs/nfs/fscache.h
@@ -89,6 +89,12