diff options
-rw-r--r-- | fs/nfsd/nfs4state.c | 49 | ||||
-rw-r--r-- | include/linux/nfsd/state.h | 5 |
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 | ||
1165 | static void | 1166 | static void |
@@ -2158,12 +2159,18 @@ out: | |||
2158 | return status; | 2159 | return status; |
2159 | } | 2160 | } |
2160 | 2161 | ||
2162 | static inline int | ||
2163 | setlkflg (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 | */ |
2165 | static int | 2172 | static int |
2166 | 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) | 2173 | nfs4_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 | ||
2646 | out: | 2664 | out: |
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 | ||
242 | struct nfs4_stateid { | 246 | struct 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() */ |