Skip to content

Commit

Permalink
nfsd4: distinguish expired from stale stateids
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Bian Naimeng authored and J. Bruce Fields committed Apr 24, 2009
1 parent a9e61e2 commit 78155ed
Showing 1 changed file with 49 additions and 13 deletions.
62 changes: 49 additions & 13 deletions fs/nfsd/nfs4state.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_stateid *stp, struct svc_f
dp->dl_recall.cbr_dp = NULL;
dp->dl_recall.cbr_ident = cb->cb_ident;
dp->dl_recall.cbr_trunc = 0;
dp->dl_stateid.si_boot = boot_time;
dp->dl_stateid.si_boot = get_seconds();
dp->dl_stateid.si_stateownerid = current_delegid++;
dp->dl_stateid.si_fileid = 0;
dp->dl_stateid.si_generation = 0;
Expand Down Expand Up @@ -1883,7 +1883,7 @@ init_stateid(struct nfs4_stateid *stp, struct nfs4_file *fp, struct nfsd4_open *
stp->st_stateowner = sop;
get_nfs4_file(fp);
stp->st_file = fp;
stp->st_stateid.si_boot = boot_time;
stp->st_stateid.si_boot = get_seconds();
stp->st_stateid.si_stateownerid = sop->so_id;
stp->st_stateid.si_fileid = fp->fi_id;
stp->st_stateid.si_generation = 0;
Expand Down Expand Up @@ -2739,12 +2739,42 @@ nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp)
static int
STALE_STATEID(stateid_t *stateid)
{
if (stateid->si_boot == boot_time)
return 0;
dprintk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n",
stateid->si_boot, stateid->si_stateownerid, stateid->si_fileid,
stateid->si_generation);
return 1;
if (time_after((unsigned long)boot_time,
(unsigned long)stateid->si_boot)) {
dprintk("NFSD: stale stateid (%08x/%08x/%08x/%08x)!\n",
stateid->si_boot, stateid->si_stateownerid,
stateid->si_fileid, stateid->si_generation);
return 1;
}
return 0;
}

static int
EXPIRED_STATEID(stateid_t *stateid)
{
if (time_before((unsigned long)boot_time,
((unsigned long)stateid->si_boot)) &&
time_before((stateid->si_boot + lease_time), get_seconds())) {
dprintk("NFSD: expired stateid (%08x/%08x/%08x/%08x)!\n",
stateid->si_boot, stateid->si_stateownerid,
stateid->si_fileid, stateid->si_generation);
return 1;
}
return 0;
}

static __be32
stateid_error_map(stateid_t *stateid)
{
if (STALE_STATEID(stateid))
return nfserr_stale_stateid;
if (EXPIRED_STATEID(stateid))
return nfserr_expired;

dprintk("NFSD: bad stateid (%08x/%08x/%08x/%08x)!\n",
stateid->si_boot, stateid->si_stateownerid,
stateid->si_fileid, stateid->si_generation);
return nfserr_bad_stateid;
}

static inline int
Expand Down Expand Up @@ -2868,8 +2898,10 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
status = nfserr_bad_stateid;
if (is_delegation_stateid(stateid)) {
dp = find_delegation_stateid(ino, stateid);
if (!dp)
if (!dp) {
status = stateid_error_map(stateid);
goto out;
}
status = check_stateid_generation(stateid, &dp->dl_stateid,
flags);
if (status)
Expand All @@ -2882,8 +2914,10 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
*filpp = dp->dl_vfs_file;
} else { /* open or lock stateid */
stp = find_stateid(stateid, flags);
if (!stp)
if (!stp) {
status = stateid_error_map(stateid);
goto out;
}
if (nfs4_check_fh(current_fh, stp))
goto out;
if (!stp->st_stateowner->so_confirmed)
Expand Down Expand Up @@ -2957,7 +2991,7 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
*/
sop = search_close_lru(stateid->si_stateownerid, flags);
if (sop == NULL)
return nfserr_bad_stateid;
return stateid_error_map(stateid);
*sopp = sop;
goto check_replay;
}
Expand Down Expand Up @@ -3228,8 +3262,10 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
if (!is_delegation_stateid(stateid))
goto out;
dp = find_delegation_stateid(inode, stateid);
if (!dp)
if (!dp) {
status = stateid_error_map(stateid);
goto out;
}
status = check_stateid_generation(stateid, &dp->dl_stateid, flags);
if (status)
goto out;
Expand Down Expand Up @@ -3456,7 +3492,7 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc
stp->st_stateowner = sop;
get_nfs4_file(fp);
stp->st_file = fp;
stp->st_stateid.si_boot = boot_time;
stp->st_stateid.si_boot = get_seconds();
stp->st_stateid.si_stateownerid = sop->so_id;
stp->st_stateid.si_fileid = fp->fi_id;
stp->st_stateid.si_generation = 0;
Expand Down

0 comments on commit 78155ed

Please sign in to comment.