aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBian Naimeng <biannm@cn.fujitsu.com>2009-04-22 06:25:37 -0400
committerJ. Bruce Fields <bfields@citi.umich.edu>2009-04-24 19:17:18 -0400
commit78155ed75f470710f2aecb3e75e3d97107ba8374 (patch)
tree1a4b52cf0cd92ce7529036a3efa0eb4ad1bd2744
parenta9e61e25f9d2e7e43bf17625f5cb56c9e0a89b17 (diff)
nfsd4: distinguish expired from stale stateids
If we encode the time of client creation into the stateid instead of the time of server boot, then we can determine whether that stateid is from a previous instance of the a server, or from a client that has expired, and return an appropriate error to the client. Signed-off-by: Bian Naimeng <biannm@cn.fujitsu.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
-rw-r--r--fs/nfsd/nfs4state.c62
1 files changed, 49 insertions, 13 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index c65a27b76a9d..74e822ec34cb 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -206,7 +206,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
206 dp->dl_recall.cbr_dp = NULL; 206 dp->dl_recall.cbr_dp = NULL;
207 dp->dl_recall.cbr_ident = cb->cb_ident; 207 dp->dl_recall.cbr_ident = cb->cb_ident;
208 dp->dl_recall.cbr_trunc = 0; 208 dp->dl_recall.cbr_trunc = 0;
209 dp->dl_stateid.si_boot = boot_time; 209 dp->dl_stateid.si_boot = get_seconds();
210 dp->dl_stateid.si_stateownerid = current_delegid++; 210 dp->dl_stateid.si_stateownerid = current_delegid++;
211 dp->dl_stateid.si_fileid = 0; 211 dp->dl_stateid.si_fileid = 0;
212 dp->dl_stateid.si_generation = 0; 212 dp->dl_stateid.si_generation = 0;
@@ -1883,7 +1883,7 @@ init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *
1883 stp->st_stateowner = sop; 1883 stp->st_stateowner = sop;
1884 get_nfs4_file(fp); 1884 get_nfs4_file(fp);
1885 stp->st_file = fp; 1885 stp->st_file = fp;
1886 stp->st_stateid.si_boot = boot_time; 1886 stp->st_stateid.si_boot = get_seconds();
1887 stp->st_stateid.si_stateownerid = sop->so_id; 1887 stp->st_stateid.si_stateownerid = sop->so_id;
1888 stp->st_stateid.si_fileid = fp->fi_id; 1888 stp->st_stateid.si_fileid = fp->fi_id;
1889 stp->st_stateid.si_generation = 0; 1889 stp->st_stateid.si_generation = 0;
@@ -2739,12 +2739,42 @@ nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp)
2739static int 2739static int
2740STALE_STATEID(stateid_t *stateid) 2740STALE_STATEID(stateid_t *stateid)
2741{ 2741{
2742 if (stateid->si_boot == boot_time) 2742 if (time_after((unsigned long)boot_time,
2743 return 0; 2743 (unsigned long)stateid->si_boot)) {
2744 dprintk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n", 2744 dprintk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n",
2745 stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid, 2745 stateid->si_boot, stateid->si_stateownerid,
2746 stateid->si_generation); 2746 stateid->si_fileid, stateid->si_generation);
2747 return 1; 2747 return 1;
2748 }
2749 return 0;
2750}
2751
2752static int
2753EXPIRED_STATEID(stateid_t *stateid)
2754{
2755 if (time_before((unsigned long)boot_time,
2756 ((unsigned long)stateid->si_boot)) &&
2757 time_before((stateid->si_boot + lease_time), get_seconds())) {
2758 dprintk("NFSD: expired stateid (%08x/%08x/%08x/%08x)!\n",
2759 stateid->si_boot, stateid->si_stateownerid,
2760 stateid->si_fileid, stateid->si_generation);
2761 return 1;
2762 }
2763 return 0;
2764}
2765
2766static __be32
2767stateid_error_map(stateid_t *stateid)
2768{
2769 if (STALE_STATEID(stateid))
2770 return nfserr_stale_stateid;
2771 if (EXPIRED_STATEID(stateid))
2772 return nfserr_expired;
2773
2774 dprintk("NFSD: bad stateid (%08x/%08x/%08x/%08x)!\n",
2775 stateid->si_boot, stateid->si_stateownerid,
2776 stateid->si_fileid, stateid->si_generation);
2777 return nfserr_bad_stateid;
2748} 2778}
2749 2779
2750static inline int 2780static inline int
@@ -2868,8 +2898,10 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
2868 status = nfserr_bad_stateid; 2898 status = nfserr_bad_stateid;
2869 if (is_delegation_stateid(stateid)) { 2899 if (is_delegation_stateid(stateid)) {
2870 dp = find_delegation_stateid(ino, stateid); 2900 dp = find_delegation_stateid(ino, stateid);
2871 if (!dp) 2901 if (!dp) {
2902 status = stateid_error_map(stateid);
2872 goto out; 2903 goto out;
2904 }
2873 status = check_stateid_generation(stateid, &dp->dl_stateid, 2905 status = check_stateid_generation(stateid, &dp->dl_stateid,
2874 flags); 2906 flags);
2875 if (status) 2907 if (status)
@@ -2882,8 +2914,10 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
2882 *filpp = dp->dl_vfs_file; 2914 *filpp = dp->dl_vfs_file;
2883 } else { /* open or lock stateid */ 2915 } else { /* open or lock stateid */
2884 stp = find_stateid(stateid, flags); 2916 stp = find_stateid(stateid, flags);
2885 if (!stp) 2917 if (!stp) {
2918 status = stateid_error_map(stateid);
2886 goto out; 2919 goto out;
2920 }
2887 if (nfs4_check_fh(current_fh, stp)) 2921 if (nfs4_check_fh(current_fh, stp))
2888 goto out; 2922 goto out;
2889 if (!stp->st_stateowner->so_confirmed) 2923 if (!stp->st_stateowner->so_confirmed)
@@ -2957,7 +2991,7 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
2957 */ 2991 */
2958 sop = search_close_lru(stateid->si_stateownerid, flags); 2992 sop = search_close_lru(stateid->si_stateownerid, flags);
2959 if (sop == NULL) 2993 if (sop == NULL)
2960 return nfserr_bad_stateid; 2994 return stateid_error_map(stateid);
2961 *sopp = sop; 2995 *sopp = sop;
2962 goto check_replay; 2996 goto check_replay;
2963 } 2997 }
@@ -3228,8 +3262,10 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
3228 if (!is_delegation_stateid(stateid)) 3262 if (!is_delegation_stateid(stateid))
3229 goto out; 3263 goto out;
3230 dp = find_delegation_stateid(inode, stateid); 3264 dp = find_delegation_stateid(inode, stateid);
3231 if (!dp) 3265 if (!dp) {
3266 status = stateid_error_map(stateid);
3232 goto out; 3267 goto out;
3268 }
3233 status = check_stateid_generation(stateid, &dp->dl_stateid, flags); 3269 status = check_stateid_generation(stateid, &dp->dl_stateid, flags);
3234 if (status) 3270 if (status)
3235 goto out; 3271 goto out;
@@ -3456,7 +3492,7 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc
3456 stp->st_stateowner = sop; 3492 stp->st_stateowner = sop;
3457 get_nfs4_file(fp); 3493 get_nfs4_file(fp);
3458 stp->st_file = fp; 3494 stp->st_file = fp;
3459 stp->st_stateid.si_boot = boot_time; 3495 stp->st_stateid.si_boot = get_seconds();
3460 stp->st_stateid.si_stateownerid = sop->so_id; 3496 stp->st_stateid.si_stateownerid = sop->so_id;
3461 stp->st_stateid.si_fileid = fp->fi_id; 3497 stp->st_stateid.si_fileid = fp->fi_id;
3462 stp->st_stateid.si_generation = 0; 3498 stp->st_stateid.si_generation = 0;