[pnfs] [PATCH 13/29] pnfs: read path set ds_size

Benny Halevy bhalevy at panasas.com
Fri Dec 28 03:45:07 EST 2007


From: Andy Adamson <andros at umich.edu>

Use the pNFS ds_rsize for read pageio.

When using the nfs page cache for pNFS I/O, it is necessary to setupe pages
using the rsize of the storage device instead of the rsize of the MDS.

In 2.6.18.3, there are several read I/O paths through the client code and
the rsize was used in each of these paths to setup the nfs page cache. Since
several functions used the rsize, an rpc_ops->rsize function makes sense.

In 2.6.24, there is only one read I/O path through the client code. The
interface to the nfs page cache has been re-written. It is now shared between
the read and write code paths, and moved entirely to fs/nfs/pagelist.c.

As a result, there is now only one place to set the rsize.

This patch removes the rpc_ops->rsize function pointer and
sets the rsize to the pNFS ds_size when pNFS is being used.

pNFS is not being used if layoutget fails, or the count is below the
threshold.

Signed-off-by: Andy Adamson<andros at umich.edu>
Signed-off-by: Benny Halevy <bhalevy at panasas.com>
---
 fs/nfs/nfs4proc.c |    1 -
 fs/nfs/pnfs.c     |   48 ++++++++++++++++++++++++++++++++++++++----------
 fs/nfs/pnfs.h     |   23 ++++++++++++++++++++++-
 fs/nfs/read.c     |    7 +++++++
 4 files changed, 67 insertions(+), 12 deletions(-)

diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 2294754..3613960 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -5312,7 +5312,6 @@ const struct nfs_rpc_ops pnfs_v41_clientops = {
 	.file_open      = nfs_open,
 	.file_release   = nfs_release,
 	.lock		= nfs4_proc_lock,
-	.rsize		= pnfs_rsize,
 	.wsize		= pnfs_wsize,
 	.rpages		= pnfs_rpages,
 	.wpages		= pnfs_wpages,
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 33de1e9..c269cf6 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -640,6 +640,44 @@ check:
 		return 0;
 }
 
+/*
+ * rsize is already set by caller to MDS rsize.
+ */
+void
+pnfs_set_ds_size(struct inode *inode,
+		 struct nfs_open_context *ctx,
+		 struct list_head *pages,
+		 loff_t offset,
+		 size_t *rsize)
+{
+	struct nfs_server *nfss = NFS_SERVER(inode);
+	struct page *page;
+	size_t count = 0;
+	int status = 0;
+
+	dprintk("--> %s inode %p ctx %p pages %p offset %lu\n",
+		__func__, inode, ctx, pages, (unsigned long)offset);
+
+	if (!pnfs_enabled_sb(nfss))
+		return;
+
+	/* Calculate the total read-ahead count */
+	list_for_each_entry(page, pages, lru)
+		count += pnfs_page_length(page, inode);
+
+	dprintk("%s count %ld\n", __func__,(long int)count);
+
+
+	status = virtual_update_layout(inode, ctx, count,
+						offset, IOMODE_READ);
+	dprintk("%s *rsize %Zd virt update returned %d\n",
+					__func__, *rsize, status);
+
+	if (status == 0 && count > 0 && !below_threshold(inode, count, 0))
+		*rsize = NFS_SERVER(inode)->ds_rsize;
+}
+
+
 /* This is utilized in the paging system to determine if
  * it should use the NFSv4 or pNFS read path.
  * If count < 0, we do not check the I/O size.
@@ -1489,16 +1527,6 @@ struct pnfs_client_operations pnfs_ops = {
 };
 
 int
-pnfs_rsize(struct inode *inode, unsigned int count, struct nfs_read_data *rdata)
-{
-	if (count >= 0 && below_threshold(inode, count, 0))
-		return NFS_SERVER(inode)->rsize;
-
-	rdata->pnfsflags |= PNFS_USE_DS;
-	return NFS_SERVER(inode)->ds_rsize;
-}
-
-int
 pnfs_wsize(struct inode *inode, unsigned int count, struct nfs_write_data *wdata)
 {
 	if (count >= 0 && below_threshold(inode, count, 1))
diff --git a/fs/nfs/pnfs.h b/fs/nfs/pnfs.h
index 8eeaf60..aa17804 100644
--- a/fs/nfs/pnfs.h
+++ b/fs/nfs/pnfs.h
@@ -46,13 +46,34 @@ int pnfs_use_nfsv4_rproto(struct inode *inode, ssize_t count);
 unsigned int pnfs_getiosize(struct nfs_server *server);
 int pnfs_commit(struct inode *inode, struct list_head *head, int sync, struct nfs_write_data *data);
 int pnfs_try_to_commit(struct inode *, struct nfs_write_data *, struct list_head *, int);
-int pnfs_rsize(struct inode *, unsigned int, struct nfs_read_data *);
 int pnfs_wsize(struct inode *, unsigned int, struct nfs_write_data *);
 int pnfs_rpages(struct inode *);
 int pnfs_wpages(struct inode *);
 void pnfs_readpage_result_norpc(struct rpc_task *task, void *calldata);
 void pnfs_writeback_done_norpc(struct rpc_task *, void *);
 void pnfs_commit_done_norpc(struct rpc_task *, void *);
+void pnfs_set_ds_size(struct inode *, struct nfs_open_context *, struct list_head *, loff_t, size_t *);
+
+
+/*
+ * Determine the number of bytes of data the page contains
+ */
+static inline
+unsigned int pnfs_page_length(struct page *page, struct inode *inode)
+{
+	loff_t i_size = i_size_read(inode);
+
+	if (i_size > 0) {
+		pgoff_t end_index = (i_size - 1) >> PAGE_CACHE_SHIFT;
+
+		if (page->index < end_index)
+			return PAGE_CACHE_SIZE;
+		if (page->index == end_index)
+			return ((i_size - 1) & ~PAGE_CACHE_MASK) + 1;
+	}
+	return 0;
+}
+
 #endif /* CONFIG_PNFS */
 
 #endif /* FS_NFS_PNFS_H */
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 46b350d..d7d8a02 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -22,6 +22,10 @@
 
 #include <asm/system.h>
 #include <linux/module.h>
+#ifdef CONFIG_PNFS
+#include <linux/pnfs_xdr.h>
+#include "pnfs.h"
+#endif /* CONFIG_PNFS */
 
 #include "nfs4_fs.h"
 #include "internal.h"
@@ -636,6 +640,9 @@ int nfs_readpages(struct file *filp, struct address_space *mapping,
 			return -EBADF;
 	} else
 		desc.ctx = get_nfs_open_context(nfs_file_open_context(filp));
+#ifdef CONFIG_PNFS
+	pnfs_set_ds_size(inode, desc.ctx, pages, filp->f_pos, &rsize);
+#endif /* CONFIG_PNFS */
 	if (rsize < PAGE_CACHE_SIZE)
 		nfs_pageio_init(&pgio, inode, nfs_pagein_multi, rsize, 0);
 	else
-- 
1.5.3.3



More information about the pNFS mailing list