diff options
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/nfs4proc.c | 5 | ||||
-rw-r--r-- | fs/nfsd/nfs4state.c | 47 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 2 |
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 |
2186 | nfsd4_process_open1(struct nfsd4_open *open) | 2186 | nfsd4_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 |
2484 | nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open) | 2488 | nfsd4_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 | ||
2784 | static int check_stateid_generation(stateid_t *in, stateid_t *ref) | 2795 | static 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; |
2819 | out: | ||
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; |