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
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
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, struct svc_fh *current_fh, struct nfsd4_read
}
/* 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, struct svc_fh *current_fh,
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, struct svc_fh *current_fh, struct nfsd4_se
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 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se
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, struct svc_fh *current_fh, struct nfsd4_writ
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;
......
......@@ -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 *current_fh, stateid_t *stateid, int fl
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 *current_fh, stateid_t *stateid, int fl
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) &&
......
......@@ -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);
......
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