Commit 1d9612dd authored by Neil Brown's avatar Neil Brown Committed by Linus Torvalds

[PATCH] knfsd: reduce stack usage in nfsd4

nfsd4_proc_compound is using over a thousand bytes of stack.

This is partly because it declares two local svc_fh's, partly because of a big
switch statement which calls a bunch of functions which may be inlined.

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>        
Signed-off-by: default avatarNeil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 0ba524ef
......@@ -318,7 +318,7 @@ nfsd4_commit(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_com
return status;
}
static inline int
static int
nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_create *create)
{
struct svc_fh resfh;
......@@ -435,7 +435,7 @@ nfsd4_link(struct svc_rqst *rqstp, struct svc_fh *current_fh,
return status;
}
static inline int
static int
nfsd4_lookupp(struct svc_rqst *rqstp, struct svc_fh *current_fh)
{
struct svc_fh tmp_fh;
......@@ -773,13 +773,20 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
struct nfsd4_compoundres *resp)
{
struct nfsd4_op *op;
struct svc_fh current_fh;
struct svc_fh save_fh;
struct svc_fh *current_fh = NULL;
struct svc_fh *save_fh = NULL;
int slack_space; /* in words, not bytes! */
int status;
fh_init(&current_fh, NFS4_FHSIZE);
fh_init(&save_fh, NFS4_FHSIZE);
status = nfserr_resource;
current_fh = kmalloc(sizeof(*current_fh), GFP_KERNEL);
if (current_fh == NULL)
goto out;
fh_init(current_fh, NFS4_FHSIZE);
save_fh = kmalloc(sizeof(*save_fh), GFP_KERNEL);
if (save_fh == NULL)
goto out;
fh_init(save_fh, NFS4_FHSIZE);
resp->xbuf = &rqstp->rq_res;
resp->p = rqstp->rq_res.head[0].iov_base + rqstp->rq_res.head[0].iov_len;
......@@ -831,7 +838,7 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
* SETATTR NOFILEHANDLE error handled in nfsd4_setattr
* due to required returned bitmap argument
*/
if ((!current_fh.fh_dentry) &&
if ((!current_fh->fh_dentry) &&
!((op->opnum == OP_PUTFH) || (op->opnum == OP_PUTROOTFH) ||
(op->opnum == OP_SETCLIENTID) ||
(op->opnum == OP_SETCLIENTID_CONFIRM) ||
......@@ -843,105 +850,105 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
}
switch (op->opnum) {
case OP_ACCESS:
op->status = nfsd4_access(rqstp, &current_fh, &op->u.access);
op->status = nfsd4_access(rqstp, current_fh, &op->u.access);
break;
case OP_CLOSE:
op->status = nfsd4_close(rqstp, &current_fh, &op->u.close);
op->status = nfsd4_close(rqstp, current_fh, &op->u.close);
if (op->u.close.cl_stateowner)
op->replay =
&op->u.close.cl_stateowner->so_replay;
break;
case OP_COMMIT:
op->status = nfsd4_commit(rqstp, &current_fh, &op->u.commit);
op->status = nfsd4_commit(rqstp, current_fh, &op->u.commit);
break;
case OP_CREATE:
op->status = nfsd4_create(rqstp, &current_fh, &op->u.create);
op->status = nfsd4_create(rqstp, current_fh, &op->u.create);
break;
case OP_GETATTR:
op->status = nfsd4_getattr(rqstp, &current_fh, &op->u.getattr);
op->status = nfsd4_getattr(rqstp, current_fh, &op->u.getattr);
break;
case OP_GETFH:
op->status = nfsd4_getfh(&current_fh, &op->u.getfh);
op->status = nfsd4_getfh(current_fh, &op->u.getfh);
break;
case OP_LINK:
op->status = nfsd4_link(rqstp, &current_fh, &save_fh, &op->u.link);
op->status = nfsd4_link(rqstp, current_fh, save_fh, &op->u.link);
break;
case OP_LOCK:
op->status = nfsd4_lock(rqstp, &current_fh, &op->u.lock);
op->status = nfsd4_lock(rqstp, current_fh, &op->u.lock);
if (op->u.lock.lk_stateowner)
op->replay =
&op->u.lock.lk_stateowner->so_replay;
break;
case OP_LOCKT:
op->status = nfsd4_lockt(rqstp, &current_fh, &op->u.lockt);
op->status = nfsd4_lockt(rqstp, current_fh, &op->u.lockt);
break;
case OP_LOCKU:
op->status = nfsd4_locku(rqstp, &current_fh, &op->u.locku);
op->status = nfsd4_locku(rqstp, current_fh, &op->u.locku);
if (op->u.locku.lu_stateowner)
op->replay =
&op->u.locku.lu_stateowner->so_replay;
break;
case OP_LOOKUP:
op->status = nfsd4_lookup(rqstp, &current_fh, &op->u.lookup);
op->status = nfsd4_lookup(rqstp, current_fh, &op->u.lookup);
break;
case OP_LOOKUPP:
op->status = nfsd4_lookupp(rqstp, &current_fh);
op->status = nfsd4_lookupp(rqstp, current_fh);
break;
case OP_NVERIFY:
op->status = nfsd4_verify(rqstp, &current_fh, &op->u.nverify);
op->status = nfsd4_verify(rqstp, current_fh, &op->u.nverify);
if (op->status == nfserr_not_same)
op->status = nfs_ok;
break;
case OP_OPEN:
op->status = nfsd4_open(rqstp, &current_fh, &op->u.open);
op->status = nfsd4_open(rqstp, current_fh, &op->u.open);
if (op->u.open.op_stateowner)
op->replay =
&op->u.open.op_stateowner->so_replay;
break;
case OP_OPEN_CONFIRM:
op->status = nfsd4_open_confirm(rqstp, &current_fh, &op->u.open_confirm);
op->status = nfsd4_open_confirm(rqstp, current_fh, &op->u.open_confirm);
if (op->u.open_confirm.oc_stateowner)
op->replay =
&op->u.open_confirm.oc_stateowner->so_replay;
break;
case OP_OPEN_DOWNGRADE:
op->status = nfsd4_open_downgrade(rqstp, &current_fh, &op->u.open_downgrade);
op->status = nfsd4_open_downgrade(rqstp, current_fh, &op->u.open_downgrade);
if (op->u.open_downgrade.od_stateowner)
op->replay =
&op->u.open_downgrade.od_stateowner->so_replay;
break;
case OP_PUTFH:
op->status = nfsd4_putfh(rqstp, &current_fh, &op->u.putfh);
op->status = nfsd4_putfh(rqstp, current_fh, &op->u.putfh);
break;
case OP_PUTROOTFH:
op->status = nfsd4_putrootfh(rqstp, &current_fh);
op->status = nfsd4_putrootfh(rqstp, current_fh);
break;
case OP_READ:
op->status = nfsd4_read(rqstp, &current_fh, &op->u.read);
op->status = nfsd4_read(rqstp, current_fh, &op->u.read);
break;
case OP_READDIR:
op->status = nfsd4_readdir(rqstp, &current_fh, &op->u.readdir);
op->status = nfsd4_readdir(rqstp, current_fh, &op->u.readdir);
break;
case OP_READLINK:
op->status = nfsd4_readlink(rqstp, &current_fh, &op->u.readlink);
op->status = nfsd4_readlink(rqstp, current_fh, &op->u.readlink);
break;
case OP_REMOVE:
op->status = nfsd4_remove(rqstp, &current_fh, &op->u.remove);
op->status = nfsd4_remove(rqstp, current_fh, &op->u.remove);
break;
case OP_RENAME:
op->status = nfsd4_rename(rqstp, &current_fh, &save_fh, &op->u.rename);
op->status = nfsd4_rename(rqstp, current_fh, save_fh, &op->u.rename);
break;
case OP_RENEW:
op->status = nfsd4_renew(&op->u.renew);
break;
case OP_RESTOREFH:
op->status = nfsd4_restorefh(&current_fh, &save_fh);
op->status = nfsd4_restorefh(current_fh, save_fh);
break;
case OP_SAVEFH:
op->status = nfsd4_savefh(&current_fh, &save_fh);
op->status = nfsd4_savefh(current_fh, save_fh);
break;
case OP_SETATTR:
op->status = nfsd4_setattr(rqstp, &current_fh, &op->u.setattr);
op->status = nfsd4_setattr(rqstp, current_fh, &op->u.setattr);
break;
case OP_SETCLIENTID:
op->status = nfsd4_setclientid(rqstp, &op->u.setclientid);
......@@ -950,12 +957,12 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
op->status = nfsd4_setclientid_confirm(rqstp, &op->u.setclientid_confirm);
break;
case OP_VERIFY:
op->status = nfsd4_verify(rqstp, &current_fh, &op->u.verify);
op->status = nfsd4_verify(rqstp, current_fh, &op->u.verify);
if (op->status == nfserr_same)
op->status = nfs_ok;
break;
case OP_WRITE:
op->status = nfsd4_write(rqstp, &current_fh, &op->u.write);
op->status = nfsd4_write(rqstp, current_fh, &op->u.write);
break;
case OP_RELEASE_LOCKOWNER:
op->status = nfsd4_release_lockowner(rqstp, &op->u.release_lockowner);
......@@ -990,8 +997,12 @@ nfsd4_proc_compound(struct svc_rqst *rqstp,
kfree(tb->buf);
kfree(tb);
}
fh_put(&current_fh);
fh_put(&save_fh);
if (current_fh)
fh_put(current_fh);
kfree(current_fh);
if (save_fh)
fh_put(save_fh);
kfree(save_fh);
return status;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment