aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfsd/nfs4state.c49
-rw-r--r--include/linux/nfsd/state.h5
2 files changed, 38 insertions, 16 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 59b214f01b6d..b83f8fb441e1 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1160,6 +1160,7 @@ init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *
1160 stp->st_deny_bmap = 0; 1160 stp->st_deny_bmap = 0;
1161 __set_bit(open->op_share_access, &stp->st_access_bmap); 1161 __set_bit(open->op_share_access, &stp->st_access_bmap);
1162 __set_bit(open->op_share_deny, &stp->st_deny_bmap); 1162 __set_bit(open->op_share_deny, &stp->st_deny_bmap);
1163 stp->st_openstp = NULL;
1163} 1164}
1164 1165
1165static void 1166static void
@@ -2158,12 +2159,18 @@ out:
2158 return status; 2159 return status;
2159} 2160}
2160 2161
2162static inline int
2163setlkflg (int type)
2164{
2165 return (type == NFS4_READW_LT || type == NFS4_READ_LT) ?
2166 RD_STATE : WR_STATE;
2167}
2161 2168
2162/* 2169/*
2163 * Checks for sequence id mutating operations. 2170 * Checks for sequence id mutating operations.
2164 */ 2171 */
2165static int 2172static int
2166nfs4_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) 2173nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *stateid, int flags, struct nfs4_stateowner **sopp, struct nfs4_stateid **stpp, struct nfsd4_lock *lock)
2167{ 2174{
2168 struct nfs4_stateid *stp; 2175 struct nfs4_stateid *stp;
2169 struct nfs4_stateowner *sop; 2176 struct nfs4_stateowner *sop;
@@ -2201,21 +2208,31 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei
2201 goto check_replay; 2208 goto check_replay;
2202 } 2209 }
2203 2210
2204 /* for new lock stateowners: 2211 if (lock) {
2205 * check that the lock->v.new.open_stateid
2206 * refers to an open stateowner
2207 *
2208 * check that the lockclid (nfs4_lock->v.new.clientid) is the same
2209 * as the open_stateid->st_stateowner->so_client->clientid
2210 */
2211 if (lockclid) {
2212 struct nfs4_stateowner *sop = stp->st_stateowner; 2212 struct nfs4_stateowner *sop = stp->st_stateowner;
2213 clientid_t *lockclid = &lock->v.new.clientid;
2213 struct nfs4_client *clp = sop->so_client; 2214 struct nfs4_client *clp = sop->so_client;
2215 int lkflg = 0;
2216 int status;
2217
2218 lkflg = setlkflg(lock->lk_type);
2219
2220 if (lock->lk_is_new) {
2221 if (!sop->so_is_open_owner)
2222 return nfserr_bad_stateid;
2223 if (!cmp_clid(&clp->cl_clientid, lockclid))
2224 return nfserr_bad_stateid;
2225 /* stp is the open stateid */
2226 status = nfs4_check_openmode(stp, lkflg);
2227 if (status)
2228 return status;
2229 } else {
2230 /* stp is the lock stateid */
2231 status = nfs4_check_openmode(stp->st_openstp, lkflg);
2232 if (status)
2233 return status;
2234 }
2214 2235
2215 if (!sop->so_is_open_owner)
2216 return nfserr_bad_stateid;
2217 if (!cmp_clid(&clp->cl_clientid, lockclid))
2218 return nfserr_bad_stateid;
2219 } 2236 }
2220 2237
2221 if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) { 2238 if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) {
@@ -2642,6 +2659,7 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc
2642 stp->st_vfs_file = open_stp->st_vfs_file; /* FIXME refcount?? */ 2659 stp->st_vfs_file = open_stp->st_vfs_file; /* FIXME refcount?? */
2643 stp->st_access_bmap = open_stp->st_access_bmap; 2660 stp->st_access_bmap = open_stp->st_access_bmap;
2644 stp->st_deny_bmap = open_stp->st_deny_bmap; 2661 stp->st_deny_bmap = open_stp->st_deny_bmap;
2662 stp->st_openstp = open_stp;
2645 2663
2646out: 2664out:
2647 return stp; 2665 return stp;
@@ -2697,8 +2715,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2697 lock->lk_new_open_seqid, 2715 lock->lk_new_open_seqid,
2698 &lock->lk_new_open_stateid, 2716 &lock->lk_new_open_stateid,
2699 CHECK_FH | OPEN_STATE, 2717 CHECK_FH | OPEN_STATE,
2700 &open_sop, &open_stp, 2718 &open_sop, &open_stp, lock);
2701 &lock->v.new.clientid);
2702 if (status) 2719 if (status)
2703 goto out; 2720 goto out;
2704 /* create lockowner and lock stateid */ 2721 /* create lockowner and lock stateid */
@@ -2726,7 +2743,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_lock
2726 lock->lk_old_lock_seqid, 2743 lock->lk_old_lock_seqid,
2727 &lock->lk_old_lock_stateid, 2744 &lock->lk_old_lock_stateid,
2728 CHECK_FH | LOCK_STATE, 2745 CHECK_FH | LOCK_STATE,
2729 &lock->lk_stateowner, &lock_stp, NULL); 2746 &lock->lk_stateowner, &lock_stp, lock);
2730 if (status) 2747 if (status)
2731 goto out; 2748 goto out;
2732 } 2749 }
diff --git a/include/linux/nfsd/state.h b/include/linux/nfsd/state.h
index 2d19431f47ea..8bf23cf8b603 100644
--- a/include/linux/nfsd/state.h
+++ b/include/linux/nfsd/state.h
@@ -237,6 +237,10 @@ struct nfs4_file {
237* st_perlockowner: (open stateid) list of lock nfs4_stateowners 237* st_perlockowner: (open stateid) list of lock nfs4_stateowners
238* st_access_bmap: used only for open stateid 238* st_access_bmap: used only for open stateid
239* st_deny_bmap: used only for open stateid 239* st_deny_bmap: used only for open stateid
240* st_openstp: open stateid lock stateid was derived from
241*
242* XXX: open stateids and lock stateids have diverged sufficiently that
243* we should consider defining separate structs for the two cases.
240*/ 244*/
241 245
242struct nfs4_stateid { 246struct nfs4_stateid {
@@ -250,6 +254,7 @@ struct nfs4_stateid {
250 struct file * st_vfs_file; 254 struct file * st_vfs_file;
251 unsigned long st_access_bmap; 255 unsigned long st_access_bmap;
252 unsigned long st_deny_bmap; 256 unsigned long st_deny_bmap;
257 struct nfs4_stateid * st_openstp;
253}; 258};
254 259
255/* flags for preprocess_seqid_op() */ 260/* flags for preprocess_seqid_op() */