aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeff Layton <jlayton@primarydata.com>2014-06-30 11:48:39 -0400
committerJ. Bruce Fields <bfields@redhat.com>2014-07-09 20:54:57 -0400
commitc53530da4dfede2f080129b58a89ef907e5a0dfd (patch)
tree2c2e79091c493593290a1a0a041596b24b42ac06
parent3c87b9b7c05d7775a3d942de588296025023c6d2 (diff)
nfsd: Allow lockowners to hold several stateids
A lockowner can have more than one lock stateid. For instance, if a process has more than one file open and has locks on both, then the same lockowner has more than one stateid associated with it. Change it so that this reality is better reflected by the objects that nfsd uses. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> Signed-off-by: Jeff Layton <jlayton@primarydata.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r--fs/nfsd/nfs4state.c55
1 files changed, 33 insertions, 22 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 137fdcce9023..9b6a4f3ec18e 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -3870,12 +3870,7 @@ nfsd4_free_lock_stateid(struct nfs4_ol_stateid *stp)
3870 3870
3871 if (check_for_locks(stp->st_file, lo)) 3871 if (check_for_locks(stp->st_file, lo))
3872 return nfserr_locks_held; 3872 return nfserr_locks_held;
3873 /* 3873 release_lockowner_if_empty(lo);
3874 * Currently there's a 1-1 lock stateid<->lockowner
3875 * correspondance, and we have to delete the lockowner when we
3876 * delete the lock stateid:
3877 */
3878 release_lockowner(lo);
3879 return nfs_ok; 3874 return nfs_ok;
3880} 3875}
3881 3876
@@ -4397,6 +4392,19 @@ alloc_init_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fp, struct
4397 return stp; 4392 return stp;
4398} 4393}
4399 4394
4395static struct nfs4_ol_stateid *
4396find_lock_stateid(struct nfs4_lockowner *lo, struct nfs4_file *fp)
4397{
4398 struct nfs4_ol_stateid *lst;
4399
4400 list_for_each_entry(lst, &lo->lo_owner.so_stateids, st_perstateowner) {
4401 if (lst->st_file == fp)
4402 return lst;
4403 }
4404 return NULL;
4405}
4406
4407
4400static int 4408static int
4401check_lock_length(u64 offset, u64 length) 4409check_lock_length(u64 offset, u64 length)
4402{ 4410{
@@ -4426,25 +4434,28 @@ static __be32 lookup_or_create_lock_state(struct nfsd4_compound_state *cstate, s
4426 4434
4427 lo = find_lockowner_str(fi->fi_inode, &cl->cl_clientid, 4435 lo = find_lockowner_str(fi->fi_inode, &cl->cl_clientid,
4428 &lock->v.new.owner, nn); 4436 &lock->v.new.owner, nn);
4429 if (lo) { 4437 if (!lo) {
4430 if (!cstate->minorversion) 4438 strhashval = ownerstr_hashval(cl->cl_clientid.cl_id,
4439 &lock->v.new.owner);
4440 lo = alloc_init_lock_stateowner(strhashval, cl, ost, lock);
4441 if (lo == NULL)
4442 return nfserr_jukebox;
4443 } else {
4444 /* with an existing lockowner, seqids must be the same */
4445 if (!cstate->minorversion &&
4446 lock->lk_new_lock_seqid != lo->lo_owner.so_seqid)
4431 return nfserr_bad_seqid; 4447 return nfserr_bad_seqid;
4432 /* XXX: a lockowner always has exactly one stateid: */
4433 *lst = list_first_entry(&lo->lo_owner.so_stateids,
4434 struct nfs4_ol_stateid, st_perstateowner);
4435 return nfs_ok;
4436 } 4448 }
4437 strhashval = ownerstr_hashval(cl->cl_clientid.cl_id, 4449
4438 &lock->v.new.owner); 4450 *lst = find_lock_stateid(lo, fi);
4439 lo = alloc_init_lock_stateowner(strhashval, cl, ost, lock);
4440 if (lo == NULL)
4441 return nfserr_jukebox;
4442 *lst = alloc_init_lock_stateid(lo, fi, ost);
4443 if (*lst == NULL) { 4451 if (*lst == NULL) {
4444 release_lockowner(lo); 4452 *lst = alloc_init_lock_stateid(lo, fi, ost);
4445 return nfserr_jukebox; 4453 if (*lst == NULL) {
4454 release_lockowner_if_empty(lo);
4455 return nfserr_jukebox;
4456 }
4457 *new = true;
4446 } 4458 }
4447 *new = true;
4448 return nfs_ok; 4459 return nfs_ok;
4449} 4460}
4450 4461
@@ -4601,7 +4612,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4601 } 4612 }
4602out: 4613out:
4603 if (status && new_state) 4614 if (status && new_state)
4604 release_lockowner(lock_sop); 4615 release_lock_stateid(lock_stp);
4605 nfsd4_bump_seqid(cstate, status); 4616 nfsd4_bump_seqid(cstate, status);
4606 if (!cstate->replay_owner) 4617 if (!cstate->replay_owner)
4607 nfs4_unlock_state(); 4618 nfs4_unlock_state();