aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4state.c
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2011-10-20 06:57:46 -0400
committerJ. Bruce Fields <bfields@redhat.com>2011-11-07 21:10:47 -0500
commit64a284d07c7d84299a90826950079a8ef11e8204 (patch)
treea00309bb6be605383a98a805ddab5fb4da6a25f0 /fs/nfsd/nfs4state.c
parent684e563858018d27acb8f00e30c026215bbd0ffb (diff)
nfsd4: maintain one seqid stream per (lockowner, file)
Instead of creating a new lockowner and stateid for every open_to_lockowner call, reuse the existing lockowner if it exists. Reported-by: Trond Myklebust <Trond.Myklebust@netapp.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r--fs/nfsd/nfs4state.c58
1 files changed, 38 insertions, 20 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 9354ddebbee2..d09d5242c088 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -3905,6 +3905,37 @@ static void get_lock_access(struct nfs4_ol_stateid *lock_stp, u32 access)
3905 __set_bit(access, &lock_stp->st_access_bmap); 3905 __set_bit(access, &lock_stp->st_access_bmap);
3906} 3906}
3907 3907
3908__be32 lookup_or_create_lock_state(struct nfsd4_compound_state *cstate, struct nfs4_ol_stateid *ost, struct nfsd4_lock *lock, struct nfs4_ol_stateid **lst, bool *new)
3909{
3910 struct nfs4_file *fi = ost->st_file;
3911 struct nfs4_openowner *oo = openowner(ost->st_stateowner);
3912 struct nfs4_client *cl = oo->oo_owner.so_client;
3913 struct nfs4_lockowner *lo;
3914 unsigned int strhashval;
3915
3916 lo = find_lockowner_str(fi->fi_inode, &cl->cl_clientid, &lock->v.new.owner);
3917 if (lo) {
3918 if (!cstate->minorversion)
3919 return nfserr_bad_seqid;
3920 /* XXX: a lockowner always has exactly one stateid: */
3921 *lst = list_first_entry(&lo->lo_owner.so_stateids,
3922 struct nfs4_ol_stateid, st_perstateowner);
3923 return nfs_ok;
3924 }
3925 strhashval = lock_ownerstr_hashval(fi->fi_inode, cl->cl_clientid.cl_id,
3926 &lock->v.new.owner);
3927 lo = alloc_init_lock_stateowner(strhashval, cl, ost, lock);
3928 if (lo == NULL)
3929 return nfserr_jukebox;
3930 *lst = alloc_init_lock_stateid(lo, fi, ost);
3931 if (*lst == NULL) {
3932 release_lockowner(lo);
3933 return nfserr_jukebox;
3934 }
3935 *new = true;
3936 return nfs_ok;
3937}
3938
3908/* 3939/*
3909 * LOCK operation 3940 * LOCK operation
3910 */ 3941 */
@@ -3920,7 +3951,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3920 struct file_lock file_lock; 3951 struct file_lock file_lock;
3921 struct file_lock conflock; 3952 struct file_lock conflock;
3922 __be32 status = 0; 3953 __be32 status = 0;
3923 unsigned int strhashval; 3954 bool new_state = false;
3924 int lkflg; 3955 int lkflg;
3925 int err; 3956 int err;
3926 3957
@@ -3969,21 +4000,9 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3969 if (!same_clid(&open_sop->oo_owner.so_client->cl_clientid, 4000 if (!same_clid(&open_sop->oo_owner.so_client->cl_clientid,
3970 &lock->v.new.clientid)) 4001 &lock->v.new.clientid))
3971 goto out; 4002 goto out;
3972 /* create lockowner and lock stateid */ 4003 status = lookup_or_create_lock_state(cstate, open_stp, lock,
3973 fp = open_stp->st_file; 4004 &lock_stp, &new_state);
3974 strhashval = lock_ownerstr_hashval(fp->fi_inode, 4005 if (status)
3975 open_sop->oo_owner.so_client->cl_clientid.cl_id,
3976 &lock->v.new.owner);
3977 /* XXX: Do we need to check for duplicate stateowners on
3978 * the same file, or should they just be allowed (and
3979 * create new stateids)? */
3980 status = nfserr_jukebox;
3981 lock_sop = alloc_init_lock_stateowner(strhashval,
3982 open_sop->oo_owner.so_client, open_stp, lock);
3983 if (lock_sop == NULL)
3984 goto out;
3985 lock_stp = alloc_init_lock_stateid(lock_sop, fp, open_stp);
3986 if (lock_stp == NULL)
3987 goto out; 4006 goto out;
3988 } else { 4007 } else {
3989 /* lock (lock owner + lock stateid) already exists */ 4008 /* lock (lock owner + lock stateid) already exists */
@@ -3993,10 +4012,9 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3993 NFS4_LOCK_STID, &lock_stp); 4012 NFS4_LOCK_STID, &lock_stp);
3994 if (status) 4013 if (status)
3995 goto out; 4014 goto out;
3996 lock_sop = lockowner(lock_stp->st_stateowner);
3997 fp = lock_stp->st_file;
3998 } 4015 }
3999 /* lock_sop and lock_stp have been created or found */ 4016 lock_sop = lockowner(lock_stp->st_stateowner);
4017 fp = lock_stp->st_file;
4000 4018
4001 lkflg = setlkflg(lock->lk_type); 4019 lkflg = setlkflg(lock->lk_type);
4002 status = nfs4_check_openmode(lock_stp, lkflg); 4020 status = nfs4_check_openmode(lock_stp, lkflg);
@@ -4071,7 +4089,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4071 break; 4089 break;
4072 } 4090 }
4073out: 4091out:
4074 if (status && lock->lk_is_new && lock_sop) 4092 if (status && new_state)
4075 release_lockowner(lock_sop); 4093 release_lockowner(lock_sop);
4076 if (!cstate->replay_owner) 4094 if (!cstate->replay_owner)
4077 nfs4_unlock_state(); 4095 nfs4_unlock_state();