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

[PATCH] NFSv4 server - missing locking

From: "William A.(Andy) Adamson" <andros@citi.umich.edu>

sorry. i forgot to lock the nfsv4 state in nfsd4_read, nfsd4_write, and
nfsd4_setattr.
parent 1042e7c3
...@@ -354,6 +354,7 @@ nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read ...@@ -354,6 +354,7 @@ nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read
if (read->rd_offset >= OFFSET_MAX) if (read->rd_offset >= OFFSET_MAX)
return nfserr_inval; return nfserr_inval;
nfsd4_lock_state();
status = nfs_ok; status = nfs_ok;
/* For stateid -1, we don't check share reservations. */ /* For stateid -1, we don't check share reservations. */
if (ONE_STATEID(&read->rd_stateid)) { if (ONE_STATEID(&read->rd_stateid)) {
...@@ -386,6 +387,7 @@ nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read ...@@ -386,6 +387,7 @@ nfsd4_read(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_read
} }
status = nfs_ok; status = nfs_ok;
out: out:
nfsd4_unlock_state();
read->rd_rqstp = rqstp; read->rd_rqstp = rqstp;
read->rd_fhp = current_fh; read->rd_fhp = current_fh;
return status; return status;
...@@ -454,12 +456,14 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se ...@@ -454,12 +456,14 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se
int status = nfs_ok; int status = nfs_ok;
if (setattr->sa_iattr.ia_valid & ATTR_SIZE) { if (setattr->sa_iattr.ia_valid & ATTR_SIZE) {
status = nfserr_bad_stateid; status = nfserr_bad_stateid;
if (ZERO_STATEID(&setattr->sa_stateid) || ONE_STATEID(&setattr->sa_stateid)) { if (ZERO_STATEID(&setattr->sa_stateid) || ONE_STATEID(&setattr->sa_stateid)) {
dprintk("NFSD: nfsd4_setattr: magic stateid!\n"); dprintk("NFSD: nfsd4_setattr: magic stateid!\n");
goto out; return status;
} }
nfsd4_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, &stp))) { CHECK_FH, &stp))) {
...@@ -471,9 +475,11 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se ...@@ -471,9 +475,11 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_se
dprintk("NFSD: nfsd4_setattr: not opened for write!\n"); dprintk("NFSD: nfsd4_setattr: not opened for write!\n");
goto out; goto out;
} }
nfsd4_unlock_state();
} }
status = nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr, 0, (time_t)0); return (nfsd_setattr(rqstp, current_fh, &setattr->sa_iattr, 0, (time_t)0));
out: out:
nfsd4_unlock_state();
return status; return status;
} }
...@@ -490,6 +496,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ ...@@ -490,6 +496,7 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
if (write->wr_offset >= OFFSET_MAX) if (write->wr_offset >= OFFSET_MAX)
return nfserr_inval; return nfserr_inval;
nfsd4_lock_state();
if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) { if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) {
dprintk("NFSD: nfsd4_write: zero stateid...\n"); dprintk("NFSD: nfsd4_write: zero stateid...\n");
if ((status = nfs4_share_conflict(current_fh, NFS4_SHARE_DENY_WRITE))) { if ((status = nfs4_share_conflict(current_fh, NFS4_SHARE_DENY_WRITE))) {
...@@ -511,17 +518,18 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ ...@@ -511,17 +518,18 @@ nfsd4_write(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_writ
} }
zero_stateid: zero_stateid:
nfsd4_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;
p = (u32 *)write->wr_verifier; p = (u32 *)write->wr_verifier;
*p++ = nfssvc_boot.tv_sec; *p++ = nfssvc_boot.tv_sec;
*p++ = nfssvc_boot.tv_usec; *p++ = nfssvc_boot.tv_usec;
status = nfsd_write(rqstp, current_fh, write->wr_offset, return (nfsd_write(rqstp, current_fh, write->wr_offset,
write->wr_vec, write->wr_vlen, write->wr_buflen, write->wr_vec, write->wr_vlen, write->wr_buflen,
&write->wr_how_written); &write->wr_how_written));
out: out:
nfsd4_unlock_state();
return status; return status;
} }
......
...@@ -79,6 +79,18 @@ u32 vfsclose = 0; ...@@ -79,6 +79,18 @@ u32 vfsclose = 0;
*/ */
static struct semaphore client_sema; static struct semaphore client_sema;
void
nfsd4_lock_state(void)
{
down(&client_sema);
}
void
nfsd4_unlock_state(void)
{
up(&client_sema);
}
static inline u32 static inline u32
opaque_hashval(const void *ptr, int nbytes) opaque_hashval(const void *ptr, int nbytes)
{ {
......
...@@ -167,4 +167,6 @@ extern int nfs4_preprocess_stateid_op(struct svc_fh *current_fh, ...@@ -167,4 +167,6 @@ 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, struct nfs4_stateid **stpp);
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 nfsd4_lock_state(void);
extern void nfsd4_unlock_state(void);
#endif /* NFSD4_STATE_H */ #endif /* NFSD4_STATE_H */
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