linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 000 of 18] knfsd: Introduction - NFSv4 updates and more
@ 2006-12-08  1:13 NeilBrown
  2006-12-08  1:13 ` [PATCH 001 of 18] knfsd: nfsd4: remove a dprink from nfsd4_lock NeilBrown
                   ` (17 more replies)
  0 siblings, 18 replies; 19+ messages in thread
From: NeilBrown @ 2006-12-08  1:13 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel

Following are 18 patches against 2.6.19-rc6-mm2 which are suitable for 2.6.20.

First 16 are from the NFSv4 team at umich (thanks Bruce).  Mostly
fixing minor bugs and tidying-up code.

Last 2 from me.  We haven't been testing against old versions of
nfs-utils and bit-rot has set in.  Some of that (hopefully all) has
been fixed.

 [PATCH 001 of 18] knfsd: nfsd4: remove a dprink from nfsd4_lock
 [PATCH 002 of 18] knfsd: svcrpc: fix gss krb5i memory leak
 [PATCH 003 of 18] knfsd: nfsd4: clarify units of COMPOUND_SLACK_SPACE
 [PATCH 004 of 18] knfsd: nfsd: make exp_rootfh handle exp_parent errors
 [PATCH 005 of 18] knfsd: nfsd: simplify exp_pseudoroot
 [PATCH 006 of 18] knfsd: nfsd4: handling more nfsd_cross_mnt errors in nfsd4 readdir
 [PATCH 007 of 18] knfsd: nfsd: don't drop silently on upcall deferral
 [PATCH 008 of 18] knfsd: svcrpc: remove another silent drop from deferral code
 [PATCH 009 of 18] knfsd: nfsd4: pass saved and current fh together into nfsd4 operations.
 [PATCH 010 of 18] knfsd: nfsd4: remove spurious replay_owner check
 [PATCH 011 of 18] knfsd: nfsd4: move replay_owner to cstate
 [PATCH 012 of 18] knfsd: nfsd4: don't inline nfsd4 compound op functions
 [PATCH 013 of 18] knfsd: nfsd4: make verify and nverify wrappers
 [PATCH 014 of 18] knfsd: nfsd4: reorganize compound ops
 [PATCH 015 of 18] knfsd: nfsd4: simplify migration op check
 [PATCH 016 of 18] knfsd: nfsd4: simplify filehandle check
 [PATCH 017 of 18] knfsd: Don't ignore kstrdup failure in rpc caches.
 [PATCH 018 of 18] knfsd: Fix up some bit-rot in exp_export

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 001 of 18] knfsd: nfsd4: remove a dprink from nfsd4_lock
  2006-12-08  1:13 [PATCH 000 of 18] knfsd: Introduction - NFSv4 updates and more NeilBrown
@ 2006-12-08  1:13 ` NeilBrown
  2006-12-08  1:13 ` [PATCH 002 of 18] knfsd: svcrpc: fix gss krb5i memory leak NeilBrown
                   ` (16 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: NeilBrown @ 2006-12-08  1:13 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel


From: J.Bruce Fields <bfields@fieldses.org>

This dprintk is printing the wrong error now, but it's probably an
unnecessary dprintk anyway; just remove it.

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./fs/nfsd/nfs4state.c |    1 -
 1 file changed, 1 deletion(-)

diff .prev/fs/nfsd/nfs4state.c ./fs/nfsd/nfs4state.c
--- .prev/fs/nfsd/nfs4state.c	2006-12-08 12:07:29.000000000 +1100
+++ ./fs/nfsd/nfs4state.c	2006-12-08 12:07:57.000000000 +1100
@@ -2760,7 +2760,6 @@ nfsd4_lock(struct svc_rqst *rqstp, struc
 	conflock.fl_ops = NULL;
 	conflock.fl_lmops = NULL;
 	err = posix_lock_file_conf(filp, &file_lock, &conflock);
-	dprintk("NFSD: nfsd4_lock: posix_lock_file_conf status %d\n",status);
 	switch (-err) {
 	case 0: /* success! */
 		update_stateid(&lock_stp->st_stateid);

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 002 of 18] knfsd: svcrpc: fix gss krb5i memory leak
  2006-12-08  1:13 [PATCH 000 of 18] knfsd: Introduction - NFSv4 updates and more NeilBrown
  2006-12-08  1:13 ` [PATCH 001 of 18] knfsd: nfsd4: remove a dprink from nfsd4_lock NeilBrown
@ 2006-12-08  1:13 ` NeilBrown
  2006-12-08  1:13 ` [PATCH 003 of 18] knfsd: nfsd4: clarify units of COMPOUND_SLACK_SPACE NeilBrown
                   ` (15 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: NeilBrown @ 2006-12-08  1:13 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 1520 bytes --]


From: J.Bruce Fields <bfields@fieldses.org>

The memory leak here is embarassingly obvious.

This fixes a problem that causes the kernel to leak a small amount of
memory every time it receives a integrity-protected request.

Thanks to Aimé Le Rouzic for the bug report.

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./net/sunrpc/auth_gss/svcauth_gss.c |    9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff .prev/net/sunrpc/auth_gss/svcauth_gss.c ./net/sunrpc/auth_gss/svcauth_gss.c
--- .prev/net/sunrpc/auth_gss/svcauth_gss.c	2006-12-08 12:07:28.000000000 +1100
+++ ./net/sunrpc/auth_gss/svcauth_gss.c	2006-12-08 12:08:05.000000000 +1100
@@ -818,19 +818,19 @@ unwrap_integ_data(struct xdr_buf *buf, u
 
 	integ_len = svc_getnl(&buf->head[0]);
 	if (integ_len & 3)
-		goto out;
+		return stat;
 	if (integ_len > buf->len)
-		goto out;
+		return stat;
 	if (xdr_buf_subsegment(buf, &integ_buf, 0, integ_len))
 		BUG();
 	/* copy out mic... */
 	if (read_u32_from_xdr_buf(buf, integ_len, &mic.len))
 		BUG();
 	if (mic.len > RPC_MAX_AUTH_SIZE)
-		goto out;
+		return stat;
 	mic.data = kmalloc(mic.len, GFP_KERNEL);
 	if (!mic.data)
-		goto out;
+		return stat;
 	if (read_bytes_from_xdr_buf(buf, integ_len + 4, mic.data, mic.len))
 		goto out;
 	maj_stat = gss_verify_mic(ctx, &integ_buf, &mic);
@@ -840,6 +840,7 @@ unwrap_integ_data(struct xdr_buf *buf, u
 		goto out;
 	stat = 0;
 out:
+	kfree(mic.data);
 	return stat;
 }
 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 003 of 18] knfsd: nfsd4: clarify units of COMPOUND_SLACK_SPACE
  2006-12-08  1:13 [PATCH 000 of 18] knfsd: Introduction - NFSv4 updates and more NeilBrown
  2006-12-08  1:13 ` [PATCH 001 of 18] knfsd: nfsd4: remove a dprink from nfsd4_lock NeilBrown
  2006-12-08  1:13 ` [PATCH 002 of 18] knfsd: svcrpc: fix gss krb5i memory leak NeilBrown
@ 2006-12-08  1:13 ` NeilBrown
  2006-12-08  1:13 ` [PATCH 004 of 18] knfsd: nfsd: make exp_rootfh handle exp_parent errors NeilBrown
                   ` (14 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: NeilBrown @ 2006-12-08  1:13 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel


From: J.Bruce Fields <bfields@fieldses.org>

A comment here incorrectly states that "slack_space" is measured in words,
not bytes.  Remove the comment, and adjust a variable name and a few
comments to clarify the situation.

This is pure cleanup; there should be no change in functionality.

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./fs/nfsd/nfs4proc.c        |   10 +++++-----
 ./include/linux/nfsd/nfsd.h |    4 ++--
 2 files changed, 7 insertions(+), 7 deletions(-)

diff .prev/fs/nfsd/nfs4proc.c ./fs/nfsd/nfs4proc.c
--- .prev/fs/nfsd/nfs4proc.c	2006-12-08 12:07:28.000000000 +1100
+++ ./fs/nfsd/nfs4proc.c	2006-12-08 12:08:12.000000000 +1100
@@ -740,7 +740,7 @@ nfsd4_proc_compound(struct svc_rqst *rqs
 	struct svc_fh	*current_fh = NULL;
 	struct svc_fh	*save_fh = NULL;
 	struct nfs4_stateowner *replay_owner = NULL;
-	int		slack_space;    /* in words, not bytes! */
+	int		slack_bytes;
 	__be32		status;
 
 	status = nfserr_resource;
@@ -790,10 +790,10 @@ nfsd4_proc_compound(struct svc_rqst *rqs
 		 * failed response to the next operation.  If we don't
 		 * have enough room, fail with ERR_RESOURCE.
 		 */
-/* FIXME - is slack_space *really* words, or bytes??? - neilb */
-		slack_space = (char *)resp->end - (char *)resp->p;
-		if (slack_space < COMPOUND_SLACK_SPACE + COMPOUND_ERR_SLACK_SPACE) {
-			BUG_ON(slack_space < COMPOUND_ERR_SLACK_SPACE);
+		slack_bytes = (char *)resp->end - (char *)resp->p;
+		if (slack_bytes < COMPOUND_SLACK_SPACE
+				+ COMPOUND_ERR_SLACK_SPACE) {
+			BUG_ON(slack_bytes < COMPOUND_ERR_SLACK_SPACE);
 			op->status = nfserr_resource;
 			goto encode_op;
 		}

diff .prev/include/linux/nfsd/nfsd.h ./include/linux/nfsd/nfsd.h
--- .prev/include/linux/nfsd/nfsd.h	2006-12-08 12:07:28.000000000 +1100
+++ ./include/linux/nfsd/nfsd.h	2006-12-08 12:08:12.000000000 +1100
@@ -275,12 +275,12 @@ static inline int is_fsid(struct svc_fh 
  * we might process an operation with side effects, and be unable to
  * tell the client that the operation succeeded.
  *
- * COMPOUND_SLACK_SPACE - this is the minimum amount of buffer space
+ * COMPOUND_SLACK_SPACE - this is the minimum bytes of buffer space
  * needed to encode an "ordinary" _successful_ operation.  (GETATTR,
  * READ, READDIR, and READLINK have their own buffer checks.)  if we
  * fall below this level, we fail the next operation with NFS4ERR_RESOURCE.
  *
- * COMPOUND_ERR_SLACK_SPACE - this is the minimum amount of buffer space
+ * COMPOUND_ERR_SLACK_SPACE - this is the minimum bytes of buffer space
  * needed to encode an operation which has failed with NFS4ERR_RESOURCE.
  * care is taken to ensure that we never fall below this level for any
  * reason.

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 004 of 18] knfsd: nfsd: make exp_rootfh handle exp_parent errors
  2006-12-08  1:13 [PATCH 000 of 18] knfsd: Introduction - NFSv4 updates and more NeilBrown
                   ` (2 preceding siblings ...)
  2006-12-08  1:13 ` [PATCH 003 of 18] knfsd: nfsd4: clarify units of COMPOUND_SLACK_SPACE NeilBrown
@ 2006-12-08  1:13 ` NeilBrown
  2006-12-08  1:13 ` [PATCH 005 of 18] knfsd: nfsd: simplify exp_pseudoroot NeilBrown
                   ` (13 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: NeilBrown @ 2006-12-08  1:13 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel


From: J.Bruce Fields <bfields@fieldses.org>

Since exp_parent can fail by returning an error (-EAGAIN) in addition 
to by returning NULL, we should check for that case in exp_rootfh.

(TODO: we should check that userland handles these errors too.)

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./fs/nfsd/export.c |    4 ++++
 1 file changed, 4 insertions(+)

diff .prev/fs/nfsd/export.c ./fs/nfsd/export.c
--- .prev/fs/nfsd/export.c	2006-12-08 12:07:28.000000000 +1100
+++ ./fs/nfsd/export.c	2006-12-08 12:08:20.000000000 +1100
@@ -1104,6 +1104,10 @@ exp_rootfh(svc_client *clp, char *path, 
 		 path, nd.dentry, clp->name,
 		 inode->i_sb->s_id, inode->i_ino);
 	exp = exp_parent(clp, nd.mnt, nd.dentry, NULL);
+	if (IS_ERR(exp)) {
+		err = PTR_ERR(exp);
+		goto out;
+	}
 	if (!exp) {
 		dprintk("nfsd: exp_rootfh export not found.\n");
 		goto out;

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 005 of 18] knfsd: nfsd: simplify exp_pseudoroot
  2006-12-08  1:13 [PATCH 000 of 18] knfsd: Introduction - NFSv4 updates and more NeilBrown
                   ` (3 preceding siblings ...)
  2006-12-08  1:13 ` [PATCH 004 of 18] knfsd: nfsd: make exp_rootfh handle exp_parent errors NeilBrown
@ 2006-12-08  1:13 ` NeilBrown
  2006-12-08  1:13 ` [PATCH 006 of 18] knfsd: nfsd4: handling more nfsd_cross_mnt errors in nfsd4 readdir NeilBrown
                   ` (12 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: NeilBrown @ 2006-12-08  1:13 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel


From: J.Bruce Fields <bfields@fieldses.org>

Note there's no need for special handling of -EAGAIN here; nfserrno() does
what we want already.  So this is a pure cleanup with no change in
functionality.

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./fs/nfsd/export.c |    6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff .prev/fs/nfsd/export.c ./fs/nfsd/export.c
--- .prev/fs/nfsd/export.c	2006-12-08 12:08:20.000000000 +1100
+++ ./fs/nfsd/export.c	2006-12-08 12:08:25.000000000 +1100
@@ -1163,12 +1163,10 @@ exp_pseudoroot(struct auth_domain *clp, 
 	mk_fsid_v1(fsidv, 0);
 
 	exp = exp_find(clp, 1, fsidv, creq);
-	if (IS_ERR(exp) && PTR_ERR(exp) == -EAGAIN)
-		return nfserr_dropit;
+	if (IS_ERR(exp))
+		return nfserrno(PTR_ERR(exp));
 	if (exp == NULL)
 		return nfserr_perm;
-	else if (IS_ERR(exp))
-		return nfserrno(PTR_ERR(exp));
 	rv = fh_compose(fhp, exp, exp->ex_dentry, NULL);
 	exp_put(exp);
 	return rv;

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 006 of 18] knfsd: nfsd4: handling more nfsd_cross_mnt errors in nfsd4 readdir
  2006-12-08  1:13 [PATCH 000 of 18] knfsd: Introduction - NFSv4 updates and more NeilBrown
                   ` (4 preceding siblings ...)
  2006-12-08  1:13 ` [PATCH 005 of 18] knfsd: nfsd: simplify exp_pseudoroot NeilBrown
@ 2006-12-08  1:13 ` NeilBrown
  2006-12-08  1:13 ` [PATCH 007 of 18] knfsd: nfsd: don't drop silently on upcall deferral NeilBrown
                   ` (11 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: NeilBrown @ 2006-12-08  1:13 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel


From: J.Bruce Fields <bfields@fieldses.org>

This patch on its own causes no change in behavior, since nfsd_cross_mnt()
only returns -EAGAIN; but in the future I'd like it to also be able to
return -ETIMEDOUT, so we may as well handle any possible error here.

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./fs/nfsd/nfs4xdr.c |   14 +++++---------
 1 file changed, 5 insertions(+), 9 deletions(-)

diff .prev/fs/nfsd/nfs4xdr.c ./fs/nfsd/nfs4xdr.c
--- .prev/fs/nfsd/nfs4xdr.c	2006-12-08 12:07:28.000000000 +1100
+++ ./fs/nfsd/nfs4xdr.c	2006-12-08 12:08:31.000000000 +1100
@@ -1845,15 +1845,11 @@ nfsd4_encode_dirent_fattr(struct nfsd4_r
 
 	exp_get(exp);
 	if (d_mountpoint(dentry)) {
-		if (nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp)) {
-		/*
-		 * -EAGAIN is the only error returned from
-		 * nfsd_cross_mnt() and it indicates that an
-		 * up-call has  been initiated to fill in the export
-		 * options on exp.  When the answer comes back,
-		 * this call will be retried.
-		 */
-			nfserr = nfserr_dropit;
+		int err;
+
+		err = nfsd_cross_mnt(cd->rd_rqstp, &dentry, &exp);
+		if (err) {
+			nfserr = nfserrno(err);
 			goto out_put;
 		}
 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 007 of 18] knfsd: nfsd: don't drop silently on upcall deferral
  2006-12-08  1:13 [PATCH 000 of 18] knfsd: Introduction - NFSv4 updates and more NeilBrown
                   ` (5 preceding siblings ...)
  2006-12-08  1:13 ` [PATCH 006 of 18] knfsd: nfsd4: handling more nfsd_cross_mnt errors in nfsd4 readdir NeilBrown
@ 2006-12-08  1:13 ` NeilBrown
  2006-12-08  1:14 ` [PATCH 008 of 18] knfsd: svcrpc: remove another silent drop from deferral code NeilBrown
                   ` (10 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: NeilBrown @ 2006-12-08  1:13 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel


From: J.Bruce Fields <bfields@fieldses.org>

To avoid tying up server threads when nfsd makes an upcall (to mountd, to
get export options, to idmapd, for nfsv4 name<->id mapping, etc.), we
temporarily "drop" the request and save enough information so that we can
revisit it later.

Certain failures during the deferral process can cause us to really drop
the request and never revisit it.

This is often less than ideal, and is unacceptable in the NFSv4 case--rfc
3530 forbids the server from dropping a request without also closing the
connection.

As a first step, we modify the deferral code to return -ETIMEDOUT (which is
translated to nfserr_jukebox in the v3 and v4 cases, and remains a drop in
the v2 case).

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./fs/nfsd/export.c                  |   11 ++++++++---
 ./fs/nfsd/nfsfh.c                   |    6 ++++--
 ./fs/nfsd/vfs.c                     |    2 +-
 ./net/sunrpc/auth_gss/svcauth_gss.c |    2 +-
 ./net/sunrpc/cache.c                |   11 +++++++----
 ./net/sunrpc/svcauth_unix.c         |    1 +
 6 files changed, 22 insertions(+), 11 deletions(-)

diff .prev/fs/nfsd/export.c ./fs/nfsd/export.c
--- .prev/fs/nfsd/export.c	2006-12-08 12:08:25.000000000 +1100
+++ ./fs/nfsd/export.c	2006-12-08 12:08:37.000000000 +1100
@@ -787,15 +787,20 @@ exp_get_by_name(svc_client *clp, struct 
 	key.ex_dentry = dentry;
 
 	exp = svc_export_lookup(&key);
-	if (exp != NULL) 
-		switch (cache_check(&svc_export_cache, &exp->h, reqp)) {
+	if (exp != NULL)  {
+		int err;
+
+		err = cache_check(&svc_export_cache, &exp->h, reqp);
+		switch (err) {
 		case 0: break;
 		case -EAGAIN:
-			exp = ERR_PTR(-EAGAIN);
+		case -ETIMEDOUT:
+			exp = ERR_PTR(err);
 			break;
 		default:
 			exp = NULL;
 		}
+	}
 
 	return exp;
 }

diff .prev/fs/nfsd/nfsfh.c ./fs/nfsd/nfsfh.c
--- .prev/fs/nfsd/nfsfh.c	2006-12-08 12:07:23.000000000 +1100
+++ ./fs/nfsd/nfsfh.c	2006-12-08 12:08:37.000000000 +1100
@@ -169,9 +169,11 @@ fh_verify(struct svc_rqst *rqstp, struct
 			exp = exp_find(rqstp->rq_client, 0, tfh, &rqstp->rq_chandle);
 		}
 
-		error = nfserr_dropit;
-		if (IS_ERR(exp) && PTR_ERR(exp) == -EAGAIN)
+		if (IS_ERR(exp) && (PTR_ERR(exp) == -EAGAIN
+				|| PTR_ERR(exp) == -ETIMEDOUT)) {
+			error = nfserrno(PTR_ERR(exp));
 			goto out;
+		}
 
 		error = nfserr_stale; 
 		if (!exp || IS_ERR(exp))

diff .prev/fs/nfsd/vfs.c ./fs/nfsd/vfs.c
--- .prev/fs/nfsd/vfs.c	2006-12-08 12:07:23.000000000 +1100
+++ ./fs/nfsd/vfs.c	2006-12-08 12:08:37.000000000 +1100
@@ -99,7 +99,7 @@ static struct raparm_hbucket	raparm_hash
 /* 
  * Called from nfsd_lookup and encode_dirent. Check if we have crossed 
  * a mount point.
- * Returns -EAGAIN leaving *dpp and *expp unchanged, 
+ * Returns -EAGAIN or -ETIMEDOUT leaving *dpp and *expp unchanged,
  *  or nfs_ok having possibly changed *dpp and *expp
  */
 int

diff .prev/net/sunrpc/auth_gss/svcauth_gss.c ./net/sunrpc/auth_gss/svcauth_gss.c
--- .prev/net/sunrpc/auth_gss/svcauth_gss.c	2006-12-08 12:08:05.000000000 +1100
+++ ./net/sunrpc/auth_gss/svcauth_gss.c	2006-12-08 12:08:37.000000000 +1100
@@ -1080,7 +1080,7 @@ svcauth_gss_accept(struct svc_rqst *rqst
 		}
 		switch(cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle)) {
 		case -EAGAIN:
-			goto drop;
+		case -ETIMEDOUT:
 		case -ENOENT:
 			goto drop;
 		case 0:

diff .prev/net/sunrpc/cache.c ./net/sunrpc/cache.c
--- .prev/net/sunrpc/cache.c	2006-12-08 12:07:23.000000000 +1100
+++ ./net/sunrpc/cache.c	2006-12-08 12:09:12.000000000 +1100
@@ -34,7 +34,7 @@
 
 #define	 RPCDBG_FACILITY RPCDBG_CACHE
 
-static void cache_defer_req(struct cache_req *req, struct cache_head *item);
+static int cache_defer_req(struct cache_req *req, struct cache_head *item);
 static void cache_revisit_request(struct cache_head *item);
 
 static void cache_init(struct cache_head *h)
@@ -185,6 +185,7 @@ static int cache_make_upcall(struct cach
  *
  * Returns 0 if the cache_head can be used, or cache_puts it and returns
  * -EAGAIN if upcall is pending,
+ * -ETIMEDOUT if upcall failed and should be retried,
  * -ENOENT if cache entry was negative
  */
 int cache_check(struct cache_detail *detail,
@@ -236,7 +237,8 @@ int cache_check(struct cache_detail *det
 	}
 
 	if (rv == -EAGAIN)
-		cache_defer_req(rqstp, h);
+		if (cache_defer_req(rqstp, h) != 0)
+			rv = -ETIMEDOUT;
 
 	if (rv)
 		cache_put(h, detail);
@@ -523,14 +525,14 @@ static LIST_HEAD(cache_defer_list);
 static struct list_head cache_defer_hash[DFR_HASHSIZE];
 static int cache_defer_cnt;
 
-static void cache_defer_req(struct cache_req *req, struct cache_head *item)
+static int cache_defer_req(struct cache_req *req, struct cache_head *item)
 {
 	struct cache_deferred_req *dreq;
 	int hash = DFR_HASH(item);
 
 	dreq = req->defer(req);
 	if (dreq == NULL)
-		return;
+		return -ETIMEDOUT;
 
 	dreq->item = item;
 	dreq->recv_time = get_seconds();
@@ -571,6 +573,7 @@ static void cache_defer_req(struct cache
 		/* must have just been validated... */
 		cache_revisit_request(item);
 	}
+	return 0;
 }
 
 static void cache_revisit_request(struct cache_head *item)

diff .prev/net/sunrpc/svcauth_unix.c ./net/sunrpc/svcauth_unix.c
--- .prev/net/sunrpc/svcauth_unix.c	2006-12-08 12:07:23.000000000 +1100
+++ ./net/sunrpc/svcauth_unix.c	2006-12-08 12:08:37.000000000 +1100
@@ -435,6 +435,7 @@ svcauth_unix_set_client(struct svc_rqst 
 		default:
 			BUG();
 		case -EAGAIN:
+		case -ETIMEDOUT:
 			return SVC_DROP;
 		case -ENOENT:
 			return SVC_DENIED;

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 008 of 18] knfsd: svcrpc: remove another silent drop from deferral code
  2006-12-08  1:13 [PATCH 000 of 18] knfsd: Introduction - NFSv4 updates and more NeilBrown
                   ` (6 preceding siblings ...)
  2006-12-08  1:13 ` [PATCH 007 of 18] knfsd: nfsd: don't drop silently on upcall deferral NeilBrown
@ 2006-12-08  1:14 ` NeilBrown
  2006-12-08  1:14 ` [PATCH 009 of 18] knfsd: nfsd4: pass saved and current fh together into nfsd4 operations NeilBrown
                   ` (9 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: NeilBrown @ 2006-12-08  1:14 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel


From: J.Bruce Fields <bfields@fieldses.org>

There's no point deferring something just to immediately fail the deferral,
especially now that we can do something more useful in the failure case by
returning an error.

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./net/sunrpc/cache.c |   20 +++++++++-----------
 1 file changed, 9 insertions(+), 11 deletions(-)

diff .prev/net/sunrpc/cache.c ./net/sunrpc/cache.c
--- .prev/net/sunrpc/cache.c	2006-12-08 12:09:12.000000000 +1100
+++ ./net/sunrpc/cache.c	2006-12-08 12:09:26.000000000 +1100
@@ -530,6 +530,13 @@ static int cache_defer_req(struct cache_
 	struct cache_deferred_req *dreq;
 	int hash = DFR_HASH(item);
 
+	if (cache_defer_cnt >= DFR_MAX) {
+		/* too much in the cache, randomly drop this one,
+		 * or continue and drop the oldest below
+		 */
+		if (net_random()&1)
+			return -ETIMEDOUT;
+	}
 	dreq = req->defer(req);
 	if (dreq == NULL)
 		return -ETIMEDOUT;
@@ -548,17 +555,8 @@ static int cache_defer_req(struct cache_
 	/* it is in, now maybe clean up */
 	dreq = NULL;
 	if (++cache_defer_cnt > DFR_MAX) {
-		/* too much in the cache, randomly drop
-		 * first or last
-		 */
-		if (net_random()&1) 
-			dreq = list_entry(cache_defer_list.next,
-					  struct cache_deferred_req,
-					  recent);
-		else
-			dreq = list_entry(cache_defer_list.prev,
-					  struct cache_deferred_req,
-					  recent);
+		dreq = list_entry(cache_defer_list.prev,
+				  struct cache_deferred_req, recent);
 		list_del(&dreq->recent);
 		list_del(&dreq->hash);
 		cache_defer_cnt--;

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 009 of 18] knfsd: nfsd4: pass saved and current fh together into nfsd4 operations.
  2006-12-08  1:13 [PATCH 000 of 18] knfsd: Introduction - NFSv4 updates and more NeilBrown
                   ` (7 preceding siblings ...)
  2006-12-08  1:14 ` [PATCH 008 of 18] knfsd: svcrpc: remove another silent drop from deferral code NeilBrown
@ 2006-12-08  1:14 ` NeilBrown
  2006-12-08  1:14 ` [PATCH 010 of 18] knfsd: nfsd4: remove spurious replay_owner check NeilBrown
                   ` (8 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: NeilBrown @ 2006-12-08  1:14 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel


From: J.Bruce Fields <bfields@fieldses.org>

Pass the saved and current filehandles together into all the nfsd4 compound
operations.

I want a unified interface to these operations so we can just call them by
pointer and throw out the huge switch statement.

Also I'll eventually want a structure like this--that holds the state used
during compound processing--for deferral.

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./fs/nfsd/nfs4proc.c        |  348 +++++++++++++++++++++++++-------------------
 ./fs/nfsd/nfs4state.c       |   68 +++++---
 ./include/linux/nfsd/xdr4.h |   22 +-
 3 files changed, 259 insertions(+), 179 deletions(-)

diff .prev/fs/nfsd/nfs4proc.c ./fs/nfsd/nfs4proc.c
--- .prev/fs/nfsd/nfs4proc.c	2006-12-08 12:08:12.000000000 +1100
+++ ./fs/nfsd/nfs4proc.c	2006-12-08 12:09:27.000000000 +1100
@@ -162,7 +162,8 @@ do_open_fhandle(struct svc_rqst *rqstp, 
 
 
 static inline __be32
-nfsd4_open(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open, struct nfs4_stateowner **replay_owner)
+nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	   struct nfsd4_open *open, struct nfs4_stateowner **replay_owner)
 {
 	__be32 status;
 	dprintk("NFSD: nfsd4_open filename %.*s op_stateowner %p\n",
@@ -179,11 +180,11 @@ nfsd4_open(struct svc_rqst *rqstp, struc
 	status = nfsd4_process_open1(open);
 	if (status == nfserr_replay_me) {
 		struct nfs4_replay *rp = &open->op_stateowner->so_replay;
-		fh_put(current_fh);
-		current_fh->fh_handle.fh_size = rp->rp_openfh_len;
-		memcpy(&current_fh->fh_handle.fh_base, rp->rp_openfh,
+		fh_put(&cstate->current_fh);
+		cstate->current_fh.fh_handle.fh_size = rp->rp_openfh_len;
+		memcpy(&cstate->current_fh.fh_handle.fh_base, rp->rp_openfh,
 				rp->rp_openfh_len);
-		status = fh_verify(rqstp, current_fh, 0, MAY_NOP);
+		status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
 		if (status)
 			dprintk("nfsd4_open: replay failed"
 				" restoring previous filehandle\n");
@@ -215,7 +216,8 @@ nfsd4_open(struct svc_rqst *rqstp, struc
 			 * (3) set open->op_truncate if the file is to be
 			 * truncated after opening, (4) do permission checking.
 			 */
-			status = do_open_lookup(rqstp, current_fh, open);
+			status = do_open_lookup(rqstp, &cstate->current_fh,
+						open);
 			if (status)
 				goto out;
 			break;
@@ -227,7 +229,8 @@ nfsd4_open(struct svc_rqst *rqstp, struc
 			 * open->op_truncate if the file is to be truncated
 			 * after opening, (3) do permission checking.
 			*/
-			status = do_open_fhandle(rqstp, current_fh, open);
+			status = do_open_fhandle(rqstp, &cstate->current_fh,
+						 open);
 			if (status)
 				goto out;
 			break;
@@ -248,7 +251,7 @@ nfsd4_open(struct svc_rqst *rqstp, struc
 	 * successful, it (1) truncates the file if open->op_truncate was
 	 * set, (2) sets open->op_stateid, (3) sets open->op_delegation.
 	 */
-	status = nfsd4_process_open2(rqstp, current_fh, open);
+	status = nfsd4_process_open2(rqstp, &cstate->current_fh, open);
 out:
 	if (open->op_stateowner) {
 		nfs4_get_stateowner(open->op_stateowner);
@@ -262,52 +265,54 @@ out:
  * filehandle-manipulating ops.
  */
 static inline __be32
-nfsd4_getfh(struct svc_fh *current_fh, struct svc_fh **getfh)
+nfsd4_getfh(struct nfsd4_compound_state *cstate, struct svc_fh **getfh)
 {
-	if (!current_fh->fh_dentry)
+	if (!cstate->current_fh.fh_dentry)
 		return nfserr_nofilehandle;
 
-	*getfh = current_fh;
+	*getfh = &cstate->current_fh;
 	return nfs_ok;
 }
 
 static inline __be32
-nfsd4_putfh(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_putfh *putfh)
+nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	    struct nfsd4_putfh *putfh)
 {
-	fh_put(current_fh);
-	current_fh->fh_handle.fh_size = putfh->pf_fhlen;
-	memcpy(&current_fh->fh_handle.fh_base, putfh->pf_fhval, putfh->pf_fhlen);
-	return fh_verify(rqstp, current_fh, 0, MAY_NOP);
+	fh_put(&cstate->current_fh);
+	cstate->current_fh.fh_handle.fh_size = putfh->pf_fhlen;
+	memcpy(&cstate->current_fh.fh_handle.fh_base, putfh->pf_fhval,
+	       putfh->pf_fhlen);
+	return fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
 }
 
 static inline __be32
-nfsd4_putrootfh(struct svc_rqst *rqstp, struct svc_fh *current_fh)
+nfsd4_putrootfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate)
 {
 	__be32 status;
 
-	fh_put(current_fh);
-	status = exp_pseudoroot(rqstp->rq_client, current_fh,
+	fh_put(&cstate->current_fh);
+	status = exp_pseudoroot(rqstp->rq_client, &cstate->current_fh,
 			      &rqstp->rq_chandle);
 	return status;
 }
 
 static inline __be32
-nfsd4_restorefh(struct svc_fh *current_fh, struct svc_fh *save_fh)
+nfsd4_restorefh(struct nfsd4_compound_state *cstate)
 {
-	if (!save_fh->fh_dentry)
+	if (!cstate->save_fh.fh_dentry)
 		return nfserr_restorefh;
 
-	fh_dup2(current_fh, save_fh);
+	fh_dup2(&cstate->current_fh, &cstate->save_fh);
 	return nfs_ok;
 }
 
 static inline __be32
-nfsd4_savefh(struct svc_fh *current_fh, struct svc_fh *save_fh)
+nfsd4_savefh(struct nfsd4_compound_state *cstate)
 {
-	if (!current_fh->fh_dentry)
+	if (!cstate->current_fh.fh_dentry)
 		return nfserr_nofilehandle;
 
-	fh_dup2(save_fh, current_fh);
+	fh_dup2(&cstate->save_fh, &cstate->current_fh);
 	return nfs_ok;
 }
 
@@ -315,17 +320,20 @@ nfsd4_savefh(struct svc_fh *current_fh, 
  * misc nfsv4 ops
  */
 static inline __be32
-nfsd4_access(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_access *access)
+nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	     struct nfsd4_access *access)
 {
 	if (access->ac_req_access & ~NFS3_ACCESS_FULL)
 		return nfserr_inval;
 
 	access->ac_resp_access = access->ac_req_access;
-	return nfsd_access(rqstp, current_fh, &access->ac_resp_access, &access->ac_supported);
+	return nfsd_access(rqstp, &cstate->current_fh, &access->ac_resp_access,
+			   &access->ac_supported);
 }
 
 static inline __be32
-nfsd4_commit(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_commit *commit)
+nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	     struct nfsd4_commit *commit)
 {
 	__be32 status;
 
@@ -333,14 +341,16 @@ nfsd4_commit(struct svc_rqst *rqstp, str
 	*p++ = nfssvc_boot.tv_sec;
 	*p++ = nfssvc_boot.tv_usec;
 
-	status = nfsd_commit(rqstp, current_fh, commit->co_offset, commit->co_count);
+	status = nfsd_commit(rqstp, &cstate->current_fh, commit->co_offset,
+			     commit->co_count);
 	if (status == nfserr_symlink)
 		status = nfserr_inval;
 	return status;
 }
 
 static __be32
-nfsd4_create(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_create *create)
+nfsd4_create(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	     struct nfsd4_create *create)
 {
 	struct svc_fh resfh;
 	__be32 status;
@@ -348,7 +358,7 @@ nfsd4_create(struct svc_rqst *rqstp, str
 
 	fh_init(&resfh, NFS4_FHSIZE);
 
-	status = fh_verify(rqstp, current_fh, S_IFDIR, MAY_CREATE);
+	status = fh_verify(rqstp, &cstate->current_fh, S_IFDIR, MAY_CREATE);
 	if (status == nfserr_symlink)
 		status = nfserr_notdir;
 	if (status)
@@ -365,9 +375,10 @@ nfsd4_create(struct svc_rqst *rqstp, str
 		 */
 		create->cr_linkname[create->cr_linklen] = 0;
 
-		status = nfsd_symlink(rqstp, current_fh, create->cr_name,
-				      create->cr_namelen, create->cr_linkname,
-				      create->cr_linklen, &resfh, &create->cr_iattr);
+		status = nfsd_symlink(rqstp, &cstate->current_fh,
+				      create->cr_name, create->cr_namelen,
+				      create->cr_linkname, create->cr_linklen,
+				      &resfh, &create->cr_iattr);
 		break;
 
 	case NF4BLK:
@@ -375,9 +386,9 @@ nfsd4_create(struct svc_rqst *rqstp, str
 		if (MAJOR(rdev) != create->cr_specdata1 ||
 		    MINOR(rdev) != create->cr_specdata2)
 			return nfserr_inval;
-		status = nfsd_create(rqstp, current_fh, create->cr_name,
-				     create->cr_namelen, &create->cr_iattr,
-				     S_IFBLK, rdev, &resfh);
+		status = nfsd_create(rqstp, &cstate->current_fh,
+				     create->cr_name, create->cr_namelen,
+				     &create->cr_iattr, S_IFBLK, rdev, &resfh);
 		break;
 
 	case NF4CHR:
@@ -385,28 +396,28 @@ nfsd4_create(struct svc_rqst *rqstp, str
 		if (MAJOR(rdev) != create->cr_specdata1 ||
 		    MINOR(rdev) != create->cr_specdata2)
 			return nfserr_inval;
-		status = nfsd_create(rqstp, current_fh, create->cr_name,
-				     create->cr_namelen, &create->cr_iattr,
-				     S_IFCHR, rdev, &resfh);
+		status = nfsd_create(rqstp, &cstate->current_fh,
+				     create->cr_name, create->cr_namelen,
+				     &create->cr_iattr,S_IFCHR, rdev, &resfh);
 		break;
 
 	case NF4SOCK:
-		status = nfsd_create(rqstp, current_fh, create->cr_name,
-				     create->cr_namelen, &create->cr_iattr,
-				     S_IFSOCK, 0, &resfh);
+		status = nfsd_create(rqstp, &cstate->current_fh,
+				     create->cr_name, create->cr_namelen,
+				     &create->cr_iattr, S_IFSOCK, 0, &resfh);
 		break;
 
 	case NF4FIFO:
-		status = nfsd_create(rqstp, current_fh, create->cr_name,
-				     create->cr_namelen, &create->cr_iattr,
-				     S_IFIFO, 0, &resfh);
+		status = nfsd_create(rqstp, &cstate->current_fh,
+				     create->cr_name, create->cr_namelen,
+				     &create->cr_iattr, S_IFIFO, 0, &resfh);
 		break;
 
 	case NF4DIR:
 		create->cr_iattr.ia_valid &= ~ATTR_SIZE;
-		status = nfsd_create(rqstp, current_fh, create->cr_name,
-				     create->cr_namelen, &create->cr_iattr,
-				     S_IFDIR, 0, &resfh);
+		status = nfsd_create(rqstp, &cstate->current_fh,
+				     create->cr_name, create->cr_namelen,
+				     &create->cr_iattr, S_IFDIR, 0, &resfh);
 		break;
 
 	default:
@@ -414,9 +425,9 @@ nfsd4_create(struct svc_rqst *rqstp, str
 	}
 
 	if (!status) {
-		fh_unlock(current_fh);
-		set_change_info(&create->cr_cinfo, current_fh);
-		fh_dup2(current_fh, &resfh);
+		fh_unlock(&cstate->current_fh);
+		set_change_info(&create->cr_cinfo, &cstate->current_fh);
+		fh_dup2(&cstate->current_fh, &resfh);
 	}
 
 	fh_put(&resfh);
@@ -424,11 +435,12 @@ nfsd4_create(struct svc_rqst *rqstp, str
 }
 
 static inline __be32
-nfsd4_getattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_getattr *getattr)
+nfsd4_getattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	      struct nfsd4_getattr *getattr)
 {
 	__be32 status;
 
-	status = fh_verify(rqstp, current_fh, 0, MAY_NOP);
+	status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
 	if (status)
 		return status;
 
@@ -438,26 +450,27 @@ nfsd4_getattr(struct svc_rqst *rqstp, st
 	getattr->ga_bmval[0] &= NFSD_SUPPORTED_ATTRS_WORD0;
 	getattr->ga_bmval[1] &= NFSD_SUPPORTED_ATTRS_WORD1;
 
-	getattr->ga_fhp = current_fh;
+	getattr->ga_fhp = &cstate->current_fh;
 	return nfs_ok;
 }
 
 static inline __be32
-nfsd4_link(struct svc_rqst *rqstp, struct svc_fh *current_fh,
-	   struct svc_fh *save_fh, struct nfsd4_link *link)
+nfsd4_link(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	   struct nfsd4_link *link)
 {
 	__be32 status = nfserr_nofilehandle;
 
-	if (!save_fh->fh_dentry)
+	if (!cstate->save_fh.fh_dentry)
 		return status;
-	status = nfsd_link(rqstp, current_fh, link->li_name, link->li_namelen, save_fh);
+	status = nfsd_link(rqstp, &cstate->current_fh,
+			   link->li_name, link->li_namelen, &cstate->save_fh);
 	if (!status)
-		set_change_info(&link->li_cinfo, current_fh);
+		set_change_info(&link->li_cinfo, &cstate->current_fh);
 	return status;
 }
 
 static __be32
-nfsd4_lookupp(struct svc_rqst *rqstp, struct svc_fh *current_fh)
+nfsd4_lookupp(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate)
 {
 	struct svc_fh tmp_fh;
 	__be32 ret;
@@ -466,22 +479,27 @@ nfsd4_lookupp(struct svc_rqst *rqstp, st
 	if((ret = exp_pseudoroot(rqstp->rq_client, &tmp_fh,
 			      &rqstp->rq_chandle)) != 0)
 		return ret;
-	if (tmp_fh.fh_dentry == current_fh->fh_dentry) {
+	if (tmp_fh.fh_dentry == cstate->current_fh.fh_dentry) {
 		fh_put(&tmp_fh);
 		return nfserr_noent;
 	}
 	fh_put(&tmp_fh);
-	return nfsd_lookup(rqstp, current_fh, "..", 2, current_fh);
+	return nfsd_lookup(rqstp, &cstate->current_fh,
+			   "..", 2, &cstate->current_fh);
 }
 
 static inline __be32
-nfsd4_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lookup *lookup)
+nfsd4_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	     struct nfsd4_lookup *lookup)
 {
-	return nfsd_lookup(rqstp, current_fh, lookup->lo_name, lookup->lo_len, current_fh);
+	return nfsd_lookup(rqstp, &cstate->current_fh,
+			   lookup->lo_name, lookup->lo_len,
+			   &cstate->current_fh);
 }
 
 static inline __be32
-nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read)
+nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	   struct nfsd4_read *read)
 {
 	__be32 status;
 
@@ -493,7 +511,8 @@ nfsd4_read(struct svc_rqst *rqstp, struc
 
 	nfs4_lock_state();
 	/* check stateid */
-	if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid,
+	if ((status = nfs4_preprocess_stateid_op(&cstate->current_fh,
+				&read->rd_stateid,
 				CHECK_FH | RD_STATE, &read->rd_filp))) {
 		dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
 		goto out;
@@ -504,12 +523,13 @@ nfsd4_read(struct svc_rqst *rqstp, struc
 out:
 	nfs4_unlock_state();
 	read->rd_rqstp = rqstp;
-	read->rd_fhp = current_fh;
+	read->rd_fhp = &cstate->current_fh;
 	return status;
 }
 
 static inline __be32
-nfsd4_readdir(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readdir *readdir)
+nfsd4_readdir(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	      struct nfsd4_readdir *readdir)
 {
 	u64 cookie = readdir->rd_cookie;
 	static const nfs4_verifier zeroverf;
@@ -527,48 +547,51 @@ nfsd4_readdir(struct svc_rqst *rqstp, st
 		return nfserr_bad_cookie;
 
 	readdir->rd_rqstp = rqstp;
-	readdir->rd_fhp = current_fh;
+	readdir->rd_fhp = &cstate->current_fh;
 	return nfs_ok;
 }
 
 static inline __be32
-nfsd4_readlink(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_readlink *readlink)
+nfsd4_readlink(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	       struct nfsd4_readlink *readlink)
 {
 	readlink->rl_rqstp = rqstp;
-	readlink->rl_fhp = current_fh;
+	readlink->rl_fhp = &cstate->current_fh;
 	return nfs_ok;
 }
 
 static inline __be32
-nfsd4_remove(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_remove *remove)
+nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	     struct nfsd4_remove *remove)
 {
 	__be32 status;
 
 	if (nfs4_in_grace())
 		return nfserr_grace;
-	status = nfsd_unlink(rqstp, current_fh, 0, remove->rm_name, remove->rm_namelen);
+	status = nfsd_unlink(rqstp, &cstate->current_fh, 0,
+			     remove->rm_name, remove->rm_namelen);
 	if (status == nfserr_symlink)
 		return nfserr_notdir;
 	if (!status) {
-		fh_unlock(current_fh);
-		set_change_info(&remove->rm_cinfo, current_fh);
+		fh_unlock(&cstate->current_fh);
+		set_change_info(&remove->rm_cinfo, &cstate->current_fh);
 	}
 	return status;
 }
 
 static inline __be32
-nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh,
-	     struct svc_fh *save_fh, struct nfsd4_rename *rename)
+nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	     struct nfsd4_rename *rename)
 {
 	__be32 status = nfserr_nofilehandle;
 
-	if (!save_fh->fh_dentry)
+	if (!cstate->save_fh.fh_dentry)
 		return status;
-	if (nfs4_in_grace() && !(save_fh->fh_export->ex_flags
+	if (nfs4_in_grace() && !(cstate->save_fh.fh_export->ex_flags
 					& NFSEXP_NOSUBTREECHECK))
 		return nfserr_grace;
-	status = nfsd_rename(rqstp, save_fh, rename->rn_sname,
-			     rename->rn_snamelen, current_fh,
+	status = nfsd_rename(rqstp, &cstate->save_fh, rename->rn_sname,
+			     rename->rn_snamelen, &cstate->current_fh,
 			     rename->rn_tname, rename->rn_tnamelen);
 
 	/* the underlying filesystem returns different error's than required
@@ -576,27 +599,28 @@ nfsd4_rename(struct svc_rqst *rqstp, str
 	if (status == nfserr_isdir)
 		status = nfserr_exist;
 	else if ((status == nfserr_notdir) &&
-                  (S_ISDIR(save_fh->fh_dentry->d_inode->i_mode) &&
-                   S_ISDIR(current_fh->fh_dentry->d_inode->i_mode)))
+                  (S_ISDIR(cstate->save_fh.fh_dentry->d_inode->i_mode) &&
+                   S_ISDIR(cstate->current_fh.fh_dentry->d_inode->i_mode)))
 		status = nfserr_exist;
 	else if (status == nfserr_symlink)
 		status = nfserr_notdir;
 
 	if (!status) {
-		set_change_info(&rename->rn_sinfo, current_fh);
-		set_change_info(&rename->rn_tinfo, save_fh);
+		set_change_info(&rename->rn_sinfo, &cstate->current_fh);
+		set_change_info(&rename->rn_tinfo, &cstate->save_fh);
 	}
 	return status;
 }
 
 static inline __be32
-nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_setattr *setattr)
+nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	      struct nfsd4_setattr *setattr)
 {
 	__be32 status = nfs_ok;
 
 	if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
 		nfs4_lock_state();
-		status = nfs4_preprocess_stateid_op(current_fh,
+		status = nfs4_preprocess_stateid_op(&cstate->current_fh,
 			&setattr->sa_stateid, CHECK_FH | WR_STATE, NULL);
 		nfs4_unlock_state();
 		if (status) {
@@ -606,16 +630,18 @@ nfsd4_setattr(struct svc_rqst *rqstp, st
 	}
 	status = nfs_ok;
 	if (setattr->sa_acl != NULL)
-		status = nfsd4_set_nfs4_acl(rqstp, current_fh, setattr->sa_acl);
+		status = nfsd4_set_nfs4_acl(rqstp, &cstate->current_fh,
+					    setattr->sa_acl);
 	if (status)
 		return status;
-	status = nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr,
+	status = nfsd_setattr(rqstp, &cstate->current_fh, &setattr->sa_iattr,
 				0, (time_t)0);
 	return status;
 }
 
 static inline __be32
-nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_write *write)
+nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	    struct nfsd4_write *write)
 {
 	stateid_t *stateid = &write->wr_stateid;
 	struct file *filp = NULL;
@@ -628,7 +654,7 @@ nfsd4_write(struct svc_rqst *rqstp, stru
 		return nfserr_inval;
 
 	nfs4_lock_state();
-	status = nfs4_preprocess_stateid_op(current_fh, stateid,
+	status = nfs4_preprocess_stateid_op(&cstate->current_fh, stateid,
 					CHECK_FH | WR_STATE, &filp);
 	if (filp)
 		get_file(filp);
@@ -645,9 +671,9 @@ nfsd4_write(struct svc_rqst *rqstp, stru
 	*p++ = nfssvc_boot.tv_sec;
 	*p++ = nfssvc_boot.tv_usec;
 
-	status =  nfsd_write(rqstp, current_fh, filp, write->wr_offset,
-			rqstp->rq_vec, write->wr_vlen, write->wr_buflen,
-			&write->wr_how_written);
+	status =  nfsd_write(rqstp, &cstate->current_fh, filp,
+			     write->wr_offset, rqstp->rq_vec, write->wr_vlen,
+			     write->wr_buflen, &write->wr_how_written);
 	if (filp)
 		fput(filp);
 
@@ -662,13 +688,14 @@ nfsd4_write(struct svc_rqst *rqstp, stru
  * to NFS_OK after the call; NVERIFY by mapping NFSERR_NOT_SAME to NFS_OK.
  */
 static __be32
-nfsd4_verify(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_verify *verify)
+nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	     struct nfsd4_verify *verify)
 {
 	__be32 *buf, *p;
 	int count;
 	__be32 status;
 
-	status = fh_verify(rqstp, current_fh, 0, MAY_NOP);
+	status = fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
 	if (status)
 		return status;
 
@@ -689,8 +716,9 @@ nfsd4_verify(struct svc_rqst *rqstp, str
 	if (!buf)
 		return nfserr_resource;
 
-	status = nfsd4_encode_fattr(current_fh, current_fh->fh_export,
-				    current_fh->fh_dentry, buf,
+	status = nfsd4_encode_fattr(&cstate->current_fh,
+				    cstate->current_fh.fh_export,
+				    cstate->current_fh.fh_dentry, buf,
 				    &count, verify->ve_bmval,
 				    rqstp);
 
@@ -727,6 +755,26 @@ static inline void nfsd4_increment_op_st
 		nfsdstats.nfs4_opcount[opnum]++;
 }
 
+static void cstate_free(struct nfsd4_compound_state *cstate)
+{
+	if (cstate == NULL)
+		return;
+	fh_put(&cstate->current_fh);
+	fh_put(&cstate->save_fh);
+	kfree(cstate);
+}
+
+static struct nfsd4_compound_state *cstate_alloc(void)
+{
+	struct nfsd4_compound_state *cstate;
+
+	cstate = kmalloc(sizeof(struct nfsd4_compound_state), GFP_KERNEL);
+	if (cstate == NULL)
+		return NULL;
+	fh_init(&cstate->current_fh, NFS4_FHSIZE);
+	fh_init(&cstate->save_fh, NFS4_FHSIZE);
+	return cstate;
+}
 
 /*
  * COMPOUND call.
@@ -737,21 +785,15 @@ nfsd4_proc_compound(struct svc_rqst *rqs
 		    struct nfsd4_compoundres *resp)
 {
 	struct nfsd4_op	*op;
-	struct svc_fh	*current_fh = NULL;
-	struct svc_fh	*save_fh = NULL;
+	struct nfsd4_compound_state *cstate = NULL;
 	struct nfs4_stateowner *replay_owner = NULL;
 	int		slack_bytes;
 	__be32		status;
 
 	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)
+	cstate = cstate_alloc();
+	if (cstate == 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;
@@ -802,7 +844,7 @@ nfsd4_proc_compound(struct svc_rqst *rqs
 		* SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH
 		* require a valid current filehandle
 		*/
-		if (!current_fh->fh_dentry) {
+		if (!cstate->current_fh.fh_dentry) {
 			if (!((op->opnum == OP_PUTFH) ||
 			      (op->opnum == OP_PUTROOTFH) ||
 			      (op->opnum == OP_SETCLIENTID) ||
@@ -817,7 +859,7 @@ nfsd4_proc_compound(struct svc_rqst *rqs
 		/* Check must be done at start of each operation, except
 		 * for GETATTR and ops not listed as returning NFS4ERR_MOVED
 		 */
-		else if (current_fh->fh_export->ex_fslocs.migrated &&
+		else if (cstate->current_fh.fh_export->ex_fslocs.migrated &&
 			 !((op->opnum == OP_GETATTR) ||
 			   (op->opnum == OP_PUTROOTFH) ||
 			   (op->opnum == OP_PUTPUBFH) ||
@@ -829,90 +871,110 @@ nfsd4_proc_compound(struct svc_rqst *rqs
 		}
 		switch (op->opnum) {
 		case OP_ACCESS:
-			op->status = nfsd4_access(rqstp, current_fh, &op->u.access);
+			op->status = nfsd4_access(rqstp, cstate,
+						  &op->u.access);
 			break;
 		case OP_CLOSE:
-			op->status = nfsd4_close(rqstp, current_fh, &op->u.close, &replay_owner);
+			op->status = nfsd4_close(rqstp, cstate,
+						 &op->u.close, &replay_owner);
 			break;
 		case OP_COMMIT:
-			op->status = nfsd4_commit(rqstp, current_fh, &op->u.commit);
+			op->status = nfsd4_commit(rqstp, cstate,
+						  &op->u.commit);
 			break;
 		case OP_CREATE:
-			op->status = nfsd4_create(rqstp, current_fh, &op->u.create);
+			op->status = nfsd4_create(rqstp, cstate,
+						  &op->u.create);
 			break;
 		case OP_DELEGRETURN:
-			op->status = nfsd4_delegreturn(rqstp, current_fh, &op->u.delegreturn);
+			op->status = nfsd4_delegreturn(rqstp, cstate,
+						       &op->u.delegreturn);
 			break;
 		case OP_GETATTR:
-			op->status = nfsd4_getattr(rqstp, current_fh, &op->u.getattr);
+			op->status = nfsd4_getattr(rqstp, cstate,
+						   &op->u.getattr);
 			break;
 		case OP_GETFH:
-			op->status = nfsd4_getfh(current_fh, &op->u.getfh);
+			op->status = nfsd4_getfh(cstate, &op->u.getfh);
 			break;
 		case OP_LINK:
-			op->status = nfsd4_link(rqstp, current_fh, save_fh, &op->u.link);
+			op->status = nfsd4_link(rqstp, cstate, &op->u.link);
 			break;
 		case OP_LOCK:
-			op->status = nfsd4_lock(rqstp, current_fh, &op->u.lock, &replay_owner);
+			op->status = nfsd4_lock(rqstp, cstate, &op->u.lock,
+						&replay_owner);
 			break;
 		case OP_LOCKT:
-			op->status = nfsd4_lockt(rqstp, current_fh, &op->u.lockt);
+			op->status = nfsd4_lockt(rqstp, cstate, &op->u.lockt);
 			break;
 		case OP_LOCKU:
-			op->status = nfsd4_locku(rqstp, current_fh, &op->u.locku, &replay_owner);
+			op->status = nfsd4_locku(rqstp, cstate, &op->u.locku,
+						 &replay_owner);
 			break;
 		case OP_LOOKUP:
-			op->status = nfsd4_lookup(rqstp, current_fh, &op->u.lookup);
+			op->status = nfsd4_lookup(rqstp, cstate,
+						  &op->u.lookup);
 			break;
 		case OP_LOOKUPP:
-			op->status = nfsd4_lookupp(rqstp, current_fh);
+			op->status = nfsd4_lookupp(rqstp, cstate);
 			break;
 		case OP_NVERIFY:
-			op->status = nfsd4_verify(rqstp, current_fh, &op->u.nverify);
+			op->status = nfsd4_verify(rqstp, cstate,
+						  &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, &replay_owner);
+			op->status = nfsd4_open(rqstp, cstate,
+						&op->u.open, &replay_owner);
 			break;
 		case OP_OPEN_CONFIRM:
-			op->status = nfsd4_open_confirm(rqstp, current_fh, &op->u.open_confirm, &replay_owner);
+			op->status = nfsd4_open_confirm(rqstp, cstate,
+							&op->u.open_confirm,
+							&replay_owner);
 			break;
 		case OP_OPEN_DOWNGRADE:
-			op->status = nfsd4_open_downgrade(rqstp, current_fh, &op->u.open_downgrade, &replay_owner);
+			op->status = nfsd4_open_downgrade(rqstp, cstate,
+							 &op->u.open_downgrade,
+							 &replay_owner);
 			break;
 		case OP_PUTFH:
-			op->status = nfsd4_putfh(rqstp, current_fh, &op->u.putfh);
+			op->status = nfsd4_putfh(rqstp, cstate, &op->u.putfh);
 			break;
 		case OP_PUTROOTFH:
-			op->status = nfsd4_putrootfh(rqstp, current_fh);
+			op->status = nfsd4_putrootfh(rqstp, cstate);
 			break;
 		case OP_READ:
-			op->status = nfsd4_read(rqstp, current_fh, &op->u.read);
+			op->status = nfsd4_read(rqstp, cstate, &op->u.read);
 			break;
 		case OP_READDIR:
-			op->status = nfsd4_readdir(rqstp, current_fh, &op->u.readdir);
+			op->status = nfsd4_readdir(rqstp, cstate,
+						   &op->u.readdir);
 			break;
 		case OP_READLINK:
-			op->status = nfsd4_readlink(rqstp, current_fh, &op->u.readlink);
+			op->status = nfsd4_readlink(rqstp, cstate,
+						    &op->u.readlink);
 			break;
 		case OP_REMOVE:
-			op->status = nfsd4_remove(rqstp, current_fh, &op->u.remove);
+			op->status = nfsd4_remove(rqstp, cstate,
+						  &op->u.remove);
 			break;
 		case OP_RENAME:
-			op->status = nfsd4_rename(rqstp, current_fh, save_fh, &op->u.rename);
+			op->status = nfsd4_rename(rqstp, cstate,
+						  &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(cstate);
 			break;
 		case OP_SAVEFH:
-			op->status = nfsd4_savefh(current_fh, save_fh);
+			op->status = nfsd4_savefh(cstate);
 			break;
 		case OP_SETATTR:
-			op->status = nfsd4_setattr(rqstp, current_fh, &op->u.setattr);
+			op->status = nfsd4_setattr(rqstp, cstate,
+						   &op->u.setattr);
 			break;
 		case OP_SETCLIENTID:
 			op->status = nfsd4_setclientid(rqstp, &op->u.setclientid);
@@ -921,12 +983,13 @@ nfsd4_proc_compound(struct svc_rqst *rqs
 			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, cstate,
+						  &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, cstate, &op->u.write);
 			break;
 		case OP_RELEASE_LOCKOWNER:
 			op->status = nfsd4_release_lockowner(rqstp, &op->u.release_lockowner);
@@ -958,12 +1021,7 @@ encode_op:
 
 out:
 	nfsd4_release_compoundargs(args);
-	if (current_fh)
-		fh_put(current_fh);
-	kfree(current_fh);
-	if (save_fh)
-		fh_put(save_fh);
-	kfree(save_fh);
+	cstate_free(cstate);
 	return status;
 }
 

diff .prev/fs/nfsd/nfs4state.c ./fs/nfsd/nfs4state.c
--- .prev/fs/nfsd/nfs4state.c	2006-12-08 12:07:57.000000000 +1100
+++ ./fs/nfsd/nfs4state.c	2006-12-08 12:09:27.000000000 +1100
@@ -2242,24 +2242,26 @@ check_replay:
 }
 
 __be32
-nfsd4_open_confirm(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_confirm *oc, struct nfs4_stateowner **replay_owner)
+nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+		   struct nfsd4_open_confirm *oc,
+		   struct nfs4_stateowner **replay_owner)
 {
 	__be32 status;
 	struct nfs4_stateowner *sop;
 	struct nfs4_stateid *stp;
 
 	dprintk("NFSD: nfsd4_open_confirm on file %.*s\n",
-			(int)current_fh->fh_dentry->d_name.len,
-			current_fh->fh_dentry->d_name.name);
+			(int)cstate->current_fh.fh_dentry->d_name.len,
+			cstate->current_fh.fh_dentry->d_name.name);
 
-	status = fh_verify(rqstp, current_fh, S_IFREG, 0);
+	status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0);
 	if (status)
 		return status;
 
 	nfs4_lock_state();
 
-	if ((status = nfs4_preprocess_seqid_op(current_fh, oc->oc_seqid,
-					&oc->oc_req_stateid,
+	if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+					oc->oc_seqid, &oc->oc_req_stateid,
 					CHECK_FH | CONFIRM | OPEN_STATE,
 					&oc->oc_stateowner, &stp, NULL)))
 		goto out; 
@@ -2311,22 +2313,26 @@ reset_union_bmap_deny(unsigned long deny
 }
 
 __be32
-nfsd4_open_downgrade(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open_downgrade *od, struct nfs4_stateowner **replay_owner)
+nfsd4_open_downgrade(struct svc_rqst *rqstp,
+		     struct nfsd4_compound_state *cstate,
+		     struct nfsd4_open_downgrade *od,
+		     struct nfs4_stateowner **replay_owner)
 {
 	__be32 status;
 	struct nfs4_stateid *stp;
 	unsigned int share_access;
 
 	dprintk("NFSD: nfsd4_open_downgrade on file %.*s\n", 
-			(int)current_fh->fh_dentry->d_name.len,
-			current_fh->fh_dentry->d_name.name);
+			(int)cstate->current_fh.fh_dentry->d_name.len,
+			cstate->current_fh.fh_dentry->d_name.name);
 
 	if (!access_valid(od->od_share_access)
 			|| !deny_valid(od->od_share_deny))
 		return nfserr_inval;
 
 	nfs4_lock_state();
-	if ((status = nfs4_preprocess_seqid_op(current_fh, od->od_seqid, 
+	if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+					od->od_seqid,
 					&od->od_stateid, 
 					CHECK_FH | OPEN_STATE, 
 					&od->od_stateowner, &stp, NULL)))
@@ -2366,18 +2372,20 @@ out:
  * nfs4_unlock_state() called after encode
  */
 __be32
-nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_close *close, struct nfs4_stateowner **replay_owner)
+nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	    struct nfsd4_close *close, struct nfs4_stateowner **replay_owner)
 {
 	__be32 status;
 	struct nfs4_stateid *stp;
 
 	dprintk("NFSD: nfsd4_close on file %.*s\n", 
-			(int)current_fh->fh_dentry->d_name.len,
-			current_fh->fh_dentry->d_name.name);
+			(int)cstate->current_fh.fh_dentry->d_name.len,
+			cstate->current_fh.fh_dentry->d_name.name);
 
 	nfs4_lock_state();
 	/* check close_lru for replay */
-	if ((status = nfs4_preprocess_seqid_op(current_fh, close->cl_seqid, 
+	if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
+					close->cl_seqid,
 					&close->cl_stateid, 
 					CHECK_FH | OPEN_STATE | CLOSE_STATE,
 					&close->cl_stateowner, &stp, NULL)))
@@ -2405,15 +2413,17 @@ out:
 }
 
 __be32
-nfsd4_delegreturn(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_delegreturn *dr)
+nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+		  struct nfsd4_delegreturn *dr)
 {
 	__be32 status;
 
-	if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0)))
+	if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0)))
 		goto out;
 
 	nfs4_lock_state();
-	status = nfs4_preprocess_stateid_op(current_fh, &dr->dr_stateid, DELEG_RET, NULL);
+	status = nfs4_preprocess_stateid_op(&cstate->current_fh,
+					    &dr->dr_stateid, DELEG_RET, NULL);
 	nfs4_unlock_state();
 out:
 	return status;
@@ -2636,7 +2646,8 @@ check_lock_length(u64 offset, u64 length
  *  LOCK operation 
  */
 __be32
-nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock *lock, struct nfs4_stateowner **replay_owner)
+nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	   struct nfsd4_lock *lock, struct nfs4_stateowner **replay_owner)
 {
 	struct nfs4_stateowner *open_sop = NULL;
 	struct nfs4_stateowner *lock_sop = NULL;
@@ -2655,7 +2666,8 @@ nfsd4_lock(struct svc_rqst *rqstp, struc
 	if (check_lock_length(lock->lk_offset, lock->lk_length))
 		 return nfserr_inval;
 
-	if ((status = fh_verify(rqstp, current_fh, S_IFREG, MAY_LOCK))) {
+	if ((status = fh_verify(rqstp, &cstate->current_fh,
+				S_IFREG, MAY_LOCK))) {
 		dprintk("NFSD: nfsd4_lock: permission denied!\n");
 		return status;
 	}
@@ -2676,7 +2688,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struc
 			goto out;
 
 		/* validate and update open stateid and open seqid */
-		status = nfs4_preprocess_seqid_op(current_fh, 
+		status = nfs4_preprocess_seqid_op(&cstate->current_fh,
 				        lock->lk_new_open_seqid,
 		                        &lock->lk_new_open_stateid,
 		                        CHECK_FH | OPEN_STATE,
@@ -2703,7 +2715,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struc
 			goto out;
 	} else {
 		/* lock (lock owner + lock stateid) already exists */
-		status = nfs4_preprocess_seqid_op(current_fh,
+		status = nfs4_preprocess_seqid_op(&cstate->current_fh,
 				       lock->lk_old_lock_seqid, 
 				       &lock->lk_old_lock_stateid, 
 				       CHECK_FH | LOCK_STATE, 
@@ -2795,7 +2807,8 @@ out:
  * LOCKT operation
  */
 __be32
-nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lockt *lockt)
+nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	    struct nfsd4_lockt *lockt)
 {
 	struct inode *inode;
 	struct file file;
@@ -2816,14 +2829,14 @@ nfsd4_lockt(struct svc_rqst *rqstp, stru
 	if (STALE_CLIENTID(&lockt->lt_clientid))
 		goto out;
 
-	if ((status = fh_verify(rqstp, current_fh, S_IFREG, 0))) {
+	if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0))) {
 		dprintk("NFSD: nfsd4_lockt: fh_verify() failed!\n");
 		if (status == nfserr_symlink)
 			status = nfserr_inval;
 		goto out;
 	}
 
-	inode = current_fh->fh_dentry->d_inode;
+	inode = cstate->current_fh.fh_dentry->d_inode;
 	locks_init_lock(&file_lock);
 	switch (lockt->lt_type) {
 		case NFS4_READ_LT:
@@ -2862,7 +2875,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, stru
 	 * only the dentry:inode set.
 	 */
 	memset(&file, 0, sizeof (struct file));
-	file.f_path.dentry = current_fh->fh_dentry;
+	file.f_path.dentry = cstate->current_fh.fh_dentry;
 
 	status = nfs_ok;
 	if (posix_test_lock(&file, &file_lock, &conflock)) {
@@ -2875,7 +2888,8 @@ out:
 }
 
 __be32
-nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_locku *locku, struct nfs4_stateowner **replay_owner)
+nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	    struct nfsd4_locku *locku, struct nfs4_stateowner **replay_owner)
 {
 	struct nfs4_stateid *stp;
 	struct file *filp = NULL;
@@ -2892,7 +2906,7 @@ nfsd4_locku(struct svc_rqst *rqstp, stru
 
 	nfs4_lock_state();
 									        
-	if ((status = nfs4_preprocess_seqid_op(current_fh, 
+	if ((status = nfs4_preprocess_seqid_op(&cstate->current_fh,
 					locku->lu_seqid, 
 					&locku->lu_stateid, 
 					CHECK_FH | LOCK_STATE, 

diff .prev/include/linux/nfsd/xdr4.h ./include/linux/nfsd/xdr4.h
--- .prev/include/linux/nfsd/xdr4.h	2006-12-08 12:07:22.000000000 +1100
+++ ./include/linux/nfsd/xdr4.h	2006-12-08 12:09:27.000000000 +1100
@@ -44,6 +44,11 @@
 #define NFSD4_MAX_TAGLEN	128
 #define XDR_LEN(n)                     (((n) + 3) & ~3)
 
+struct nfsd4_compound_state {
+	struct svc_fh current_fh;
+	struct svc_fh save_fh;
+};
+
 struct nfsd4_change_info {
 	u32		atomic;
 	u32		before_ctime_sec;
@@ -437,20 +442,23 @@ extern __be32 nfsd4_process_open1(struct
 extern __be32 nfsd4_process_open2(struct svc_rqst *rqstp,
 		struct svc_fh *current_fh, struct nfsd4_open *open);
 extern __be32 nfsd4_open_confirm(struct svc_rqst *rqstp,
-		struct svc_fh *current_fh, struct nfsd4_open_confirm *oc,
+		struct nfsd4_compound_state *, struct nfsd4_open_confirm *oc,
 		struct nfs4_stateowner **);
-extern __be32 nfsd4_close(struct svc_rqst *rqstp, struct svc_fh *current_fh,
+extern __be32 nfsd4_close(struct svc_rqst *rqstp,
+		struct nfsd4_compound_state *,
 		struct nfsd4_close *close,
 		struct nfs4_stateowner **replay_owner);
 extern __be32 nfsd4_open_downgrade(struct svc_rqst *rqstp,
-		struct svc_fh *current_fh, struct nfsd4_open_downgrade *od,
+		struct nfsd4_compound_state *, struct nfsd4_open_downgrade *od,
 		struct nfs4_stateowner **replay_owner);
-extern __be32 nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh,
+extern __be32 nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *,
 		struct nfsd4_lock *lock,
 		struct nfs4_stateowner **replay_owner);
-extern __be32 nfsd4_lockt(struct svc_rqst *rqstp, struct svc_fh *current_fh,
+extern __be32 nfsd4_lockt(struct svc_rqst *rqstp,
+		struct nfsd4_compound_state *,
 		struct nfsd4_lockt *lockt);
-extern __be32 nfsd4_locku(struct svc_rqst *rqstp, struct svc_fh *current_fh,
+extern __be32 nfsd4_locku(struct svc_rqst *rqstp,
+		struct nfsd4_compound_state *,
 		struct nfsd4_locku *locku,
 		struct nfs4_stateowner **replay_owner);
 extern __be32
@@ -458,7 +466,7 @@ nfsd4_release_lockowner(struct svc_rqst 
 		struct nfsd4_release_lockowner *rlockowner);
 extern void nfsd4_release_compoundargs(struct nfsd4_compoundargs *);
 extern __be32 nfsd4_delegreturn(struct svc_rqst *rqstp,
-		struct svc_fh *current_fh, struct nfsd4_delegreturn *dr);
+		struct nfsd4_compound_state *, struct nfsd4_delegreturn *dr);
 #endif
 
 /*

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 010 of 18] knfsd: nfsd4: remove spurious replay_owner check
  2006-12-08  1:13 [PATCH 000 of 18] knfsd: Introduction - NFSv4 updates and more NeilBrown
                   ` (8 preceding siblings ...)
  2006-12-08  1:14 ` [PATCH 009 of 18] knfsd: nfsd4: pass saved and current fh together into nfsd4 operations NeilBrown
@ 2006-12-08  1:14 ` NeilBrown
  2006-12-08  1:14 ` [PATCH 011 of 18] knfsd: nfsd4: move replay_owner to cstate NeilBrown
                   ` (7 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: NeilBrown @ 2006-12-08  1:14 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel


From: J.Bruce Fields <bfields@fieldses.org>

OK, this is embarassing--I've even looked back at the history, and cannot
for the life of me figure out why I added this check.

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./fs/nfsd/nfs4proc.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff .prev/fs/nfsd/nfs4proc.c ./fs/nfsd/nfs4proc.c
--- .prev/fs/nfsd/nfs4proc.c	2006-12-08 12:09:27.000000000 +1100
+++ ./fs/nfsd/nfs4proc.c	2006-12-08 12:09:27.000000000 +1100
@@ -1008,7 +1008,7 @@ encode_op:
 			nfsd4_encode_operation(resp, op);
 			status = op->status;
 		}
-		if (replay_owner && (replay_owner != (void *)(-1))) {
+		if (replay_owner) {
 			nfs4_put_stateowner(replay_owner);
 			replay_owner = NULL;
 		}

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 011 of 18] knfsd: nfsd4: move replay_owner to cstate
  2006-12-08  1:13 [PATCH 000 of 18] knfsd: Introduction - NFSv4 updates and more NeilBrown
                   ` (9 preceding siblings ...)
  2006-12-08  1:14 ` [PATCH 010 of 18] knfsd: nfsd4: remove spurious replay_owner check NeilBrown
@ 2006-12-08  1:14 ` NeilBrown
  2006-12-08  1:14 ` [PATCH 012 of 18] knfsd: nfsd4: don't inline nfsd4 compound op functions NeilBrown
                   ` (6 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: NeilBrown @ 2006-12-08  1:14 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel


From: J.Bruce Fields <bfields@fieldses.org>

Tuck away the replay_owner in the cstate while we're at it.

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./fs/nfsd/nfs4proc.c        |   31 ++++++++++++++-----------------
 ./fs/nfsd/nfs4state.c       |   22 ++++++++++------------
 ./include/linux/nfsd/xdr4.h |   17 +++++++----------
 3 files changed, 31 insertions(+), 39 deletions(-)

diff .prev/fs/nfsd/nfs4proc.c ./fs/nfsd/nfs4proc.c
--- .prev/fs/nfsd/nfs4proc.c	2006-12-08 12:09:27.000000000 +1100
+++ ./fs/nfsd/nfs4proc.c	2006-12-08 12:09:27.000000000 +1100
@@ -163,7 +163,7 @@ do_open_fhandle(struct svc_rqst *rqstp, 
 
 static inline __be32
 nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
-	   struct nfsd4_open *open, struct nfs4_stateowner **replay_owner)
+	   struct nfsd4_open *open)
 {
 	__be32 status;
 	dprintk("NFSD: nfsd4_open filename %.*s op_stateowner %p\n",
@@ -255,7 +255,7 @@ nfsd4_open(struct svc_rqst *rqstp, struc
 out:
 	if (open->op_stateowner) {
 		nfs4_get_stateowner(open->op_stateowner);
-		*replay_owner = open->op_stateowner;
+		cstate->replay_owner = open->op_stateowner;
 	}
 	nfs4_unlock_state();
 	return status;
@@ -761,6 +761,7 @@ static void cstate_free(struct nfsd4_com
 		return;
 	fh_put(&cstate->current_fh);
 	fh_put(&cstate->save_fh);
+	BUG_ON(cstate->replay_owner);
 	kfree(cstate);
 }
 
@@ -773,6 +774,7 @@ static struct nfsd4_compound_state *csta
 		return NULL;
 	fh_init(&cstate->current_fh, NFS4_FHSIZE);
 	fh_init(&cstate->save_fh, NFS4_FHSIZE);
+	cstate->replay_owner = NULL;
 	return cstate;
 }
 
@@ -786,7 +788,6 @@ nfsd4_proc_compound(struct svc_rqst *rqs
 {
 	struct nfsd4_op	*op;
 	struct nfsd4_compound_state *cstate = NULL;
-	struct nfs4_stateowner *replay_owner = NULL;
 	int		slack_bytes;
 	__be32		status;
 
@@ -876,7 +877,7 @@ nfsd4_proc_compound(struct svc_rqst *rqs
 			break;
 		case OP_CLOSE:
 			op->status = nfsd4_close(rqstp, cstate,
-						 &op->u.close, &replay_owner);
+						 &op->u.close);
 			break;
 		case OP_COMMIT:
 			op->status = nfsd4_commit(rqstp, cstate,
@@ -901,15 +902,13 @@ nfsd4_proc_compound(struct svc_rqst *rqs
 			op->status = nfsd4_link(rqstp, cstate, &op->u.link);
 			break;
 		case OP_LOCK:
-			op->status = nfsd4_lock(rqstp, cstate, &op->u.lock,
-						&replay_owner);
+			op->status = nfsd4_lock(rqstp, cstate, &op->u.lock);
 			break;
 		case OP_LOCKT:
 			op->status = nfsd4_lockt(rqstp, cstate, &op->u.lockt);
 			break;
 		case OP_LOCKU:
-			op->status = nfsd4_locku(rqstp, cstate, &op->u.locku,
-						 &replay_owner);
+			op->status = nfsd4_locku(rqstp, cstate, &op->u.locku);
 			break;
 		case OP_LOOKUP:
 			op->status = nfsd4_lookup(rqstp, cstate,
@@ -926,17 +925,15 @@ nfsd4_proc_compound(struct svc_rqst *rqs
 			break;
 		case OP_OPEN:
 			op->status = nfsd4_open(rqstp, cstate,
-						&op->u.open, &replay_owner);
+						&op->u.open);
 			break;
 		case OP_OPEN_CONFIRM:
 			op->status = nfsd4_open_confirm(rqstp, cstate,
-							&op->u.open_confirm,
-							&replay_owner);
+							&op->u.open_confirm);
 			break;
 		case OP_OPEN_DOWNGRADE:
 			op->status = nfsd4_open_downgrade(rqstp, cstate,
-							 &op->u.open_downgrade,
-							 &replay_owner);
+							&op->u.open_downgrade);
 			break;
 		case OP_PUTFH:
 			op->status = nfsd4_putfh(rqstp, cstate, &op->u.putfh);
@@ -1001,16 +998,16 @@ nfsd4_proc_compound(struct svc_rqst *rqs
 
 encode_op:
 		if (op->status == nfserr_replay_me) {
-			op->replay = &replay_owner->so_replay;
+			op->replay = &cstate->replay_owner->so_replay;
 			nfsd4_encode_replay(resp, op);
 			status = op->status = op->replay->rp_status;
 		} else {
 			nfsd4_encode_operation(resp, op);
 			status = op->status;
 		}
-		if (replay_owner) {
-			nfs4_put_stateowner(replay_owner);
-			replay_owner = NULL;
+		if (cstate->replay_owner) {
+			nfs4_put_stateowner(cstate->replay_owner);
+			cstate->replay_owner = NULL;
 		}
 		/* XXX Ugh, we need to get rid of this kind of special case: */
 		if (op->opnum == OP_READ && op->u.read.rd_filp)

diff .prev/fs/nfsd/nfs4state.c ./fs/nfsd/nfs4state.c
--- .prev/fs/nfsd/nfs4state.c	2006-12-08 12:09:27.000000000 +1100
+++ ./fs/nfsd/nfs4state.c	2006-12-08 12:09:27.000000000 +1100
@@ -2243,8 +2243,7 @@ check_replay:
 
 __be32
 nfsd4_open_confirm(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
-		   struct nfsd4_open_confirm *oc,
-		   struct nfs4_stateowner **replay_owner)
+		   struct nfsd4_open_confirm *oc)
 {
 	__be32 status;
 	struct nfs4_stateowner *sop;
@@ -2281,7 +2280,7 @@ nfsd4_open_confirm(struct svc_rqst *rqst
 out:
 	if (oc->oc_stateowner) {
 		nfs4_get_stateowner(oc->oc_stateowner);
-		*replay_owner = oc->oc_stateowner;
+		cstate->replay_owner = oc->oc_stateowner;
 	}
 	nfs4_unlock_state();
 	return status;
@@ -2315,8 +2314,7 @@ reset_union_bmap_deny(unsigned long deny
 __be32
 nfsd4_open_downgrade(struct svc_rqst *rqstp,
 		     struct nfsd4_compound_state *cstate,
-		     struct nfsd4_open_downgrade *od,
-		     struct nfs4_stateowner **replay_owner)
+		     struct nfsd4_open_downgrade *od)
 {
 	__be32 status;
 	struct nfs4_stateid *stp;
@@ -2362,7 +2360,7 @@ nfsd4_open_downgrade(struct svc_rqst *rq
 out:
 	if (od->od_stateowner) {
 		nfs4_get_stateowner(od->od_stateowner);
-		*replay_owner = od->od_stateowner;
+		cstate->replay_owner = od->od_stateowner;
 	}
 	nfs4_unlock_state();
 	return status;
@@ -2373,7 +2371,7 @@ out:
  */
 __be32
 nfsd4_close(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
-	    struct nfsd4_close *close, struct nfs4_stateowner **replay_owner)
+	    struct nfsd4_close *close)
 {
 	__be32 status;
 	struct nfs4_stateid *stp;
@@ -2406,7 +2404,7 @@ nfsd4_close(struct svc_rqst *rqstp, stru
 out:
 	if (close->cl_stateowner) {
 		nfs4_get_stateowner(close->cl_stateowner);
-		*replay_owner = close->cl_stateowner;
+		cstate->replay_owner = close->cl_stateowner;
 	}
 	nfs4_unlock_state();
 	return status;
@@ -2647,7 +2645,7 @@ check_lock_length(u64 offset, u64 length
  */
 __be32
 nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
-	   struct nfsd4_lock *lock, struct nfs4_stateowner **replay_owner)
+	   struct nfsd4_lock *lock)
 {
 	struct nfs4_stateowner *open_sop = NULL;
 	struct nfs4_stateowner *lock_sop = NULL;
@@ -2797,7 +2795,7 @@ out:
 		release_stateowner(lock_sop);
 	if (lock->lk_replay_owner) {
 		nfs4_get_stateowner(lock->lk_replay_owner);
-		*replay_owner = lock->lk_replay_owner;
+		cstate->replay_owner = lock->lk_replay_owner;
 	}
 	nfs4_unlock_state();
 	return status;
@@ -2889,7 +2887,7 @@ out:
 
 __be32
 nfsd4_locku(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
-	    struct nfsd4_locku *locku, struct nfs4_stateowner **replay_owner)
+	    struct nfsd4_locku *locku)
 {
 	struct nfs4_stateid *stp;
 	struct file *filp = NULL;
@@ -2947,7 +2945,7 @@ nfsd4_locku(struct svc_rqst *rqstp, stru
 out:
 	if (locku->lu_stateowner) {
 		nfs4_get_stateowner(locku->lu_stateowner);
-		*replay_owner = locku->lu_stateowner;
+		cstate->replay_owner = locku->lu_stateowner;
 	}
 	nfs4_unlock_state();
 	return status;

diff .prev/include/linux/nfsd/xdr4.h ./include/linux/nfsd/xdr4.h
--- .prev/include/linux/nfsd/xdr4.h	2006-12-08 12:09:27.000000000 +1100
+++ ./include/linux/nfsd/xdr4.h	2006-12-08 12:09:27.000000000 +1100
@@ -47,6 +47,7 @@
 struct nfsd4_compound_state {
 	struct svc_fh current_fh;
 	struct svc_fh save_fh;
+	struct nfs4_stateowner *replay_owner;
 };
 
 struct nfsd4_change_info {
@@ -442,25 +443,21 @@ extern __be32 nfsd4_process_open1(struct
 extern __be32 nfsd4_process_open2(struct svc_rqst *rqstp,
 		struct svc_fh *current_fh, struct nfsd4_open *open);
 extern __be32 nfsd4_open_confirm(struct svc_rqst *rqstp,
-		struct nfsd4_compound_state *, struct nfsd4_open_confirm *oc,
-		struct nfs4_stateowner **);
+		struct nfsd4_compound_state *, struct nfsd4_open_confirm *oc);
 extern __be32 nfsd4_close(struct svc_rqst *rqstp,
 		struct nfsd4_compound_state *,
-		struct nfsd4_close *close,
-		struct nfs4_stateowner **replay_owner);
+		struct nfsd4_close *close);
 extern __be32 nfsd4_open_downgrade(struct svc_rqst *rqstp,
-		struct nfsd4_compound_state *, struct nfsd4_open_downgrade *od,
-		struct nfs4_stateowner **replay_owner);
+		struct nfsd4_compound_state *,
+		struct nfsd4_open_downgrade *od);
 extern __be32 nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *,
-		struct nfsd4_lock *lock,
-		struct nfs4_stateowner **replay_owner);
+		struct nfsd4_lock *lock);
 extern __be32 nfsd4_lockt(struct svc_rqst *rqstp,
 		struct nfsd4_compound_state *,
 		struct nfsd4_lockt *lockt);
 extern __be32 nfsd4_locku(struct svc_rqst *rqstp,
 		struct nfsd4_compound_state *,
-		struct nfsd4_locku *locku,
-		struct nfs4_stateowner **replay_owner);
+		struct nfsd4_locku *locku);
 extern __be32
 nfsd4_release_lockowner(struct svc_rqst *rqstp,
 		struct nfsd4_release_lockowner *rlockowner);

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 012 of 18] knfsd: nfsd4: don't inline nfsd4 compound op functions
  2006-12-08  1:13 [PATCH 000 of 18] knfsd: Introduction - NFSv4 updates and more NeilBrown
                   ` (10 preceding siblings ...)
  2006-12-08  1:14 ` [PATCH 011 of 18] knfsd: nfsd4: move replay_owner to cstate NeilBrown
@ 2006-12-08  1:14 ` NeilBrown
  2006-12-08  1:14 ` [PATCH 013 of 18] knfsd: nfsd4: make verify and nverify wrappers NeilBrown
                   ` (5 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: NeilBrown @ 2006-12-08  1:14 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel


From: J.Bruce Fields <bfields@fieldses.org>

The inlining contributes to bloating the stack of nfsd4_compound, and
I want to change the compound op functions to function pointers anyway.

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./fs/nfsd/nfs4proc.c |   43 ++++++++++++++++++-------------------------
 1 file changed, 18 insertions(+), 25 deletions(-)

diff .prev/fs/nfsd/nfs4proc.c ./fs/nfsd/nfs4proc.c
--- .prev/fs/nfsd/nfs4proc.c	2006-12-08 12:09:27.000000000 +1100
+++ ./fs/nfsd/nfs4proc.c	2006-12-08 12:09:29.000000000 +1100
@@ -33,13 +33,6 @@
  *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Note: some routines in this file are just trivial wrappers
- * (e.g. nfsd4_lookup()) defined solely for the sake of consistent
- * naming.  Since all such routines have been declared "inline",
- * there shouldn't be any associated overhead.  At some point in
- * the future, I might inline these "by hand" to clean up a
- * little.
  */
 
 #include <linux/param.h>
@@ -161,7 +154,7 @@ do_open_fhandle(struct svc_rqst *rqstp, 
 }
 
 
-static inline __be32
+static __be32
 nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	   struct nfsd4_open *open)
 {
@@ -264,7 +257,7 @@ out:
 /*
  * filehandle-manipulating ops.
  */
-static inline __be32
+static __be32
 nfsd4_getfh(struct nfsd4_compound_state *cstate, struct svc_fh **getfh)
 {
 	if (!cstate->current_fh.fh_dentry)
@@ -274,7 +267,7 @@ nfsd4_getfh(struct nfsd4_compound_state 
 	return nfs_ok;
 }
 
-static inline __be32
+static __be32
 nfsd4_putfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	    struct nfsd4_putfh *putfh)
 {
@@ -285,7 +278,7 @@ nfsd4_putfh(struct svc_rqst *rqstp, stru
 	return fh_verify(rqstp, &cstate->current_fh, 0, MAY_NOP);
 }
 
-static inline __be32
+static __be32
 nfsd4_putrootfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate)
 {
 	__be32 status;
@@ -296,7 +289,7 @@ nfsd4_putrootfh(struct svc_rqst *rqstp, 
 	return status;
 }
 
-static inline __be32
+static __be32
 nfsd4_restorefh(struct nfsd4_compound_state *cstate)
 {
 	if (!cstate->save_fh.fh_dentry)
@@ -306,7 +299,7 @@ nfsd4_restorefh(struct nfsd4_compound_st
 	return nfs_ok;
 }
 
-static inline __be32
+static __be32
 nfsd4_savefh(struct nfsd4_compound_state *cstate)
 {
 	if (!cstate->current_fh.fh_dentry)
@@ -319,7 +312,7 @@ nfsd4_savefh(struct nfsd4_compound_state
 /*
  * misc nfsv4 ops
  */
-static inline __be32
+static __be32
 nfsd4_access(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	     struct nfsd4_access *access)
 {
@@ -331,7 +324,7 @@ nfsd4_access(struct svc_rqst *rqstp, str
 			   &access->ac_supported);
 }
 
-static inline __be32
+static __be32
 nfsd4_commit(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	     struct nfsd4_commit *commit)
 {
@@ -434,7 +427,7 @@ nfsd4_create(struct svc_rqst *rqstp, str
 	return status;
 }
 
-static inline __be32
+static __be32
 nfsd4_getattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	      struct nfsd4_getattr *getattr)
 {
@@ -454,7 +447,7 @@ nfsd4_getattr(struct svc_rqst *rqstp, st
 	return nfs_ok;
 }
 
-static inline __be32
+static __be32
 nfsd4_link(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	   struct nfsd4_link *link)
 {
@@ -488,7 +481,7 @@ nfsd4_lookupp(struct svc_rqst *rqstp, st
 			   "..", 2, &cstate->current_fh);
 }
 
-static inline __be32
+static __be32
 nfsd4_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	     struct nfsd4_lookup *lookup)
 {
@@ -497,7 +490,7 @@ nfsd4_lookup(struct svc_rqst *rqstp, str
 			   &cstate->current_fh);
 }
 
-static inline __be32
+static __be32
 nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	   struct nfsd4_read *read)
 {
@@ -527,7 +520,7 @@ out:
 	return status;
 }
 
-static inline __be32
+static __be32
 nfsd4_readdir(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	      struct nfsd4_readdir *readdir)
 {
@@ -551,7 +544,7 @@ nfsd4_readdir(struct svc_rqst *rqstp, st
 	return nfs_ok;
 }
 
-static inline __be32
+static __be32
 nfsd4_readlink(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	       struct nfsd4_readlink *readlink)
 {
@@ -560,7 +553,7 @@ nfsd4_readlink(struct svc_rqst *rqstp, s
 	return nfs_ok;
 }
 
-static inline __be32
+static __be32
 nfsd4_remove(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	     struct nfsd4_remove *remove)
 {
@@ -579,7 +572,7 @@ nfsd4_remove(struct svc_rqst *rqstp, str
 	return status;
 }
 
-static inline __be32
+static __be32
 nfsd4_rename(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	     struct nfsd4_rename *rename)
 {
@@ -612,7 +605,7 @@ nfsd4_rename(struct svc_rqst *rqstp, str
 	return status;
 }
 
-static inline __be32
+static __be32
 nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	      struct nfsd4_setattr *setattr)
 {
@@ -639,7 +632,7 @@ nfsd4_setattr(struct svc_rqst *rqstp, st
 	return status;
 }
 
-static inline __be32
+static __be32
 nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	    struct nfsd4_write *write)
 {

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 013 of 18] knfsd: nfsd4: make verify and nverify wrappers
  2006-12-08  1:13 [PATCH 000 of 18] knfsd: Introduction - NFSv4 updates and more NeilBrown
                   ` (11 preceding siblings ...)
  2006-12-08  1:14 ` [PATCH 012 of 18] knfsd: nfsd4: don't inline nfsd4 compound op functions NeilBrown
@ 2006-12-08  1:14 ` NeilBrown
  2006-12-08  1:14 ` [PATCH 014 of 18] knfsd: nfsd4: reorganize compound ops NeilBrown
                   ` (4 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: NeilBrown @ 2006-12-08  1:14 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel


From: J.Bruce Fields <bfields@fieldses.org>

Make wrappers for verify and nverify, for consistency with other ops.

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./fs/nfsd/nfs4proc.c |   28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)

diff .prev/fs/nfsd/nfs4proc.c ./fs/nfsd/nfs4proc.c
--- .prev/fs/nfsd/nfs4proc.c	2006-12-08 12:09:29.000000000 +1100
+++ ./fs/nfsd/nfs4proc.c	2006-12-08 12:09:30.000000000 +1100
@@ -681,7 +681,7 @@ nfsd4_write(struct svc_rqst *rqstp, stru
  * to NFS_OK after the call; NVERIFY by mapping NFSERR_NOT_SAME to NFS_OK.
  */
 static __be32
-nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+_nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	     struct nfsd4_verify *verify)
 {
 	__be32 *buf, *p;
@@ -733,6 +733,26 @@ out_kfree:
 	return status;
 }
 
+static __be32
+nfsd4_nverify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	      struct nfsd4_verify *verify)
+{
+	__be32 status;
+
+	status = _nfsd4_verify(rqstp, cstate, verify);
+	return status == nfserr_not_same ? nfs_ok : status;
+}
+
+static __be32
+nfsd4_verify(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	     struct nfsd4_verify *verify)
+{
+	__be32 status;
+
+	status = _nfsd4_verify(rqstp, cstate, verify);
+	return status == nfserr_same ? nfs_ok : status;
+}
+
 /*
  * NULL call.
  */
@@ -911,10 +931,8 @@ nfsd4_proc_compound(struct svc_rqst *rqs
 			op->status = nfsd4_lookupp(rqstp, cstate);
 			break;
 		case OP_NVERIFY:
-			op->status = nfsd4_verify(rqstp, cstate,
+			op->status = nfsd4_nverify(rqstp, cstate,
 						  &op->u.nverify);
-			if (op->status == nfserr_not_same)
-				op->status = nfs_ok;
 			break;
 		case OP_OPEN:
 			op->status = nfsd4_open(rqstp, cstate,
@@ -975,8 +993,6 @@ nfsd4_proc_compound(struct svc_rqst *rqs
 		case OP_VERIFY:
 			op->status = nfsd4_verify(rqstp, cstate,
 						  &op->u.verify);
-			if (op->status == nfserr_same)
-				op->status = nfs_ok;
 			break;
 		case OP_WRITE:
 			op->status = nfsd4_write(rqstp, cstate, &op->u.write);

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 014 of 18] knfsd: nfsd4: reorganize compound ops
  2006-12-08  1:13 [PATCH 000 of 18] knfsd: Introduction - NFSv4 updates and more NeilBrown
                   ` (12 preceding siblings ...)
  2006-12-08  1:14 ` [PATCH 013 of 18] knfsd: nfsd4: make verify and nverify wrappers NeilBrown
@ 2006-12-08  1:14 ` NeilBrown
  2006-12-08  1:14 ` [PATCH 015 of 18] knfsd: nfsd4: simplify migration op check NeilBrown
                   ` (3 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: NeilBrown @ 2006-12-08  1:14 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel


From: J.Bruce Fields <bfields@fieldses.org>

Define an op descriptor struct, use it to simplify nfsd4_proc_compound().

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./fs/nfsd/nfs4proc.c         |  254 +++++++++++++++++++++----------------------
 ./fs/nfsd/nfs4state.c        |   14 +-
 ./include/linux/nfsd/state.h |    1 
 ./include/linux/nfsd/xdr4.h  |    5 
 4 files changed, 144 insertions(+), 130 deletions(-)

diff .prev/fs/nfsd/nfs4proc.c ./fs/nfsd/nfs4proc.c
--- .prev/fs/nfsd/nfs4proc.c	2006-12-08 12:09:30.000000000 +1100
+++ ./fs/nfsd/nfs4proc.c	2006-12-08 12:09:30.000000000 +1100
@@ -258,7 +258,8 @@ out:
  * filehandle-manipulating ops.
  */
 static __be32
-nfsd4_getfh(struct nfsd4_compound_state *cstate, struct svc_fh **getfh)
+nfsd4_getfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	    struct svc_fh **getfh)
 {
 	if (!cstate->current_fh.fh_dentry)
 		return nfserr_nofilehandle;
@@ -279,7 +280,8 @@ nfsd4_putfh(struct svc_rqst *rqstp, stru
 }
 
 static __be32
-nfsd4_putrootfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate)
+nfsd4_putrootfh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+		void *arg)
 {
 	__be32 status;
 
@@ -290,7 +292,8 @@ nfsd4_putrootfh(struct svc_rqst *rqstp, 
 }
 
 static __be32
-nfsd4_restorefh(struct nfsd4_compound_state *cstate)
+nfsd4_restorefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+		void *arg)
 {
 	if (!cstate->save_fh.fh_dentry)
 		return nfserr_restorefh;
@@ -300,7 +303,8 @@ nfsd4_restorefh(struct nfsd4_compound_st
 }
 
 static __be32
-nfsd4_savefh(struct nfsd4_compound_state *cstate)
+nfsd4_savefh(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	     void *arg)
 {
 	if (!cstate->current_fh.fh_dentry)
 		return nfserr_nofilehandle;
@@ -463,7 +467,8 @@ nfsd4_link(struct svc_rqst *rqstp, struc
 }
 
 static __be32
-nfsd4_lookupp(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate)
+nfsd4_lookupp(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	      void *arg)
 {
 	struct svc_fh tmp_fh;
 	__be32 ret;
@@ -791,6 +796,16 @@ static struct nfsd4_compound_state *csta
 	return cstate;
 }
 
+typedef __be32(*nfsd4op_func)(struct svc_rqst *, struct nfsd4_compound_state *,
+			      void *);
+
+struct nfsd4_operation {
+	nfsd4op_func op_func;
+	u32 op_flags;
+};
+
+static struct nfsd4_operation nfsd4_ops[];
+
 /*
  * COMPOUND call.
  */
@@ -800,6 +815,7 @@ nfsd4_proc_compound(struct svc_rqst *rqs
 		    struct nfsd4_compoundres *resp)
 {
 	struct nfsd4_op	*op;
+	struct nfsd4_operation *opdesc;
 	struct nfsd4_compound_state *cstate = NULL;
 	int		slack_bytes;
 	__be32		status;
@@ -854,6 +870,8 @@ nfsd4_proc_compound(struct svc_rqst *rqs
 			goto encode_op;
 		}
 
+		opdesc = &nfsd4_ops[op->opnum];
+
 		/* All operations except RENEW, SETCLIENTID, RESTOREFH
 		* SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH
 		* require a valid current filehandle
@@ -883,127 +901,11 @@ nfsd4_proc_compound(struct svc_rqst *rqs
 			op->status = nfserr_moved;
 			goto encode_op;
 		}
-		switch (op->opnum) {
-		case OP_ACCESS:
-			op->status = nfsd4_access(rqstp, cstate,
-						  &op->u.access);
-			break;
-		case OP_CLOSE:
-			op->status = nfsd4_close(rqstp, cstate,
-						 &op->u.close);
-			break;
-		case OP_COMMIT:
-			op->status = nfsd4_commit(rqstp, cstate,
-						  &op->u.commit);
-			break;
-		case OP_CREATE:
-			op->status = nfsd4_create(rqstp, cstate,
-						  &op->u.create);
-			break;
-		case OP_DELEGRETURN:
-			op->status = nfsd4_delegreturn(rqstp, cstate,
-						       &op->u.delegreturn);
-			break;
-		case OP_GETATTR:
-			op->status = nfsd4_getattr(rqstp, cstate,
-						   &op->u.getattr);
-			break;
-		case OP_GETFH:
-			op->status = nfsd4_getfh(cstate, &op->u.getfh);
-			break;
-		case OP_LINK:
-			op->status = nfsd4_link(rqstp, cstate, &op->u.link);
-			break;
-		case OP_LOCK:
-			op->status = nfsd4_lock(rqstp, cstate, &op->u.lock);
-			break;
-		case OP_LOCKT:
-			op->status = nfsd4_lockt(rqstp, cstate, &op->u.lockt);
-			break;
-		case OP_LOCKU:
-			op->status = nfsd4_locku(rqstp, cstate, &op->u.locku);
-			break;
-		case OP_LOOKUP:
-			op->status = nfsd4_lookup(rqstp, cstate,
-						  &op->u.lookup);
-			break;
-		case OP_LOOKUPP:
-			op->status = nfsd4_lookupp(rqstp, cstate);
-			break;
-		case OP_NVERIFY:
-			op->status = nfsd4_nverify(rqstp, cstate,
-						  &op->u.nverify);
-			break;
-		case OP_OPEN:
-			op->status = nfsd4_open(rqstp, cstate,
-						&op->u.open);
-			break;
-		case OP_OPEN_CONFIRM:
-			op->status = nfsd4_open_confirm(rqstp, cstate,
-							&op->u.open_confirm);
-			break;
-		case OP_OPEN_DOWNGRADE:
-			op->status = nfsd4_open_downgrade(rqstp, cstate,
-							&op->u.open_downgrade);
-			break;
-		case OP_PUTFH:
-			op->status = nfsd4_putfh(rqstp, cstate, &op->u.putfh);
-			break;
-		case OP_PUTROOTFH:
-			op->status = nfsd4_putrootfh(rqstp, cstate);
-			break;
-		case OP_READ:
-			op->status = nfsd4_read(rqstp, cstate, &op->u.read);
-			break;
-		case OP_READDIR:
-			op->status = nfsd4_readdir(rqstp, cstate,
-						   &op->u.readdir);
-			break;
-		case OP_READLINK:
-			op->status = nfsd4_readlink(rqstp, cstate,
-						    &op->u.readlink);
-			break;
-		case OP_REMOVE:
-			op->status = nfsd4_remove(rqstp, cstate,
-						  &op->u.remove);
-			break;
-		case OP_RENAME:
-			op->status = nfsd4_rename(rqstp, cstate,
-						  &op->u.rename);
-			break;
-		case OP_RENEW:
-			op->status = nfsd4_renew(&op->u.renew);
-			break;
-		case OP_RESTOREFH:
-			op->status = nfsd4_restorefh(cstate);
-			break;
-		case OP_SAVEFH:
-			op->status = nfsd4_savefh(cstate);
-			break;
-		case OP_SETATTR:
-			op->status = nfsd4_setattr(rqstp, cstate,
-						   &op->u.setattr);
-			break;
-		case OP_SETCLIENTID:
-			op->status = nfsd4_setclientid(rqstp, &op->u.setclientid);
-			break;
-		case OP_SETCLIENTID_CONFIRM:
-			op->status = nfsd4_setclientid_confirm(rqstp, &op->u.setclientid_confirm);
-			break;
-		case OP_VERIFY:
-			op->status = nfsd4_verify(rqstp, cstate,
-						  &op->u.verify);
-			break;
-		case OP_WRITE:
-			op->status = nfsd4_write(rqstp, cstate, &op->u.write);
-			break;
-		case OP_RELEASE_LOCKOWNER:
-			op->status = nfsd4_release_lockowner(rqstp, &op->u.release_lockowner);
-			break;
-		default:
+
+		if (opdesc->op_func)
+			op->status = opdesc->op_func(rqstp, cstate, &op->u);
+		else
 			BUG_ON(op->status == nfs_ok);
-			break;
-		}
 
 encode_op:
 		if (op->status == nfserr_replay_me) {
@@ -1031,6 +933,108 @@ out:
 	return status;
 }
 
+static struct nfsd4_operation nfsd4_ops[OP_RELEASE_LOCKOWNER+1] = {
+	[OP_ACCESS] = {
+		.op_func = (nfsd4op_func)nfsd4_access,
+	},
+	[OP_CLOSE] = {
+		.op_func = (nfsd4op_func)nfsd4_close,
+	},
+	[OP_COMMIT] = {
+		.op_func = (nfsd4op_func)nfsd4_commit,
+	},
+	[OP_CREATE] = {
+		.op_func = (nfsd4op_func)nfsd4_create,
+	},
+	[OP_DELEGRETURN] = {
+		.op_func = (nfsd4op_func)nfsd4_delegreturn,
+	},
+	[OP_GETATTR] = {
+		.op_func = (nfsd4op_func)nfsd4_getattr,
+	},
+	[OP_GETFH] = {
+		.op_func = (nfsd4op_func)nfsd4_getfh,
+	},
+	[OP_LINK] = {
+		.op_func = (nfsd4op_func)nfsd4_link,
+	},
+	[OP_LOCK] = {
+		.op_func = (nfsd4op_func)nfsd4_lock,
+	},
+	[OP_LOCKT] = {
+		.op_func = (nfsd4op_func)nfsd4_lockt,
+	},
+	[OP_LOCKU] = {
+		.op_func = (nfsd4op_func)nfsd4_locku,
+	},
+	[OP_LOOKUP] = {
+		.op_func = (nfsd4op_func)nfsd4_lookup,
+	},
+	[OP_LOOKUPP] = {
+		.op_func = (nfsd4op_func)nfsd4_lookupp,
+	},
+	[OP_NVERIFY] = {
+		.op_func = (nfsd4op_func)nfsd4_nverify,
+	},
+	[OP_OPEN] = {
+		.op_func = (nfsd4op_func)nfsd4_open,
+	},
+	[OP_OPEN_CONFIRM] = {
+		.op_func = (nfsd4op_func)nfsd4_open_confirm,
+	},
+	[OP_OPEN_DOWNGRADE] = {
+		.op_func = (nfsd4op_func)nfsd4_open_downgrade,
+	},
+	[OP_PUTFH] = {
+		.op_func = (nfsd4op_func)nfsd4_putfh,
+	},
+	[OP_PUTROOTFH] = {
+		.op_func = (nfsd4op_func)nfsd4_putrootfh,
+	},
+	[OP_READ] = {
+		.op_func = (nfsd4op_func)nfsd4_read,
+	},
+	[OP_READDIR] = {
+		.op_func = (nfsd4op_func)nfsd4_readdir,
+	},
+	[OP_READLINK] = {
+		.op_func = (nfsd4op_func)nfsd4_readlink,
+	},
+	[OP_REMOVE] = {
+		.op_func = (nfsd4op_func)nfsd4_remove,
+	},
+	[OP_RENAME] = {
+		.op_func = (nfsd4op_func)nfsd4_rename,
+	},
+	[OP_RENEW] = {
+		.op_func = (nfsd4op_func)nfsd4_renew,
+	},
+	[OP_RESTOREFH] = {
+		.op_func = (nfsd4op_func)nfsd4_restorefh,
+	},
+	[OP_SAVEFH] = {
+		.op_func = (nfsd4op_func)nfsd4_savefh,
+	},
+	[OP_SETATTR] = {
+		.op_func = (nfsd4op_func)nfsd4_setattr,
+	},
+	[OP_SETCLIENTID] = {
+		.op_func = (nfsd4op_func)nfsd4_setclientid,
+	},
+	[OP_SETCLIENTID_CONFIRM] = {
+		.op_func = (nfsd4op_func)nfsd4_setclientid_confirm,
+	},
+	[OP_VERIFY] = {
+		.op_func = (nfsd4op_func)nfsd4_verify,
+	},
+	[OP_WRITE] = {
+		.op_func = (nfsd4op_func)nfsd4_write,
+	},
+	[OP_RELEASE_LOCKOWNER] = {
+		.op_func = (nfsd4op_func)nfsd4_release_lockowner,
+	},
+};
+
 #define nfs4svc_decode_voidargs		NULL
 #define nfs4svc_release_void		NULL
 #define nfsd4_voidres			nfsd4_voidargs

diff .prev/fs/nfsd/nfs4state.c ./fs/nfsd/nfs4state.c
--- .prev/fs/nfsd/nfs4state.c	2006-12-08 12:09:27.000000000 +1100
+++ ./fs/nfsd/nfs4state.c	2006-12-08 12:09:30.000000000 +1100
@@ -711,7 +711,8 @@ out_err:
  *
  */
 __be32
-nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_setclientid *setclid)
+nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+		  struct nfsd4_setclientid *setclid)
 {
 	__be32 			ip_addr = rqstp->rq_addr.sin_addr.s_addr;
 	struct xdr_netobj 	clname = { 
@@ -876,7 +877,9 @@ out:
  * NOTE: callback information will be processed here in a future patch
  */
 __be32
-nfsd4_setclientid_confirm(struct svc_rqst *rqstp, struct nfsd4_setclientid_confirm *setclientid_confirm)
+nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+			 struct nfsd4_compound_state *cstate,
+			 struct nfsd4_setclientid_confirm *setclientid_confirm)
 {
 	__be32 ip_addr = rqstp->rq_addr.sin_addr.s_addr;
 	struct nfs4_client *conf, *unconf;
@@ -1834,7 +1837,8 @@ static void laundromat_main(void *);
 static DECLARE_WORK(laundromat_work, laundromat_main, NULL);
 
 __be32
-nfsd4_renew(clientid_t *clid)
+nfsd4_renew(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
+	    clientid_t *clid)
 {
 	struct nfs4_client *clp;
 	__be32 status;
@@ -2980,7 +2984,9 @@ out:
 }
 
 __be32
-nfsd4_release_lockowner(struct svc_rqst *rqstp, struct nfsd4_release_lockowner *rlockowner)
+nfsd4_release_lockowner(struct svc_rqst *rqstp,
+			struct nfsd4_compound_state *cstate,
+			struct nfsd4_release_lockowner *rlockowner)
 {
 	clientid_t *clid = &rlockowner->rl_clientid;
 	struct nfs4_stateowner *sop;

diff .prev/include/linux/nfsd/state.h ./include/linux/nfsd/state.h
--- .prev/include/linux/nfsd/state.h	2006-12-08 12:07:21.000000000 +1100
+++ ./include/linux/nfsd/state.h	2006-12-08 12:09:30.000000000 +1100
@@ -273,7 +273,6 @@ struct nfs4_stateid {
 	((err) != nfserr_stale_stateid) &&      \
 	((err) != nfserr_bad_stateid))
 
-extern __be32 nfsd4_renew(clientid_t *clid);
 extern __be32 nfs4_preprocess_stateid_op(struct svc_fh *current_fh,
 		stateid_t *stateid, int flags, struct file **filp);
 extern void nfs4_lock_state(void);

diff .prev/include/linux/nfsd/xdr4.h ./include/linux/nfsd/xdr4.h
--- .prev/include/linux/nfsd/xdr4.h	2006-12-08 12:09:27.000000000 +1100
+++ ./include/linux/nfsd/xdr4.h	2006-12-08 12:09:30.000000000 +1100
@@ -436,8 +436,10 @@ __be32 nfsd4_encode_fattr(struct svc_fh 
 		       struct dentry *dentry, __be32 *buffer, int *countp,
 		       u32 *bmval, struct svc_rqst *);
 extern __be32 nfsd4_setclientid(struct svc_rqst *rqstp,
+		struct nfsd4_compound_state *,
 		struct nfsd4_setclientid *setclid);
 extern __be32 nfsd4_setclientid_confirm(struct svc_rqst *rqstp,
+		struct nfsd4_compound_state *,
 		struct nfsd4_setclientid_confirm *setclientid_confirm);
 extern __be32 nfsd4_process_open1(struct nfsd4_open *open);
 extern __be32 nfsd4_process_open2(struct svc_rqst *rqstp,
@@ -460,10 +462,13 @@ extern __be32 nfsd4_locku(struct svc_rqs
 		struct nfsd4_locku *locku);
 extern __be32
 nfsd4_release_lockowner(struct svc_rqst *rqstp,
+		struct nfsd4_compound_state *,
 		struct nfsd4_release_lockowner *rlockowner);
 extern void nfsd4_release_compoundargs(struct nfsd4_compoundargs *);
 extern __be32 nfsd4_delegreturn(struct svc_rqst *rqstp,
 		struct nfsd4_compound_state *, struct nfsd4_delegreturn *dr);
+extern __be32 nfsd4_renew(struct svc_rqst *rqstp,
+			  struct nfsd4_compound_state *, clientid_t *clid);
 #endif
 
 /*

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 015 of 18] knfsd: nfsd4: simplify migration op check
  2006-12-08  1:13 [PATCH 000 of 18] knfsd: Introduction - NFSv4 updates and more NeilBrown
                   ` (13 preceding siblings ...)
  2006-12-08  1:14 ` [PATCH 014 of 18] knfsd: nfsd4: reorganize compound ops NeilBrown
@ 2006-12-08  1:14 ` NeilBrown
  2006-12-08  1:14 ` [PATCH 016 of 18] knfsd: nfsd4: simplify filehandle check NeilBrown
                   ` (2 subsequent siblings)
  17 siblings, 0 replies; 19+ messages in thread
From: NeilBrown @ 2006-12-08  1:14 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel


From: J.Bruce Fields <bfields@fieldses.org>

I'm not too fond of these big if conditions.  Replace them by checks of a
flag in the operation descriptor.  To my eye this makes the code a bit more
self-documenting, and makes the complicated part of the code
(proc_compound) a little more compact.

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./fs/nfsd/nfs4proc.c |   24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)

diff .prev/fs/nfsd/nfs4proc.c ./fs/nfsd/nfs4proc.c
--- .prev/fs/nfsd/nfs4proc.c	2006-12-08 12:09:30.000000000 +1100
+++ ./fs/nfsd/nfs4proc.c	2006-12-08 12:09:30.000000000 +1100
@@ -802,6 +802,8 @@ typedef __be32(*nfsd4op_func)(struct svc
 struct nfsd4_operation {
 	nfsd4op_func op_func;
 	u32 op_flags;
+/* GETATTR and ops not listed as returning NFS4ERR_MOVED: */
+#define ALLOWED_ON_ABSENT_FS 1
 };
 
 static struct nfsd4_operation nfsd4_ops[];
@@ -887,17 +889,8 @@ nfsd4_proc_compound(struct svc_rqst *rqs
 				op->status = nfserr_nofilehandle;
 				goto encode_op;
 			}
-		}
-		/* Check must be done at start of each operation, except
-		 * for GETATTR and ops not listed as returning NFS4ERR_MOVED
-		 */
-		else if (cstate->current_fh.fh_export->ex_fslocs.migrated &&
-			 !((op->opnum == OP_GETATTR) ||
-			   (op->opnum == OP_PUTROOTFH) ||
-			   (op->opnum == OP_PUTPUBFH) ||
-			   (op->opnum == OP_RENEW) ||
-			   (op->opnum == OP_SETCLIENTID) ||
-			   (op->opnum == OP_RELEASE_LOCKOWNER))) {
+		} else if (cstate->current_fh.fh_export->ex_fslocs.migrated &&
+			  !(opdesc->op_flags & ALLOWED_ON_ABSENT_FS)) {
 			op->status = nfserr_moved;
 			goto encode_op;
 		}
@@ -951,6 +944,7 @@ static struct nfsd4_operation nfsd4_ops[
 	},
 	[OP_GETATTR] = {
 		.op_func = (nfsd4op_func)nfsd4_getattr,
+		.op_flags = ALLOWED_ON_ABSENT_FS,
 	},
 	[OP_GETFH] = {
 		.op_func = (nfsd4op_func)nfsd4_getfh,
@@ -988,8 +982,13 @@ static struct nfsd4_operation nfsd4_ops[
 	[OP_PUTFH] = {
 		.op_func = (nfsd4op_func)nfsd4_putfh,
 	},
+	[OP_PUTPUBFH] = {
+		/* unsupported; just for future reference: */
+		.op_flags = ALLOWED_ON_ABSENT_FS,
+	},
 	[OP_PUTROOTFH] = {
 		.op_func = (nfsd4op_func)nfsd4_putrootfh,
+		.op_flags = ALLOWED_ON_ABSENT_FS,
 	},
 	[OP_READ] = {
 		.op_func = (nfsd4op_func)nfsd4_read,
@@ -1008,6 +1007,7 @@ static struct nfsd4_operation nfsd4_ops[
 	},
 	[OP_RENEW] = {
 		.op_func = (nfsd4op_func)nfsd4_renew,
+		.op_flags = ALLOWED_ON_ABSENT_FS,
 	},
 	[OP_RESTOREFH] = {
 		.op_func = (nfsd4op_func)nfsd4_restorefh,
@@ -1020,6 +1020,7 @@ static struct nfsd4_operation nfsd4_ops[
 	},
 	[OP_SETCLIENTID] = {
 		.op_func = (nfsd4op_func)nfsd4_setclientid,
+		.op_flags = ALLOWED_ON_ABSENT_FS,
 	},
 	[OP_SETCLIENTID_CONFIRM] = {
 		.op_func = (nfsd4op_func)nfsd4_setclientid_confirm,
@@ -1032,6 +1033,7 @@ static struct nfsd4_operation nfsd4_ops[
 	},
 	[OP_RELEASE_LOCKOWNER] = {
 		.op_func = (nfsd4op_func)nfsd4_release_lockowner,
+		.op_flags = ALLOWED_ON_ABSENT_FS,
 	},
 };
 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 016 of 18] knfsd: nfsd4: simplify filehandle check
  2006-12-08  1:13 [PATCH 000 of 18] knfsd: Introduction - NFSv4 updates and more NeilBrown
                   ` (14 preceding siblings ...)
  2006-12-08  1:14 ` [PATCH 015 of 18] knfsd: nfsd4: simplify migration op check NeilBrown
@ 2006-12-08  1:14 ` NeilBrown
  2006-12-08  1:14 ` [PATCH 017 of 18] knfsd: Don't ignore kstrdup failure in rpc caches NeilBrown
  2006-12-08  1:14 ` [PATCH 018 of 18] knfsd: Fix up some bit-rot in exp_export NeilBrown
  17 siblings, 0 replies; 19+ messages in thread
From: NeilBrown @ 2006-12-08  1:14 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel


From: J.Bruce Fields <bfields@fieldses.org>

Kill another big "if" clause.

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./fs/nfsd/nfs4proc.c |   29 ++++++++++++-----------------
 1 file changed, 12 insertions(+), 17 deletions(-)

diff .prev/fs/nfsd/nfs4proc.c ./fs/nfsd/nfs4proc.c
--- .prev/fs/nfsd/nfs4proc.c	2006-12-08 12:09:30.000000000 +1100
+++ ./fs/nfsd/nfs4proc.c	2006-12-08 12:09:30.000000000 +1100
@@ -802,8 +802,10 @@ typedef __be32(*nfsd4op_func)(struct svc
 struct nfsd4_operation {
 	nfsd4op_func op_func;
 	u32 op_flags;
+/* Most ops require a valid current filehandle; a few don't: */
+#define ALLOWED_WITHOUT_FH 1
 /* GETATTR and ops not listed as returning NFS4ERR_MOVED: */
-#define ALLOWED_ON_ABSENT_FS 1
+#define ALLOWED_ON_ABSENT_FS 2
 };
 
 static struct nfsd4_operation nfsd4_ops[];
@@ -874,18 +876,8 @@ nfsd4_proc_compound(struct svc_rqst *rqs
 
 		opdesc = &nfsd4_ops[op->opnum];
 
-		/* All operations except RENEW, SETCLIENTID, RESTOREFH
-		* SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH
-		* require a valid current filehandle
-		*/
 		if (!cstate->current_fh.fh_dentry) {
-			if (!((op->opnum == OP_PUTFH) ||
-			      (op->opnum == OP_PUTROOTFH) ||
-			      (op->opnum == OP_SETCLIENTID) ||
-			      (op->opnum == OP_SETCLIENTID_CONFIRM) ||
-			      (op->opnum == OP_RENEW) ||
-			      (op->opnum == OP_RESTOREFH) ||
-			      (op->opnum == OP_RELEASE_LOCKOWNER))) {
+			if (!(opdesc->op_flags & ALLOWED_WITHOUT_FH)) {
 				op->status = nfserr_nofilehandle;
 				goto encode_op;
 			}
@@ -981,14 +973,15 @@ static struct nfsd4_operation nfsd4_ops[
 	},
 	[OP_PUTFH] = {
 		.op_func = (nfsd4op_func)nfsd4_putfh,
+		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
 	},
 	[OP_PUTPUBFH] = {
 		/* unsupported; just for future reference: */
-		.op_flags = ALLOWED_ON_ABSENT_FS,
+		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
 	},
 	[OP_PUTROOTFH] = {
 		.op_func = (nfsd4op_func)nfsd4_putrootfh,
-		.op_flags = ALLOWED_ON_ABSENT_FS,
+		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
 	},
 	[OP_READ] = {
 		.op_func = (nfsd4op_func)nfsd4_read,
@@ -1007,10 +1000,11 @@ static struct nfsd4_operation nfsd4_ops[
 	},
 	[OP_RENEW] = {
 		.op_func = (nfsd4op_func)nfsd4_renew,
-		.op_flags = ALLOWED_ON_ABSENT_FS,
+		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
 	},
 	[OP_RESTOREFH] = {
 		.op_func = (nfsd4op_func)nfsd4_restorefh,
+		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
 	},
 	[OP_SAVEFH] = {
 		.op_func = (nfsd4op_func)nfsd4_savefh,
@@ -1020,10 +1014,11 @@ static struct nfsd4_operation nfsd4_ops[
 	},
 	[OP_SETCLIENTID] = {
 		.op_func = (nfsd4op_func)nfsd4_setclientid,
-		.op_flags = ALLOWED_ON_ABSENT_FS,
+		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
 	},
 	[OP_SETCLIENTID_CONFIRM] = {
 		.op_func = (nfsd4op_func)nfsd4_setclientid_confirm,
+		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
 	},
 	[OP_VERIFY] = {
 		.op_func = (nfsd4op_func)nfsd4_verify,
@@ -1033,7 +1028,7 @@ static struct nfsd4_operation nfsd4_ops[
 	},
 	[OP_RELEASE_LOCKOWNER] = {
 		.op_func = (nfsd4op_func)nfsd4_release_lockowner,
-		.op_flags = ALLOWED_ON_ABSENT_FS,
+		.op_flags = ALLOWED_WITHOUT_FH | ALLOWED_ON_ABSENT_FS,
 	},
 };
 

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 017 of 18] knfsd: Don't ignore kstrdup failure in rpc caches.
  2006-12-08  1:13 [PATCH 000 of 18] knfsd: Introduction - NFSv4 updates and more NeilBrown
                   ` (15 preceding siblings ...)
  2006-12-08  1:14 ` [PATCH 016 of 18] knfsd: nfsd4: simplify filehandle check NeilBrown
@ 2006-12-08  1:14 ` NeilBrown
  2006-12-08  1:14 ` [PATCH 018 of 18] knfsd: Fix up some bit-rot in exp_export NeilBrown
  17 siblings, 0 replies; 19+ messages in thread
From: NeilBrown @ 2006-12-08  1:14 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel



Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./net/sunrpc/svcauth_unix.c |    4 ++++
 1 file changed, 4 insertions(+)

diff .prev/net/sunrpc/svcauth_unix.c ./net/sunrpc/svcauth_unix.c
--- .prev/net/sunrpc/svcauth_unix.c	2006-12-08 12:08:37.000000000 +1100
+++ ./net/sunrpc/svcauth_unix.c	2006-12-08 12:09:31.000000000 +1100
@@ -53,6 +53,10 @@ struct auth_domain *unix_domain_find(cha
 			return NULL;
 		kref_init(&new->h.ref);
 		new->h.name = kstrdup(name, GFP_KERNEL);
+		if (new->h.name == NULL) {
+			kfree(new);
+			return NULL;
+		}
 		new->h.flavour = &svcauth_unix;
 		new->addr_changes = 0;
 		rv = auth_domain_lookup(name, &new->h);

^ permalink raw reply	[flat|nested] 19+ messages in thread

* [PATCH 018 of 18] knfsd: Fix up some bit-rot in exp_export
  2006-12-08  1:13 [PATCH 000 of 18] knfsd: Introduction - NFSv4 updates and more NeilBrown
                   ` (16 preceding siblings ...)
  2006-12-08  1:14 ` [PATCH 017 of 18] knfsd: Don't ignore kstrdup failure in rpc caches NeilBrown
@ 2006-12-08  1:14 ` NeilBrown
  17 siblings, 0 replies; 19+ messages in thread
From: NeilBrown @ 2006-12-08  1:14 UTC (permalink / raw)
  To: Andrew Morton; +Cc: nfs, linux-kernel


The nfsservctl systemcall isn't used but recent nfs-utils releases for
exporting filesystems, and consequently the code that is uses -
exp_export - has suffered some bitrot.

Particular:
  - some newly added fields in 'struct svc_export' are being initialised
    properly.
  - the return value is now always -ENOMEM ...

This patch fixes both these problems.

Signed-off-by: Neil Brown <neilb@suse.de>

### Diffstat output
 ./fs/nfsd/export.c |   12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff .prev/fs/nfsd/export.c ./fs/nfsd/export.c
--- .prev/fs/nfsd/export.c	2006-12-08 12:08:37.000000000 +1100
+++ ./fs/nfsd/export.c	2006-12-08 12:09:31.000000000 +1100
@@ -955,6 +955,8 @@ exp_export(struct nfsctl_export *nxp)
 
 	exp = exp_get_by_name(clp, nd.mnt, nd.dentry, NULL);
 
+	memset(&new, 0, sizeof(new));
+
 	/* must make sure there won't be an ex_fsid clash */
 	if ((nxp->ex_flags & NFSEXP_FSID) &&
 	    (fsid_key = exp_get_fsid_key(clp, nxp->ex_dev)) &&
@@ -985,6 +987,9 @@ exp_export(struct nfsctl_export *nxp)
 
 	new.h.expiry_time = NEVER;
 	new.h.flags = 0;
+	new.ex_path = kstrdup(nxp->ex_path, GFP_KERNEL);
+	if (! new.ex_path)
+		goto finish;
 	new.ex_client = clp;
 	new.ex_mnt = nd.mnt;
 	new.ex_dentry = nd.dentry;
@@ -1005,10 +1010,11 @@ exp_export(struct nfsctl_export *nxp)
 		/* failed to create at least one index */
 		exp_do_unexport(exp);
 		cache_flush();
-		err = -ENOMEM;
-	}
-
+	} else
+		err = 0;
 finish:
+	if (new.ex_path)
+		kfree(new.ex_path);
 	if (exp)
 		exp_put(exp);
 	if (fsid_key && !IS_ERR(fsid_key))

^ permalink raw reply	[flat|nested] 19+ messages in thread

end of thread, other threads:[~2006-12-08  1:19 UTC | newest]

Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-12-08  1:13 [PATCH 000 of 18] knfsd: Introduction - NFSv4 updates and more NeilBrown
2006-12-08  1:13 ` [PATCH 001 of 18] knfsd: nfsd4: remove a dprink from nfsd4_lock NeilBrown
2006-12-08  1:13 ` [PATCH 002 of 18] knfsd: svcrpc: fix gss krb5i memory leak NeilBrown
2006-12-08  1:13 ` [PATCH 003 of 18] knfsd: nfsd4: clarify units of COMPOUND_SLACK_SPACE NeilBrown
2006-12-08  1:13 ` [PATCH 004 of 18] knfsd: nfsd: make exp_rootfh handle exp_parent errors NeilBrown
2006-12-08  1:13 ` [PATCH 005 of 18] knfsd: nfsd: simplify exp_pseudoroot NeilBrown
2006-12-08  1:13 ` [PATCH 006 of 18] knfsd: nfsd4: handling more nfsd_cross_mnt errors in nfsd4 readdir NeilBrown
2006-12-08  1:13 ` [PATCH 007 of 18] knfsd: nfsd: don't drop silently on upcall deferral NeilBrown
2006-12-08  1:14 ` [PATCH 008 of 18] knfsd: svcrpc: remove another silent drop from deferral code NeilBrown
2006-12-08  1:14 ` [PATCH 009 of 18] knfsd: nfsd4: pass saved and current fh together into nfsd4 operations NeilBrown
2006-12-08  1:14 ` [PATCH 010 of 18] knfsd: nfsd4: remove spurious replay_owner check NeilBrown
2006-12-08  1:14 ` [PATCH 011 of 18] knfsd: nfsd4: move replay_owner to cstate NeilBrown
2006-12-08  1:14 ` [PATCH 012 of 18] knfsd: nfsd4: don't inline nfsd4 compound op functions NeilBrown
2006-12-08  1:14 ` [PATCH 013 of 18] knfsd: nfsd4: make verify and nverify wrappers NeilBrown
2006-12-08  1:14 ` [PATCH 014 of 18] knfsd: nfsd4: reorganize compound ops NeilBrown
2006-12-08  1:14 ` [PATCH 015 of 18] knfsd: nfsd4: simplify migration op check NeilBrown
2006-12-08  1:14 ` [PATCH 016 of 18] knfsd: nfsd4: simplify filehandle check NeilBrown
2006-12-08  1:14 ` [PATCH 017 of 18] knfsd: Don't ignore kstrdup failure in rpc caches NeilBrown
2006-12-08  1:14 ` [PATCH 018 of 18] knfsd: Fix up some bit-rot in exp_export NeilBrown

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).