From: NeilBrown <neilb@cse.unsw.edu.au>

nfsd4_restore_fh() returns nfserr_restorefh instead of nfserr_nofilehandle


---

 25-akpm/fs/nfsd/nfs4proc.c |   32 ++++++++++++++++++++++++++++----
 25-akpm/fs/nfsd/nfs4xdr.c  |   10 ++++++++--
 2 files changed, 36 insertions(+), 6 deletions(-)

diff -puN fs/nfsd/nfs4proc.c~knfsd-nfserr_nofilehandle-fix fs/nfsd/nfs4proc.c
--- 25/fs/nfsd/nfs4proc.c~knfsd-nfserr_nofilehandle-fix	Mon Feb 23 16:33:47 2004
+++ 25-akpm/fs/nfsd/nfs4proc.c	Mon Feb 23 16:33:47 2004
@@ -192,7 +192,7 @@ static inline int
 nfsd4_restorefh(struct svc_fh *current_fh, struct svc_fh *save_fh)
 {
 	if (!save_fh->fh_dentry)
-		return nfserr_nofilehandle;
+		return nfserr_restorefh;
 
 	fh_dup2(current_fh, save_fh);
 	return nfs_ok;
@@ -336,8 +336,10 @@ static inline int
 nfsd4_link(struct svc_rqst *rqstp, struct svc_fh *current_fh,
 	   struct svc_fh *save_fh, struct nfsd4_link *link)
 {
-	int status;
+	int status = nfserr_nofilehandle;
 
+	if (!save_fh->fh_dentry)
+		return status;
 	status = nfsd_link(rqstp, current_fh, link->li_name, link->li_namelen, save_fh);
 	if (!status)
 		set_change_info(&link->li_cinfo, current_fh);
@@ -458,8 +460,10 @@ static inline int
 nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh,
 	     struct svc_fh *save_fh, struct nfsd4_rename *rename)
 {
-	int status;
+	int status = nfserr_nofilehandle;
 
+	if (!save_fh->fh_dentry)
+		return status;
 	status = nfsd_rename(rqstp, save_fh, rename->rn_sname,
 			     rename->rn_snamelen, current_fh,
 			     rename->rn_tname, rename->rn_tnamelen);
@@ -474,8 +478,12 @@ static inline int
 nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_setattr *setattr)
 {
 	struct nfs4_stateid *stp;
-	int status = nfs_ok;
+	int status = nfserr_nofilehandle;
+
+	if (!current_fh->fh_dentry)
+		goto out;
 
+	status = nfs_ok;
 	if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
 
 		status = nfserr_bad_stateid;
@@ -679,6 +687,22 @@ nfsd4_proc_compound(struct svc_rqst *rqs
 			goto encode_op;
 		}
 
+		/* All operations except RENEW, SETCLIENTID, RESTOREFH
+		* SETCLIENTID_CONFIRM, PUTFH and PUTROOTFH
+		* require a valid current filehandle
+		*
+		* SETATTR NOFILEHANDLE error handled in nfsd4_setattr
+		* due to required returned bitmap argument
+		*/
+		if ((!current_fh.fh_dentry) &&
+		   !((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_SETATTR))) {
+			op->status = nfserr_nofilehandle;
+			goto encode_op;
+		}
 		switch (op->opnum) {
 		case OP_ACCESS:
 			op->status = nfsd4_access(rqstp, &current_fh, &op->u.access);
diff -puN fs/nfsd/nfs4xdr.c~knfsd-nfserr_nofilehandle-fix fs/nfsd/nfs4xdr.c
--- 25/fs/nfsd/nfs4xdr.c~knfsd-nfserr_nofilehandle-fix	Mon Feb 23 16:33:47 2004
+++ 25-akpm/fs/nfsd/nfs4xdr.c	Mon Feb 23 16:33:47 2004
@@ -2226,8 +2226,14 @@ nfsd4_encode_operation(struct nfsd4_comp
 
 	RESERVE_SPACE(8);
 	WRITE32(op->opnum);
-	statp = p++;                  /* to be backfilled at the end */
-	ADJUST_ARGS();
+	if ((op->opnum != OP_SETATTR) && (op->opnum != OP_LOCK) && (op->opnum != OP_LOCKT) && (op->opnum != OP_SETCLIENTID) && (op->status)) {
+		*p++ = op->status;
+		ADJUST_ARGS();
+		return;
+	} else {
+		statp = p++;        /* to be backfilled at the end */
+		ADJUST_ARGS();
+	}
 
 	switch (op->opnum) {
 	case OP_ACCESS:

_