diff options
author | Trond Myklebust <trond.myklebust@fys.uio.no> | 2005-01-04 21:46:31 +0100 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@fys.uio.no> | 2005-01-04 21:46:31 +0100 |
commit | e5a9af8f74583c175f45055b492ac5f218b41dfc (patch) | |
tree | 19c58ceb11d3383462a8e225c8658542dd32584f /fs | |
parent | a0358ceace052cd8e0973e1a3ab5ca992082a927 (diff) | |
download | history-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.c | 65 | ||||
-rw-r--r-- | fs/nfs/read.c | 19 |
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); |