aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs4proc.c5
-rw-r--r--fs/nfsd/nfs4state.c47
-rw-r--r--fs/nfsd/nfs4xdr.c2
3 files changed, 44 insertions, 10 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index e6a0f314fdbe..aeb4888bdfad 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -168,6 +168,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
168 struct nfsd4_open *open) 168 struct nfsd4_open *open)
169{ 169{
170 __be32 status; 170 __be32 status;
171 struct nfsd4_compoundres *resp;
172
171 dprintk("NFSD: nfsd4_open filename %.*s op_stateowner %p\n", 173 dprintk("NFSD: nfsd4_open filename %.*s op_stateowner %p\n",
172 (int)open->op_fname.len, open->op_fname.data, 174 (int)open->op_fname.len, open->op_fname.data,
173 open->op_stateowner); 175 open->op_stateowner);
@@ -179,7 +181,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
179 nfs4_lock_state(); 181 nfs4_lock_state();
180 182
181 /* check seqid for replay. set nfs4_owner */ 183 /* check seqid for replay. set nfs4_owner */
182 status = nfsd4_process_open1(open); 184 resp = rqstp->rq_resp;
185 status = nfsd4_process_open1(&resp->cstate, open);
183 if (status == nfserr_replay_me) { 186 if (status == nfserr_replay_me) {
184 struct nfs4_replay *rp = &open->op_stateowner->so_replay; 187 struct nfs4_replay *rp = &open->op_stateowner->so_replay;
185 fh_put(&cstate->current_fh); 188 fh_put(&cstate->current_fh);
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index f49f305096ec..bbaf3c9bfe5a 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -2183,7 +2183,8 @@ static struct lock_manager_operations nfsd_lease_mng_ops = {
2183 2183
2184 2184
2185__be32 2185__be32
2186nfsd4_process_open1(struct nfsd4_open *open) 2186nfsd4_process_open1(struct nfsd4_compound_state *cstate,
2187 struct nfsd4_open *open)
2187{ 2188{
2188 clientid_t *clientid = &open->op_clientid; 2189 clientid_t *clientid = &open->op_clientid;
2189 struct nfs4_client *clp = NULL; 2190 struct nfs4_client *clp = NULL;
@@ -2206,6 +2207,9 @@ nfsd4_process_open1(struct nfsd4_open *open)
2206 return nfserr_expired; 2207 return nfserr_expired;
2207 goto renew; 2208 goto renew;
2208 } 2209 }
2210 /* When sessions are used, skip open sequenceid processing */
2211 if (nfsd4_has_session(cstate))
2212 goto renew;
2209 if (!sop->so_confirmed) { 2213 if (!sop->so_confirmed) {
2210 /* Replace unconfirmed owners without checking for replay. */ 2214 /* Replace unconfirmed owners without checking for replay. */
2211 clp = sop->so_client; 2215 clp = sop->so_client;
@@ -2483,6 +2487,7 @@ out:
2483__be32 2487__be32
2484nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open) 2488nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
2485{ 2489{
2490 struct nfsd4_compoundres *resp = rqstp->rq_resp;
2486 struct nfs4_file *fp = NULL; 2491 struct nfs4_file *fp = NULL;
2487 struct inode *ino = current_fh->fh_dentry->d_inode; 2492 struct inode *ino = current_fh->fh_dentry->d_inode;
2488 struct nfs4_stateid *stp = NULL; 2493 struct nfs4_stateid *stp = NULL;
@@ -2541,9 +2546,14 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
2541 release_open_stateid(stp); 2546 release_open_stateid(stp);
2542 goto out; 2547 goto out;
2543 } 2548 }
2549 if (nfsd4_has_session(&resp->cstate))
2550 update_stateid(&stp->st_stateid);
2544 } 2551 }
2545 memcpy(&open->op_stateid, &stp->st_stateid, sizeof(stateid_t)); 2552 memcpy(&open->op_stateid, &stp->st_stateid, sizeof(stateid_t));
2546 2553
2554 if (nfsd4_has_session(&resp->cstate))
2555 open->op_stateowner->so_confirmed = 1;
2556
2547 /* 2557 /*
2548 * Attempt to hand out a delegation. No error return, because the 2558 * Attempt to hand out a delegation. No error return, because the
2549 * OPEN succeeds even if we fail. 2559 * OPEN succeeds even if we fail.
@@ -2564,7 +2574,8 @@ out:
2564 * To finish the open response, we just need to set the rflags. 2574 * To finish the open response, we just need to set the rflags.
2565 */ 2575 */
2566 open->op_rflags = NFS4_OPEN_RESULT_LOCKTYPE_POSIX; 2576 open->op_rflags = NFS4_OPEN_RESULT_LOCKTYPE_POSIX;
2567 if (!open->op_stateowner->so_confirmed) 2577 if (!open->op_stateowner->so_confirmed &&
2578 !nfsd4_has_session(&resp->cstate))
2568 open->op_rflags |= NFS4_OPEN_RESULT_CONFIRM; 2579 open->op_rflags |= NFS4_OPEN_RESULT_CONFIRM;
2569 2580
2570 return status; 2581 return status;
@@ -2781,8 +2792,15 @@ grace_disallows_io(struct inode *inode)
2781 return locks_in_grace() && mandatory_lock(inode); 2792 return locks_in_grace() && mandatory_lock(inode);
2782} 2793}
2783 2794
2784static int check_stateid_generation(stateid_t *in, stateid_t *ref) 2795static int check_stateid_generation(stateid_t *in, stateid_t *ref, int flags)
2785{ 2796{
2797 /*
2798 * When sessions are used the stateid generation number is ignored
2799 * when it is zero.
2800 */
2801 if ((flags & HAS_SESSION) && in->si_generation == 0)
2802 goto out;
2803
2786 /* If the client sends us a stateid from the future, it's buggy: */ 2804 /* If the client sends us a stateid from the future, it's buggy: */
2787 if (in->si_generation > ref->si_generation) 2805 if (in->si_generation > ref->si_generation)
2788 return nfserr_bad_stateid; 2806 return nfserr_bad_stateid;
@@ -2798,6 +2816,7 @@ static int check_stateid_generation(stateid_t *in, stateid_t *ref)
2798 */ 2816 */
2799 if (in->si_generation < ref->si_generation) 2817 if (in->si_generation < ref->si_generation)
2800 return nfserr_old_stateid; 2818 return nfserr_old_stateid;
2819out:
2801 return nfs_ok; 2820 return nfs_ok;
2802} 2821}
2803 2822
@@ -2825,6 +2844,9 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
2825 if (grace_disallows_io(ino)) 2844 if (grace_disallows_io(ino))
2826 return nfserr_grace; 2845 return nfserr_grace;
2827 2846
2847 if (nfsd4_has_session(cstate))
2848 flags |= HAS_SESSION;
2849
2828 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) 2850 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
2829 return check_special_stateids(current_fh, stateid, flags); 2851 return check_special_stateids(current_fh, stateid, flags);
2830 2852
@@ -2837,7 +2859,8 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
2837 dp = find_delegation_stateid(ino, stateid); 2859 dp = find_delegation_stateid(ino, stateid);
2838 if (!dp) 2860 if (!dp)
2839 goto out; 2861 goto out;
2840 status = check_stateid_generation(stateid, &dp->dl_stateid); 2862 status = check_stateid_generation(stateid, &dp->dl_stateid,
2863 flags);
2841 if (status) 2864 if (status)
2842 goto out; 2865 goto out;
2843 status = nfs4_check_delegmode(dp, flags); 2866 status = nfs4_check_delegmode(dp, flags);
@@ -2854,7 +2877,8 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
2854 goto out; 2877 goto out;
2855 if (!stp->st_stateowner->so_confirmed) 2878 if (!stp->st_stateowner->so_confirmed)
2856 goto out; 2879 goto out;
2857 status = check_stateid_generation(stateid, &stp->st_stateid); 2880 status = check_stateid_generation(stateid, &stp->st_stateid,
2881 flags);
2858 if (status) 2882 if (status)
2859 goto out; 2883 goto out;
2860 status = nfs4_check_openmode(stp, flags); 2884 status = nfs4_check_openmode(stp, flags);
@@ -2905,6 +2929,10 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
2905 2929
2906 if (STALE_STATEID(stateid)) 2930 if (STALE_STATEID(stateid))
2907 return nfserr_stale_stateid; 2931 return nfserr_stale_stateid;
2932
2933 if (nfsd4_has_session(cstate))
2934 flags |= HAS_SESSION;
2935
2908 /* 2936 /*
2909 * We return BAD_STATEID if filehandle doesn't match stateid, 2937 * We return BAD_STATEID if filehandle doesn't match stateid,
2910 * the confirmed flag is incorrecly set, or the generation 2938 * the confirmed flag is incorrecly set, or the generation
@@ -2961,7 +2989,7 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
2961 * For the moment, we ignore the possibility of 2989 * For the moment, we ignore the possibility of
2962 * generation number wraparound. 2990 * generation number wraparound.
2963 */ 2991 */
2964 if (seqid != sop->so_seqid) 2992 if (!(flags & HAS_SESSION) && seqid != sop->so_seqid)
2965 goto check_replay; 2993 goto check_replay;
2966 2994
2967 if (sop->so_confirmed && flags & CONFIRM) { 2995 if (sop->so_confirmed && flags & CONFIRM) {
@@ -2974,7 +3002,7 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
2974 " confirmed yet!\n"); 3002 " confirmed yet!\n");
2975 return nfserr_bad_stateid; 3003 return nfserr_bad_stateid;
2976 } 3004 }
2977 status = check_stateid_generation(stateid, &stp->st_stateid); 3005 status = check_stateid_generation(stateid, &stp->st_stateid, flags);
2978 if (status) 3006 if (status)
2979 return status; 3007 return status;
2980 renew_client(sop->so_client); 3008 renew_client(sop->so_client);
@@ -3169,11 +3197,14 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3169 stateid_t *stateid = &dr->dr_stateid; 3197 stateid_t *stateid = &dr->dr_stateid;
3170 struct inode *inode; 3198 struct inode *inode;
3171 __be32 status; 3199 __be32 status;
3200 int flags = 0;
3172 3201
3173 if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0))) 3202 if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0)))
3174 return status; 3203 return status;
3175 inode = cstate->current_fh.fh_dentry->d_inode; 3204 inode = cstate->current_fh.fh_dentry->d_inode;
3176 3205
3206 if (nfsd4_has_session(cstate))
3207 flags |= HAS_SESSION;
3177 nfs4_lock_state(); 3208 nfs4_lock_state();
3178 status = nfserr_bad_stateid; 3209 status = nfserr_bad_stateid;
3179 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) 3210 if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
@@ -3187,7 +3218,7 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3187 dp = find_delegation_stateid(inode, stateid); 3218 dp = find_delegation_stateid(inode, stateid);
3188 if (!dp) 3219 if (!dp)
3189 goto out; 3220 goto out;
3190 status = check_stateid_generation(stateid, &dp->dl_stateid); 3221 status = check_stateid_generation(stateid, &dp->dl_stateid, flags);
3191 if (status) 3222 if (status)
3192 goto out; 3223 goto out;
3193 renew_client(dp->dl_client); 3224 renew_client(dp->dl_client);
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index c6a726d04efd..dd81ac1a1c6c 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -3194,7 +3194,7 @@ nfs4svc_encode_compoundres(struct svc_rqst *rqstp, __be32 *p, struct nfsd4_compo
3194 iov = &rqstp->rq_res.head[0]; 3194 iov = &rqstp->rq_res.head[0];
3195 iov->iov_len = ((char*)resp->p) - (char*)iov->iov_base; 3195 iov->iov_len = ((char*)resp->p) - (char*)iov->iov_base;
3196 BUG_ON(iov->iov_len > PAGE_SIZE); 3196 BUG_ON(iov->iov_len > PAGE_SIZE);
3197 if (resp->cstate.slot != NULL) { 3197 if (nfsd4_has_session(&resp->cstate)) {
3198 if (resp->cstate.status == nfserr_replay_cache && 3198 if (resp->cstate.status == nfserr_replay_cache &&
3199 !nfsd4_not_cached(resp)) { 3199 !nfsd4_not_cached(resp)) {
3200 iov->iov_len = resp->cstate.iovlen; 3200 iov->iov_len = resp->cstate.iovlen;