diff options
-rw-r--r-- | fs/nfsd/nfs4state.c | 62 |
1 files changed, 49 insertions, 13 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index c65a27b..74e822e 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 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; @@ -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; @@ -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 @@ -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) @@ -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) @@ -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; } @@ -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; @@ -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; |