Skip to content

Commit 78155ed

Browse files
biannmJ. Bruce Fields
authored andcommitted
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 <[email protected]> Signed-off-by: J. Bruce Fields <[email protected]>
1 parent a9e61e2 commit 78155ed

File tree

1 file changed

+49
-13
lines changed

1 file changed

+49
-13
lines changed

fs/nfsd/nfs4state.c

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
206206
dp->dl_recall.cbr_dp = NULL;
207207
dp->dl_recall.cbr_ident = cb->cb_ident;
208208
dp->dl_recall.cbr_trunc = 0;
209-
dp->dl_stateid.si_boot = boot_time;
209+
dp->dl_stateid.si_boot = get_seconds();
210210
dp->dl_stateid.si_stateownerid = current_delegid++;
211211
dp->dl_stateid.si_fileid = 0;
212212
dp->dl_stateid.si_generation = 0;
@@ -1883,7 +1883,7 @@ init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *
18831883
stp->st_stateowner = sop;
18841884
get_nfs4_file(fp);
18851885
stp->st_file = fp;
1886-
stp->st_stateid.si_boot = boot_time;
1886+
stp->st_stateid.si_boot = get_seconds();
18871887
stp->st_stateid.si_stateownerid = sop->so_id;
18881888
stp->st_stateid.si_fileid = fp->fi_id;
18891889
stp->st_stateid.si_generation = 0;
@@ -2739,12 +2739,42 @@ nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp)
27392739
static int
27402740
STALE_STATEID(stateid_t *stateid)
27412741
{
2742-
if (stateid->si_boot == boot_time)
2743-
return 0;
2744-
dprintk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n",
2745-
stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid,
2746-
stateid->si_generation);
2747-
return 1;
2742+
if (time_after((unsigned long)boot_time,
2743+
(unsigned long)stateid->si_boot)) {
2744+
dprintk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n",
2745+
stateid->si_boot, stateid->si_stateownerid,
2746+
stateid->si_fileid, stateid->si_generation);
2747+
return 1;
2748+
}
2749+
return 0;
2750+
}
2751+
2752+
static int
2753+
EXPIRED_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+
2766+
static __be32
2767+
stateid_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;
27482778
}
27492779

27502780
static inline int
@@ -2868,8 +2898,10 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
28682898
status = nfserr_bad_stateid;
28692899
if (is_delegation_stateid(stateid)) {
28702900
dp = find_delegation_stateid(ino, stateid);
2871-
if (!dp)
2901+
if (!dp) {
2902+
status = stateid_error_map(stateid);
28722903
goto out;
2904+
}
28732905
status = check_stateid_generation(stateid, &dp->dl_stateid,
28742906
flags);
28752907
if (status)
@@ -2882,8 +2914,10 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
28822914
*filpp = dp->dl_vfs_file;
28832915
} else { /* open or lock stateid */
28842916
stp = find_stateid(stateid, flags);
2885-
if (!stp)
2917+
if (!stp) {
2918+
status = stateid_error_map(stateid);
28862919
goto out;
2920+
}
28872921
if (nfs4_check_fh(current_fh, stp))
28882922
goto out;
28892923
if (!stp->st_stateowner->so_confirmed)
@@ -2957,7 +2991,7 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
29572991
*/
29582992
sop = search_close_lru(stateid->si_stateownerid, flags);
29592993
if (sop == NULL)
2960-
return nfserr_bad_stateid;
2994+
return stateid_error_map(stateid);
29612995
*sopp = sop;
29622996
goto check_replay;
29632997
}
@@ -3228,8 +3262,10 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
32283262
if (!is_delegation_stateid(stateid))
32293263
goto out;
32303264
dp = find_delegation_stateid(inode, stateid);
3231-
if (!dp)
3265+
if (!dp) {
3266+
status = stateid_error_map(stateid);
32323267
goto out;
3268+
}
32333269
status = check_stateid_generation(stateid, &dp->dl_stateid, flags);
32343270
if (status)
32353271
goto out;
@@ -3456,7 +3492,7 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc
34563492
stp->st_stateowner = sop;
34573493
get_nfs4_file(fp);
34583494
stp->st_file = fp;
3459-
stp->st_stateid.si_boot = boot_time;
3495+
stp->st_stateid.si_boot = get_seconds();
34603496
stp->st_stateid.si_stateownerid = sop->so_id;
34613497
stp->st_stateid.si_fileid = fp->fi_id;
34623498
stp->st_stateid.si_generation = 0;

0 commit comments

Comments
 (0)