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

Move special stateid processing to nfs4_preprocess_stateid_op().  Also make
stateid processing for setattr the same as that for write.

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/fs/nfsd/nfs4proc.c  |   38 +-------------------------------------
 25-akpm/fs/nfsd/nfs4state.c |   19 +++++++++++++++++++
 2 files changed, 20 insertions(+), 37 deletions(-)

diff -puN fs/nfsd/nfs4proc.c~nfsd4-move-special-stateid-processing fs/nfsd/nfs4proc.c
--- 25/fs/nfsd/nfs4proc.c~nfsd4-move-special-stateid-processing	2005-03-07 23:55:18.000000000 -0800
+++ 25-akpm/fs/nfsd/nfs4proc.c	2005-03-07 23:55:18.000000000 -0800
@@ -473,25 +473,6 @@ nfsd4_read(struct svc_rqst *rqstp, struc
 		return nfserr_inval;
 
 	nfs4_lock_state();
-	status = nfs_ok;
-	/* For stateid -1, we don't check share reservations.  */
-	if (ONE_STATEID(&read->rd_stateid)) {
-		dprintk("NFSD: nfsd4_read: -1 stateid...\n");
-		goto out;
-	}
-	/*
-	* For stateid 0, the client doesn't have to have the file open, but
-	* we still check for share reservation conflicts. 
-	*/
-	if (ZERO_STATEID(&read->rd_stateid)) {
-		dprintk("NFSD: nfsd4_read: zero stateid...\n");
-		if ((status = nfs4_share_conflict(current_fh, NFS4_SHARE_DENY_READ))) {
-			dprintk("NFSD: nfsd4_read: conflicting share reservation!\n");
-			goto out;
-		}
-		status = nfs_ok;
-		goto out;
-	}
 	/* check stateid */
 	if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid, 
 					CHECK_FH | RD_STATE))) {
@@ -595,13 +576,6 @@ nfsd4_setattr(struct svc_rqst *rqstp, st
 
 	status = nfs_ok;
 	if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
-
-		status = nfserr_bad_stateid;
-		if (ZERO_STATEID(&setattr->sa_stateid) || ONE_STATEID(&setattr->sa_stateid)) {
-			dprintk("NFSD: nfsd4_setattr: magic stateid!\n");
-			goto out;
-		}
-
 		nfs4_lock_state();
 		if ((status = nfs4_preprocess_stateid_op(current_fh, 
 						&setattr->sa_stateid, 
@@ -641,23 +615,13 @@ nfsd4_write(struct svc_rqst *rqstp, stru
 		return nfserr_inval;
 
 	nfs4_lock_state();
-	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) {
-		dprintk("NFSD: nfsd4_write: zero stateid...\n");
-		if ((status = nfs4_share_conflict(current_fh, NFS4_SHARE_DENY_WRITE))) {
-			dprintk("NFSD: nfsd4_write: conflicting share reservation!\n");
-			goto out;
-		}
-		goto zero_stateid;
-	}
 	if ((status = nfs4_preprocess_stateid_op(current_fh, stateid, 
 					CHECK_FH | WR_STATE))) {
 		dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
 		goto out;
 	}
-
-zero_stateid:
-
 	nfs4_unlock_state();
+
 	write->wr_bytes_written = write->wr_buflen;
 	write->wr_how_written = write->wr_stable_how;
 	p = (u32 *)write->wr_verifier.data;
diff -puN fs/nfsd/nfs4state.c~nfsd4-move-special-stateid-processing fs/nfsd/nfs4state.c
--- 25/fs/nfsd/nfs4state.c~nfsd4-move-special-stateid-processing	2005-03-07 23:55:18.000000000 -0800
+++ 25-akpm/fs/nfsd/nfs4state.c	2005-03-07 23:55:18.000000000 -0800
@@ -2007,6 +2007,22 @@ out:
 	return status;
 }
 
+static inline int
+check_special_stateids(svc_fh *current_fh, stateid_t *stateid, int flags)
+{
+	/* Trying to call delegreturn with a special stateid? Yuch: */
+	if (!(flags & (RD_STATE | WR_STATE)))
+		return nfserr_bad_stateid;
+	else if (ONE_STATEID(stateid) && (flags & RD_STATE))
+		return nfs_ok;
+	else if (flags & WR_STATE)
+		return nfs4_share_conflict(current_fh,
+				NFS4_SHARE_DENY_WRITE);
+	else /* (flags & RD_STATE) && ZERO_STATEID(stateid) */
+		return nfs4_share_conflict(current_fh,
+				NFS4_SHARE_DENY_READ);
+}
+
 /*
 * Checks for stateid operations
 */
@@ -2022,6 +2038,9 @@ nfs4_preprocess_stateid_op(struct svc_fh
 		stateid->si_boot, stateid->si_stateownerid, 
 		stateid->si_fileid, stateid->si_generation); 
 
+	if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
+		return check_special_stateids(current_fh, stateid, flags);
+
 	/* STALE STATEID */
 	status = nfserr_stale_stateid;
 	if (STALE_STATEID(stateid)) 
_