From: NeilBrown <neilb@cse.unsw.edu.au>

owned by the lockowner clientid.


---

 fs/nfsd/nfs4state.c |   32 +++++++++++++++++++++++++-------
 1 files changed, 25 insertions(+), 7 deletions(-)

diff -puN fs/nfsd/nfs4state.c~knfsd-OP_LOCK-check fs/nfsd/nfs4state.c
--- 25/fs/nfsd/nfs4state.c~knfsd-OP_LOCK-check	2004-02-25 02:32:22.000000000 -0800
+++ 25-akpm/fs/nfsd/nfs4state.c	2004-02-25 02:32:22.000000000 -0800
@@ -1402,7 +1402,7 @@ out:
  * Checks for sequence id mutating operations. 
  */
 int
-nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp)
+nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, clientid_t *lockclid)
 {
 	int status;
 	struct nfs4_stateid *stp;
@@ -1439,6 +1439,21 @@ nfs4_preprocess_seqid_op(struct svc_fh *
 
 	status = nfserr_bad_stateid;
 
+	/* for new lock stateowners, check that the lock->v.new.open_stateid
+	 * refers to an open stateowner, and that the lockclid
+	 * (nfs4_lock->v.new.clientid) is the same as the
+	 * open_stateid->st_stateowner->so_client->clientid
+	 */
+	if (lockclid) {
+		struct nfs4_stateowner *sop = stp->st_stateowner;
+		struct nfs4_client *clp = sop->so_client;
+
+		if (!sop->so_is_open_owner)
+			goto out;
+		if (!cmp_clid(&clp->cl_clientid, lockclid))
+			goto out;
+	}
+
 	if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) {
 		printk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n");
 		stp->st_vfs_set = 0;
@@ -1525,7 +1540,7 @@ nfsd4_open_confirm(struct svc_rqst *rqst
 	if ((status = nfs4_preprocess_seqid_op(current_fh, oc->oc_seqid,
 					&oc->oc_req_stateid,
 					CHECK_FH | CONFIRM | OPEN_STATE,
-					&oc->oc_stateowner, &stp)))
+					&oc->oc_stateowner, &stp, NULL)))
 		goto out; 
 
 	sop = oc->oc_stateowner;
@@ -1557,7 +1572,7 @@ nfsd4_open_downgrade(struct svc_rqst *rq
 	if ((status = nfs4_preprocess_seqid_op(current_fh, od->od_seqid, 
 					&od->od_stateid, 
 					CHECK_FH | OPEN_STATE, 
-					&od->od_stateowner, &stp)))
+					&od->od_stateowner, &stp, NULL)))
 		goto out; 
 
 	status = nfserr_inval;
@@ -1597,7 +1612,7 @@ nfsd4_close(struct svc_rqst *rqstp, stru
 	if ((status = nfs4_preprocess_seqid_op(current_fh, close->cl_seqid, 
 					&close->cl_stateid, 
 					CHECK_FH | OPEN_STATE, 
-					&close->cl_stateowner, &stp)))
+					&close->cl_stateowner, &stp, NULL)))
 		goto out; 
 	/*
 	*  Return success, but first update the stateid.
@@ -1853,12 +1868,15 @@ nfsd4_lock(struct svc_rqst *rqstp, struc
 			printk("NFSD: nfsd4_lock: clientid is stale!\n");
 			goto out;
 		}
+		/* does the clientid in the lock owner own the open stateid? */
+
 		/* validate and update open stateid and open seqid */
 		status = nfs4_preprocess_seqid_op(current_fh, 
 				        lock->lk_new_open_seqid,
 		                        &lock->lk_new_open_stateid,
 		                        CHECK_FH | OPEN_STATE,
-		                        &open_sop, &open_stp);
+		                        &open_sop, &open_stp,
+					&lock->v.new.clientid);
 		if (status)
 			goto out;
 		/* create lockowner and lock stateid */
@@ -1890,7 +1908,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struc
 				       lock->lk_old_lock_seqid, 
 				       &lock->lk_old_lock_stateid, 
 				       CHECK_FH | LOCK_STATE, 
-				       &lock->lk_stateowner, &lock_stp);
+				       &lock->lk_stateowner, &lock_stp, NULL);
 		if (status)
 			goto out;
 	}
@@ -2095,7 +2113,7 @@ nfsd4_locku(struct svc_rqst *rqstp, stru
 					locku->lu_seqid, 
 					&locku->lu_stateid, 
 					CHECK_FH | LOCK_STATE, 
-					&locku->lu_stateowner, &stp)))
+					&locku->lu_stateowner, &stp, NULL)))
 		goto out;
 
 	filp = &stp->st_vfs_file;

_