aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@fys.uio.no>2005-01-04 21:46:31 +0100
committerTrond Myklebust <trond.myklebust@fys.uio.no>2005-01-04 21:46:31 +0100
commite5a9af8f74583c175f45055b492ac5f218b41dfc (patch)
tree19c58ceb11d3383462a8e225c8658542dd32584f /fs
parenta0358ceace052cd8e0973e1a3ab5ca992082a927 (diff)
downloadhistory-e5a9af8f74583c175f45055b492ac5f218b41dfc.tar.gz
Subject: [PATCH] NFS: Direct read path allocates nfs_read_data on the stack
Reduce stack utilization in the NFS direct read path by using a dynamically allocated nfs_read_data structure instead of allocating one on the stack. This reduces stack utilization of nfs_direct_read_seg from over 900 bytes to less than 100 bytes. Signed-off-by: Chuck Lever <cel@netapp.com> Signed-off-by: Trond Myklebust <trond.myklebust@fys.uio.no>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/direct.c65
-rw-r--r--fs/nfs/read.c19
2 files changed, 34 insertions, 50 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 5dd9f6011bcf3a..3fa5d86f0d7b9d 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -124,34 +124,35 @@ nfs_direct_read_seg(struct inode *inode, struct nfs_open_context *ctx,
const unsigned int rsize = NFS_SERVER(inode)->rsize;
int tot_bytes = 0;
int curpage = 0;
- struct nfs_read_data rdata = {
- .inode = inode,
- .cred = ctx->cred,
- .args = {
- .fh = NFS_FH(inode),
- .context = ctx,
- },
- .res = {
- .fattr = &rdata.fattr,
- },
- };
+ struct nfs_read_data *rdata;
+
+ rdata = nfs_readdata_alloc();
+ if (!rdata)
+ return -ENOMEM;
+
+ memset(rdata, 0, sizeof(*rdata));
+ rdata->inode = inode;
+ rdata->cred = ctx->cred;
+ rdata->args.fh = NFS_FH(inode);
+ rdata->args.context = ctx;
+ rdata->res.fattr = &rdata->fattr;
- rdata.args.pgbase = user_addr & ~PAGE_MASK;
- rdata.args.offset = file_offset;
- do {
+ rdata->args.pgbase = user_addr & ~PAGE_MASK;
+ rdata->args.offset = file_offset;
+ do {
int result;
- rdata.args.count = count;
- if (rdata.args.count > rsize)
- rdata.args.count = rsize;
- rdata.args.pages = &pages[curpage];
+ rdata->args.count = count;
+ if (rdata->args.count > rsize)
+ rdata->args.count = rsize;
+ rdata->args.pages = &pages[curpage];
dprintk("NFS: direct read: c=%u o=%Ld ua=%lu, pb=%u, cp=%u\n",
- rdata.args.count, (long long) rdata.args.offset,
- user_addr + tot_bytes, rdata.args.pgbase, curpage);
+ rdata->args.count, (long long) rdata->args.offset,
+ user_addr + tot_bytes, rdata->args.pgbase, curpage);
lock_kernel();
- result = NFS_PROTO(inode)->read(&rdata);
+ result = NFS_PROTO(inode)->read(rdata);
unlock_kernel();
if (result <= 0) {
@@ -159,23 +160,22 @@ nfs_direct_read_seg(struct inode *inode, struct nfs_open_context *ctx,
break;
if (result == -EISDIR)
result = -EINVAL;
+ nfs_readdata_free(rdata);
return result;
}
- tot_bytes += result;
- if (rdata.res.eof)
+ tot_bytes += result;
+ if (rdata->res.eof)
break;
- rdata.args.offset += result;
- rdata.args.pgbase += result;
- curpage += rdata.args.pgbase >> PAGE_SHIFT;
- rdata.args.pgbase &= ~PAGE_MASK;
+ rdata->args.offset += result;
+ rdata->args.pgbase += result;
+ curpage += rdata->args.pgbase >> PAGE_SHIFT;
+ rdata->args.pgbase &= ~PAGE_MASK;
count -= result;
} while (count != 0);
- /* XXX: should we zero the rest of the user's buffer if we
- * hit eof? */
-
+ nfs_readdata_free(rdata);
return tot_bytes;
}
@@ -188,9 +188,8 @@ nfs_direct_read_seg(struct inode *inode, struct nfs_open_context *ctx,
* file_offset: offset in file to begin the operation
* nr_segs: size of iovec array
*
- * generic_file_direct_IO has already pushed out any non-direct
- * writes so that this read will see them when we read from the
- * server.
+ * We've already pushed out any non-direct writes so that this read
+ * will see them when we read from the server.
*/
static ssize_t
nfs_direct_read(struct inode *inode, struct nfs_open_context *ctx,
diff --git a/fs/nfs/read.c b/fs/nfs/read.c
index 0de2e2d120154a..cb6f7bfe373b23 100644
--- a/fs/nfs/read.c
+++ b/fs/nfs/read.c
@@ -24,7 +24,6 @@
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/pagemap.h>
-#include <linux/mempool.h>
#include <linux/sunrpc/clnt.h>
#include <linux/nfs_fs.h>
#include <linux/nfs_page.h>
@@ -39,25 +38,11 @@ static void nfs_readpage_result_partial(struct nfs_read_data *, int);
static void nfs_readpage_result_full(struct nfs_read_data *, int);
static kmem_cache_t *nfs_rdata_cachep;
-static mempool_t *nfs_rdata_mempool;
+mempool_t *nfs_rdata_mempool;
#define MIN_POOL_READ (32)
-static struct nfs_read_data *nfs_readdata_alloc(void)
-{
- struct nfs_read_data *p;
- p = (struct nfs_read_data *)mempool_alloc(nfs_rdata_mempool, SLAB_NOFS);
- if (p)
- memset(p, 0, sizeof(*p));
- return p;
-}
-
-static __inline__ void nfs_readdata_free(struct nfs_read_data *p)
-{
- mempool_free(p, nfs_rdata_mempool);
-}
-
-static void nfs_readdata_release(struct rpc_task *task)
+void nfs_readdata_release(struct rpc_task *task)
{
struct nfs_read_data *data = (struct nfs_read_data *)task->tk_calldata;
nfs_readdata_free(data);