aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfsd/nfs4state.c45
1 files changed, 33 insertions, 12 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 749608b914b4..eaa5f9ebf444 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -4754,6 +4754,7 @@ find_lockowner_str(clientid_t *clid, struct xdr_netobj *owner,
4754 continue; 4754 continue;
4755 if (!same_owner_str(so, owner, clid)) 4755 if (!same_owner_str(so, owner, clid))
4756 continue; 4756 continue;
4757 atomic_inc(&so->so_count);
4757 return lockowner(so); 4758 return lockowner(so);
4758 } 4759 }
4759 return NULL; 4760 return NULL;
@@ -4787,9 +4788,7 @@ alloc_init_lock_stateowner(unsigned int strhashval, struct nfs4_client *clp, str
4787 return NULL; 4788 return NULL;
4788 INIT_LIST_HEAD(&lo->lo_owner.so_stateids); 4789 INIT_LIST_HEAD(&lo->lo_owner.so_stateids);
4789 lo->lo_owner.so_is_open_owner = 0; 4790 lo->lo_owner.so_is_open_owner = 0;
4790 /* It is the openowner seqid that will be incremented in encode in the 4791 lo->lo_owner.so_seqid = lock->lk_new_lock_seqid;
4791 * case of new lockowners; so increment the lock seqid manually: */
4792 lo->lo_owner.so_seqid = lock->lk_new_lock_seqid + 1;
4793 lo->lo_owner.so_ops = &lockowner_ops; 4792 lo->lo_owner.so_ops = &lockowner_ops;
4794 list_add(&lo->lo_owner.so_strhash, &nn->ownerstr_hashtbl[strhashval]); 4793 list_add(&lo->lo_owner.so_strhash, &nn->ownerstr_hashtbl[strhashval]);
4795 return lo; 4794 return lo;
@@ -4895,6 +4894,7 @@ lookup_or_create_lock_state(struct nfsd4_compound_state *cstate,
4895 struct nfsd4_lock *lock, 4894 struct nfsd4_lock *lock,
4896 struct nfs4_ol_stateid **lst, bool *new) 4895 struct nfs4_ol_stateid **lst, bool *new)
4897{ 4896{
4897 __be32 status;
4898 struct nfs4_file *fi = ost->st_stid.sc_file; 4898 struct nfs4_file *fi = ost->st_stid.sc_file;
4899 struct nfs4_openowner *oo = openowner(ost->st_stateowner); 4899 struct nfs4_openowner *oo = openowner(ost->st_stateowner);
4900 struct nfs4_client *cl = oo->oo_owner.so_client; 4900 struct nfs4_client *cl = oo->oo_owner.so_client;
@@ -4910,19 +4910,26 @@ lookup_or_create_lock_state(struct nfsd4_compound_state *cstate,
4910 lo = alloc_init_lock_stateowner(strhashval, cl, ost, lock); 4910 lo = alloc_init_lock_stateowner(strhashval, cl, ost, lock);
4911 if (lo == NULL) 4911 if (lo == NULL)
4912 return nfserr_jukebox; 4912 return nfserr_jukebox;
4913 /* FIXME: extra reference for new lockowners for the client */
4914 atomic_inc(&lo->lo_owner.so_count);
4913 } else { 4915 } else {
4914 /* with an existing lockowner, seqids must be the same */ 4916 /* with an existing lockowner, seqids must be the same */
4917 status = nfserr_bad_seqid;
4915 if (!cstate->minorversion && 4918 if (!cstate->minorversion &&
4916 lock->lk_new_lock_seqid != lo->lo_owner.so_seqid) 4919 lock->lk_new_lock_seqid != lo->lo_owner.so_seqid)
4917 return nfserr_bad_seqid; 4920 goto out;
4918 } 4921 }
4919 4922
4920 *lst = find_or_create_lock_stateid(lo, fi, inode, ost, new); 4923 *lst = find_or_create_lock_stateid(lo, fi, inode, ost, new);
4921 if (*lst == NULL) { 4924 if (*lst == NULL) {
4922 release_lockowner_if_empty(lo); 4925 release_lockowner_if_empty(lo);
4923 return nfserr_jukebox; 4926 status = nfserr_jukebox;
4927 goto out;
4924 } 4928 }
4925 return nfs_ok; 4929 status = nfs_ok;
4930out:
4931 nfs4_put_stateowner(&lo->lo_owner);
4932 return status;
4926} 4933}
4927 4934
4928/* 4935/*
@@ -4941,9 +4948,9 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4941 struct file_lock *file_lock = NULL; 4948 struct file_lock *file_lock = NULL;
4942 struct file_lock *conflock = NULL; 4949 struct file_lock *conflock = NULL;
4943 __be32 status = 0; 4950 __be32 status = 0;
4944 bool new_state = false;
4945 int lkflg; 4951 int lkflg;
4946 int err; 4952 int err;
4953 bool new = false;
4947 struct net *net = SVC_NET(rqstp); 4954 struct net *net = SVC_NET(rqstp);
4948 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 4955 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
4949 4956
@@ -4986,7 +4993,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
4986 &lock->v.new.clientid)) 4993 &lock->v.new.clientid))
4987 goto out; 4994 goto out;
4988 status = lookup_or_create_lock_state(cstate, open_stp, lock, 4995 status = lookup_or_create_lock_state(cstate, open_stp, lock,
4989 &lock_stp, &new_state); 4996 &lock_stp, &new);
4990 } else { 4997 } else {
4991 status = nfs4_preprocess_seqid_op(cstate, 4998 status = nfs4_preprocess_seqid_op(cstate,
4992 lock->lk_old_lock_seqid, 4999 lock->lk_old_lock_seqid,
@@ -5085,12 +5092,24 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
5085out: 5092out:
5086 if (filp) 5093 if (filp)
5087 fput(filp); 5094 fput(filp);
5088 if (lock_stp) 5095 if (lock_stp) {
5096 /* Bump seqid manually if the 4.0 replay owner is openowner */
5097 if (cstate->replay_owner &&
5098 cstate->replay_owner != &lock_sop->lo_owner &&
5099 seqid_mutating_err(ntohl(status)))
5100 lock_sop->lo_owner.so_seqid++;
5101
5102 /*
5103 * If this is a new, never-before-used stateid, and we are
5104 * returning an error, then just go ahead and release it.
5105 */
5106 if (status && new)
5107 release_lock_stateid(lock_stp);
5108
5089 nfs4_put_stid(&lock_stp->st_stid); 5109 nfs4_put_stid(&lock_stp->st_stid);
5110 }
5090 if (open_stp) 5111 if (open_stp)
5091 nfs4_put_stid(&open_stp->st_stid); 5112 nfs4_put_stid(&open_stp->st_stid);
5092 if (status && new_state)
5093 release_lock_stateid(lock_stp);
5094 nfsd4_bump_seqid(cstate, status); 5113 nfsd4_bump_seqid(cstate, status);
5095 nfs4_unlock_state(); 5114 nfs4_unlock_state();
5096 if (file_lock) 5115 if (file_lock)
@@ -5125,7 +5144,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
5125 struct nfsd4_lockt *lockt) 5144 struct nfsd4_lockt *lockt)
5126{ 5145{
5127 struct file_lock *file_lock = NULL; 5146 struct file_lock *file_lock = NULL;
5128 struct nfs4_lockowner *lo; 5147 struct nfs4_lockowner *lo = NULL;
5129 __be32 status; 5148 __be32 status;
5130 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); 5149 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
5131 5150
@@ -5188,6 +5207,8 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
5188 nfs4_set_lock_denied(file_lock, &lockt->lt_denied); 5207 nfs4_set_lock_denied(file_lock, &lockt->lt_denied);
5189 } 5208 }
5190out: 5209out:
5210 if (lo)
5211 nfs4_put_stateowner(&lo->lo_owner);
5191 nfs4_unlock_state(); 5212 nfs4_unlock_state();
5192 if (file_lock) 5213 if (file_lock)
5193 locks_free_lock(file_lock); 5214 locks_free_lock(file_lock);