aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorAndy Adamson <andros@netapp.com>2009-04-03 01:28:45 -0400
committerJ. Bruce Fields <bfields@citi.umich.edu>2009-04-03 20:41:19 -0400
commit6668958fac1d05f55420de702f3678d46c1e93a5 (patch)
tree2ee7fe01bb6720ecb1147c5c7f7e3d0289fc71bb /fs
parentdd453dfd70538cadc02cb47ff8d8cfd0cb8cf435 (diff)
nfsd41: stateid handling
When sessions are used, stateful operation sequenceid and stateid handling are not used. When sessions are used, on the first open set the seqid to 1, mark state confirmed and skip seqid processing. When sessionas are used the stateid generation number is ignored when it is zero whereas without sessions bad_stateid or stale stateid is returned. Add flags to propagate session use to all stateful ops and down to check_stateid_generation. Signed-off-by: Benny Halevy <bhalevy@panasas.com> Signed-off-by: Andy Adamson <andros@netapp.com> [nfsd4_has_session should return a boolean, not u32] Signed-off-by: Benny Halevy <bhalevy@panasas.com> [nfsd41: pass nfsd4_compoundres * to nfsd4_process_open1] [nfsd41: calculate HAS_SESSION in nfs4_preprocess_stateid_op] [nfsd41: calculate HAS_SESSION in nfs4_preprocess_seqid_op] Signed-off-by: Benny Halevy <bhalevy@panasas.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
Diffstat (limited to 'fs')
-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;