Commit a733375f authored by Neil Brown's avatar Neil Brown Committed by Linus Torvalds

[PATCH] knfsd: move nfserr_openmode checking from nfsd_read/write into...

[PATCH] knfsd: move nfserr_openmode checking from nfsd_read/write into nfs4_preprocess_stateid_op() in preparation for delegation state.
Signed-off-by: default avatarAndy Adamson <andros@citi.umich.edu>
Signed-off-by: default avatarNeil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 4798d59e
...@@ -460,24 +460,9 @@ nfsd4_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_loo ...@@ -460,24 +460,9 @@ nfsd4_lookup(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_loo
return nfsd_lookup(rqstp, current_fh, lookup->lo_name, lookup->lo_len, current_fh); return nfsd_lookup(rqstp, current_fh, lookup->lo_name, lookup->lo_len, current_fh);
} }
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 static inline int
nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read) nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read *read)
{ {
struct nfs4_stateid *stp;
int status; int status;
/* no need to check permission - this will be done in nfsd_read() */ /* no need to check permission - this will be done in nfsd_read() */
...@@ -509,15 +494,10 @@ nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read ...@@ -509,15 +494,10 @@ nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read
} }
/* check stateid */ /* check stateid */
if ((status = nfs4_preprocess_stateid_op(current_fh, &read->rd_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"); dprintk("NFSD: nfsd4_read: couldn't process stateid!\n");
goto out; 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; status = nfs_ok;
out: out:
nfs4_unlock_state(); nfs4_unlock_state();
...@@ -605,7 +585,6 @@ nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh, ...@@ -605,7 +585,6 @@ nfsd4_rename(struct svc_rqst *rqstp, struct svc_fh *current_fh,
static inline int static inline int
nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_setattr *setattr) 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 = nfs_ok;
if (nfs4_in_grace()) if (nfs4_in_grace())
...@@ -626,15 +605,10 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se ...@@ -626,15 +605,10 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se
nfs4_lock_state(); nfs4_lock_state();
if ((status = nfs4_preprocess_stateid_op(current_fh, if ((status = nfs4_preprocess_stateid_op(current_fh,
&setattr->sa_stateid, &setattr->sa_stateid,
CHECK_FH | RDWR_STATE, &stp))) { CHECK_FH | WR_STATE))) {
dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n"); dprintk("NFSD: nfsd4_setattr: couldn't process stateid!\n");
goto out_unlock; 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(); nfs4_unlock_state();
} }
status = nfs_ok; status = nfs_ok;
...@@ -654,7 +628,6 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se ...@@ -654,7 +628,6 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se
static inline int static inline int
nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_write *write) 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; stateid_t *stateid = &write->wr_stateid;
u32 *p; u32 *p;
int status = nfs_ok; int status = nfs_ok;
...@@ -677,18 +650,13 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ ...@@ -677,18 +650,13 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
goto zero_stateid; goto zero_stateid;
} }
if ((status = nfs4_preprocess_stateid_op(current_fh, 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"); dprintk("NFSD: nfsd4_write: couldn't process stateid!\n");
goto out; 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: zero_stateid:
nfs4_unlock_state(); nfs4_unlock_state();
write->wr_bytes_written = write->wr_buflen; write->wr_bytes_written = write->wr_buflen;
write->wr_how_written = write->wr_stable_how; write->wr_how_written = write->wr_stable_how;
......
...@@ -1564,12 +1564,39 @@ STALE_STATEID(stateid_t *stateid) ...@@ -1564,12 +1564,39 @@ STALE_STATEID(stateid_t *stateid)
return 1; 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 * Checks for stateid operations
*/ */
int 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; struct nfs4_stateid *stp;
int status; int status;
...@@ -1578,8 +1605,6 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl ...@@ -1578,8 +1605,6 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
stateid->si_boot, stateid->si_stateownerid, stateid->si_boot, stateid->si_stateownerid,
stateid->si_fileid, stateid->si_generation); stateid->si_fileid, stateid->si_generation);
*stpp = NULL;
/* STALE STATEID */ /* STALE STATEID */
status = nfserr_stale_stateid; status = nfserr_stale_stateid;
if (STALE_STATEID(stateid)) if (STALE_STATEID(stateid))
...@@ -1611,9 +1636,12 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl ...@@ -1611,9 +1636,12 @@ nfs4_preprocess_stateid_op(struct svc_fh *current_fh, stateid_t *stateid, int fl
dprintk("preprocess_stateid_op: old stateid!\n"); dprintk("preprocess_stateid_op: old stateid!\n");
goto out; goto out;
} }
*stpp = stp;
status = nfs_ok;
renew_client(stp->st_stateowner->so_client); renew_client(stp->st_stateowner->so_client);
if((status = check_openmode(stp, flags)))
goto out;
status = nfs_ok;
out: out:
return status; return status;
} }
...@@ -1938,7 +1966,7 @@ find_stateid(stateid_t *stid, int flags) ...@@ -1938,7 +1966,7 @@ find_stateid(stateid_t *stid, int flags)
unsigned int hashval; unsigned int hashval;
dprintk("NFSD: find_stateid flags 0x%x\n",flags); 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); hashval = stateid_hashval(st_id, f_id);
list_for_each_entry(local, &lockstateid_hashtbl[hashval], st_hash) { list_for_each_entry(local, &lockstateid_hashtbl[hashval], st_hash) {
if ((local->st_stateid.si_stateownerid == st_id) && if ((local->st_stateid.si_stateownerid == st_id) &&
...@@ -1946,7 +1974,7 @@ find_stateid(stateid_t *stid, int flags) ...@@ -1946,7 +1974,7 @@ find_stateid(stateid_t *stid, int flags)
return local; 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); hashval = stateid_hashval(st_id, f_id);
list_for_each_entry(local, &stateid_hashtbl[hashval], st_hash) { list_for_each_entry(local, &stateid_hashtbl[hashval], st_hash) {
if ((local->st_stateid.si_stateownerid == st_id) && if ((local->st_stateid.si_stateownerid == st_id) &&
......
...@@ -231,8 +231,9 @@ struct nfs4_stateid { ...@@ -231,8 +231,9 @@ struct nfs4_stateid {
#define CONFIRM 0x00000002 #define CONFIRM 0x00000002
#define OPEN_STATE 0x00000004 #define OPEN_STATE 0x00000004
#define LOCK_STATE 0x00000008 #define LOCK_STATE 0x00000008
#define RDWR_STATE 0x00000010 #define RD_STATE 0x00000010
#define CLOSE_STATE 0x00000020 #define WR_STATE 0x00000020
#define CLOSE_STATE 0x00000040
#define seqid_mutating_err(err) \ #define seqid_mutating_err(err) \
(((err) != nfserr_stale_clientid) && \ (((err) != nfserr_stale_clientid) && \
...@@ -243,7 +244,7 @@ struct nfs4_stateid { ...@@ -243,7 +244,7 @@ struct nfs4_stateid {
extern time_t nfs4_laundromat(void); extern time_t nfs4_laundromat(void);
extern int nfsd4_renew(clientid_t *clid); extern int nfsd4_renew(clientid_t *clid);
extern int nfs4_preprocess_stateid_op(struct svc_fh *current_fh, 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, extern int nfs4_share_conflict(struct svc_fh *current_fh,
unsigned int deny_type); unsigned int deny_type);
extern void nfs4_lock_state(void); extern void nfs4_lock_state(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment