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

Signed-off-by: Andy Adamson <andros@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         |   40 +++--------------------------------
 25-akpm/fs/nfsd/nfs4state.c        |   42 ++++++++++++++++++++++++++++++-------
 25-akpm/include/linux/nfsd/state.h |    7 +++---
 3 files changed, 43 insertions(+), 46 deletions(-)

diff -puN fs/nfsd/nfs4proc.c~knfsd-move-nfserr_openmode-checking-from-nfsd_read-write-into-nfs4_preprocess_stateid_op-in-preperation-for-delegation-state fs/nfsd/nfs4proc.c
--- 25/fs/nfsd/nfs4proc.c~knfsd-move-nfserr_openmode-checking-from-nfsd_read-write-into-nfs4_preprocess_stateid_op-in-preperation-for-delegation-state	Fri Dec 17 15:08:26 2004
+++ 25-akpm/fs/nfsd/nfs4proc.c	Fri Dec 17 15:08:26 2004
@@ -461,23 +461,8 @@ nfsd4_lookup(struct svc_rqst *rqstp, str
 }
 
 static inline int
-access_bits_permit_read(unsigned long access_bmap)
-{
-	return test_bit(NFS4_SHARE_ACCESS_READ, &access_bmap) ||
-		test_bit(NFS4_SHARE_ACCESS_BOTH, &access_bmap);
-}
-
-static inline int
-access_bits_permit_write(unsigned long access_bmap)
-{
-	return test_bit(NFS4_SHARE_ACCESS_WRITE, &access_bmap) ||
-		test_bit(NFS4_SHARE_ACCESS_BOTH, &access_bmap);
-}
-
-static inline int
 nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read)
 {
-	struct nfs4_stateid *stp;
 	int status;
 
 	/* no need to check permission - this will be done in nfsd_read() */
@@ -509,15 +494,10 @@ nfsd4_read(struct svc_rqst *rqstp, struc
 	}
 	/* check stateid */
 	if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_stateid, 
-					CHECK_FH | RDWR_STATE, &stp))) {
+					CHECK_FH | RD_STATE))) {
 		dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
 		goto out;
 	}
-	status = nfserr_openmode;
-	if (!access_bits_permit_read(stp->st_access_bmap)) {
-		dprintk("NFSD: nfsd4_read: file not opened for read!\n");
-		goto out;
-	}
 	status = nfs_ok;
 out:
 	nfs4_unlock_state();
@@ -605,7 +585,6 @@ nfsd4_rename(struct svc_rqst *rqstp, str
 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;
 
 	if (nfs4_in_grace())
@@ -626,15 +605,10 @@ nfsd4_setattr(struct svc_rqst *rqstp, st
 		nfs4_lock_state();
 		if ((status = nfs4_preprocess_stateid_op(current_fh, 
 						&setattr->sa_stateid, 
-						CHECK_FH | RDWR_STATE, &stp))) {
+						CHECK_FH | WR_STATE))) {
 			dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
 			goto out_unlock;
 		}
-		status = nfserr_openmode;
-		if (!access_bits_permit_write(stp->st_access_bmap)) {
-			dprintk("NFSD: nfsd4_setattr: not opened for write!\n");
-			goto out_unlock;
-		}
 		nfs4_unlock_state();
 	}
 	status = nfs_ok;
@@ -654,7 +628,6 @@ out_unlock:
 static inline int
 nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_write *write)
 {
-	struct nfs4_stateid *stp;
 	stateid_t *stateid = &write->wr_stateid;
 	u32 *p;
 	int status = nfs_ok;
@@ -677,18 +650,13 @@ nfsd4_write(struct svc_rqst *rqstp, stru
 		goto zero_stateid;
 	}
 	if ((status = nfs4_preprocess_stateid_op(current_fh, stateid, 
-					CHECK_FH | RDWR_STATE, &stp))) {
+					CHECK_FH | WR_STATE))) {
 		dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
 		goto out;
 	}
 
-	status = nfserr_openmode;
-	if (!access_bits_permit_write(stp->st_access_bmap)) {
-		dprintk("NFSD: nfsd4_write: file not open for write!\n");
-		goto out;
-	}
-
 zero_stateid:
+
 	nfs4_unlock_state();
 	write->wr_bytes_written = write->wr_buflen;
 	write->wr_how_written = write->wr_stable_how;
diff -puN fs/nfsd/nfs4state.c~knfsd-move-nfserr_openmode-checking-from-nfsd_read-write-into-nfs4_preprocess_stateid_op-in-preperation-for-delegation-state fs/nfsd/nfs4state.c
--- 25/fs/nfsd/nfs4state.c~knfsd-move-nfserr_openmode-checking-from-nfsd_read-write-into-nfs4_preprocess_stateid_op-in-preperation-for-delegation-state	Fri Dec 17 15:08:26 2004
+++ 25-akpm/fs/nfsd/nfs4state.c	Fri Dec 17 15:08:26 2004
@@ -1564,12 +1564,39 @@ STALE_STATEID(stateid_t *stateid)
 	return 1;
 }
 
+static inline int
+access_permit_read(unsigned long access_bmap)
+{
+	return test_bit(NFS4_SHARE_ACCESS_READ, &access_bmap) ||
+		test_bit(NFS4_SHARE_ACCESS_BOTH, &access_bmap);
+}
+
+static inline int
+access_permit_write(unsigned long access_bmap)
+{
+	return test_bit(NFS4_SHARE_ACCESS_WRITE, &access_bmap) ||
+		test_bit(NFS4_SHARE_ACCESS_BOTH, &access_bmap);
+}
+
+static
+int check_openmode(struct nfs4_stateid *stp, int flags)
+{
+        int status = nfserr_openmode;
+
+	if ((flags & WR_STATE) && (!access_permit_write(stp->st_access_bmap)))
+                goto out;
+	if ((flags & RD_STATE) && (!access_permit_read(stp->st_access_bmap)))
+                goto out;
+	status = nfs_ok;
+out:
+	return status;
+}
 
 /*
 * Checks for stateid operations
 */
 int
-nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int flags, struct nfs4_stateid **stpp)
+nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int flags)
 {
 	struct nfs4_stateid *stp;
 	int status;
@@ -1578,8 +1605,6 @@ nfs4_preprocess_stateid_op(struct svc_fh
 		stateid->si_boot, stateid->si_stateownerid, 
 		stateid->si_fileid, stateid->si_generation); 
 
-	*stpp = NULL;
-
 	/* STALE STATEID */
 	status = nfserr_stale_stateid;
 	if (STALE_STATEID(stateid)) 
@@ -1611,9 +1636,12 @@ nfs4_preprocess_stateid_op(struct svc_fh
 		dprintk("preprocess_stateid_op: old stateid!\n");
 		goto out;
 	}
-	*stpp = stp;
-	status = nfs_ok;
 	renew_client(stp->st_stateowner->so_client);
+
+        if((status = check_openmode(stp, flags)))
+		goto out;
+
+	status = nfs_ok;
 out:
 	return status;
 }
@@ -1938,7 +1966,7 @@ find_stateid(stateid_t *stid, int flags)
 	unsigned int hashval;
 
 	dprintk("NFSD: find_stateid flags 0x%x\n",flags);
-	if ((flags & LOCK_STATE) || (flags & RDWR_STATE)) {
+	if ((flags & LOCK_STATE) || (flags & RD_STATE) || (flags & WR_STATE)) {
 		hashval = stateid_hashval(st_id, f_id);
 		list_for_each_entry(local, &lockstateid_hashtbl[hashval], st_hash) {
 			if ((local->st_stateid.si_stateownerid == st_id) &&
@@ -1946,7 +1974,7 @@ find_stateid(stateid_t *stid, int flags)
 				return local;
 		}
 	} 
-	if ((flags & OPEN_STATE) || (flags & RDWR_STATE)) {
+	if ((flags & OPEN_STATE) || (flags & RD_STATE) || (flags & WR_STATE)) {
 		hashval = stateid_hashval(st_id, f_id);
 		list_for_each_entry(local, &stateid_hashtbl[hashval], st_hash) {
 			if ((local->st_stateid.si_stateownerid == st_id) &&
diff -puN include/linux/nfsd/state.h~knfsd-move-nfserr_openmode-checking-from-nfsd_read-write-into-nfs4_preprocess_stateid_op-in-preperation-for-delegation-state include/linux/nfsd/state.h
--- 25/include/linux/nfsd/state.h~knfsd-move-nfserr_openmode-checking-from-nfsd_read-write-into-nfs4_preprocess_stateid_op-in-preperation-for-delegation-state	Fri Dec 17 15:08:26 2004
+++ 25-akpm/include/linux/nfsd/state.h	Fri Dec 17 15:08:26 2004
@@ -231,8 +231,9 @@ struct nfs4_stateid {
 #define CONFIRM                 0x00000002
 #define OPEN_STATE              0x00000004
 #define LOCK_STATE              0x00000008
-#define RDWR_STATE              0x00000010
-#define CLOSE_STATE             0x00000020
+#define RD_STATE	        0x00000010
+#define WR_STATE	        0x00000020
+#define CLOSE_STATE             0x00000040
 
 #define seqid_mutating_err(err)                       \
 	(((err) != nfserr_stale_clientid) &&    \
@@ -243,7 +244,7 @@ struct nfs4_stateid {
 extern time_t nfs4_laundromat(void);
 extern int nfsd4_renew(clientid_t *clid);
 extern int nfs4_preprocess_stateid_op(struct svc_fh *current_fh, 
-		stateid_t *stateid, int flags, struct nfs4_stateid **stpp);
+		stateid_t *stateid, int flags);
 extern int nfs4_share_conflict(struct svc_fh *current_fh, 
 		unsigned int deny_type);
 extern void nfs4_lock_state(void);
_
