diff options
| author | Neil Brown <neilb@cse.unsw.edu.au> | 2004-10-19 18:25:26 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-10-19 18:25:26 -0700 |
| commit | 7b7e07a026a089e49bba8f1fc7f06da2180c24a2 (patch) | |
| tree | 651d8027da6e62bf16bbd27cc8e7842028041bb4 | |
| parent | d1c3bc1b288bdd65403fce876d0b242587293b9b (diff) | |
[PATCH] nfsd4: fix race in xdr encoding of lock_denied response.
We take a reference on the stateowner, and copy the clientid, instead of just
hoping no one destroys the stateowner before we reference it in
nfsd4_encode_lock_denied.
Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
| -rw-r--r-- | fs/nfsd/nfs4state.c | 5 | ||||
| -rw-r--r-- | fs/nfsd/nfs4xdr.c | 3 | ||||
| -rw-r--r-- | include/linux/nfsd/xdr4.h | 1 |
3 files changed, 7 insertions, 2 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index fcf49fe08460..440695e625cb 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1949,8 +1949,11 @@ nfs4_set_lock_denied(struct file_lock *fl, struct nfsd4_lock_denied *deny) unsigned int hval = lockownerid_hashval(sop->so_id); deny->ld_sop = NULL; - if (nfs4_verify_lock_stateowner(sop, hval)) + if (nfs4_verify_lock_stateowner(sop, hval)) { + kref_get(&sop->so_ref); deny->ld_sop = sop; + deny->ld_clientid = sop->so_client->cl_clientid; + } deny->ld_start = fl->fl_start; deny->ld_length = ~(u64)0; if (fl->fl_end != ~(u64)0) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 67cbaa9cb050..76cd74eddbeb 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -1994,9 +1994,10 @@ nfsd4_encode_lock_denied(struct nfsd4_compoundres *resp, struct nfsd4_lock_denie WRITE64(ld->ld_length); WRITE32(ld->ld_type); if (ld->ld_sop) { - WRITEMEM(&ld->ld_sop->so_client->cl_clientid, 8); + WRITEMEM(&ld->ld_clientid, 8); WRITE32(ld->ld_sop->so_owner.len); WRITEMEM(ld->ld_sop->so_owner.data, ld->ld_sop->so_owner.len); + kref_put(&ld->ld_sop->so_ref, nfs4_free_stateowner); } else { /* non - nfsv4 lock in conflict, no clientid nor owner */ WRITE64((u64)0); /* clientid */ WRITE32(0); /* length of owner name */ diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h index bf94561ca623..d629b5e55d90 100644 --- a/include/linux/nfsd/xdr4.h +++ b/include/linux/nfsd/xdr4.h @@ -116,6 +116,7 @@ struct nfsd4_link { }; struct nfsd4_lock_denied { + clientid_t ld_clientid; struct nfs4_stateowner *ld_sop; u64 ld_start; u64 ld_length; |
