From: NeilBrown Signed-off-by: Andy Adamson Signed-off-by: Neil Brown Signed-off-by: Andrew Morton --- 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); _