|
@@ -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_dp = NULL;
|
|
dp->dl_recall.cbr_ident = cb->cb_ident;
|
|
dp->dl_recall.cbr_ident = cb->cb_ident;
|
|
dp->dl_recall.cbr_trunc = 0;
|
|
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_stateownerid = current_delegid++;
|
|
dp->dl_stateid.si_fileid = 0;
|
|
dp->dl_stateid.si_fileid = 0;
|
|
dp->dl_stateid.si_generation = 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;
|
|
stp->st_stateowner = sop;
|
|
get_nfs4_file(fp);
|
|
get_nfs4_file(fp);
|
|
stp->st_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_stateownerid = sop->so_id;
|
|
stp->st_stateid.si_fileid = fp->fi_id;
|
|
stp->st_stateid.si_fileid = fp->fi_id;
|
|
stp->st_stateid.si_generation = 0;
|
|
stp->st_stateid.si_generation = 0;
|
|
@@ -2739,12 +2739,42 @@ nfs4_check_fh(struct svc_fh *fhp, struct nfs4_stateid *stp)
|
|
static int
|
|
static int
|
|
STALE_STATEID(stateid_t *stateid)
|
|
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
|
|
static inline int
|
|
@@ -2868,8 +2898,10 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
|
|
status = nfserr_bad_stateid;
|
|
status = nfserr_bad_stateid;
|
|
if (is_delegation_stateid(stateid)) {
|
|
if (is_delegation_stateid(stateid)) {
|
|
dp = find_delegation_stateid(ino, stateid);
|
|
dp = find_delegation_stateid(ino, stateid);
|
|
- if (!dp)
|
|
|
|
|
|
+ if (!dp) {
|
|
|
|
+ status = stateid_error_map(stateid);
|
|
goto out;
|
|
goto out;
|
|
|
|
+ }
|
|
status = check_stateid_generation(stateid, &dp->dl_stateid,
|
|
status = check_stateid_generation(stateid, &dp->dl_stateid,
|
|
flags);
|
|
flags);
|
|
if (status)
|
|
if (status)
|
|
@@ -2882,8 +2914,10 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
|
|
*filpp = dp->dl_vfs_file;
|
|
*filpp = dp->dl_vfs_file;
|
|
} else { /* open or lock stateid */
|
|
} else { /* open or lock stateid */
|
|
stp = find_stateid(stateid, flags);
|
|
stp = find_stateid(stateid, flags);
|
|
- if (!stp)
|
|
|
|
|
|
+ if (!stp) {
|
|
|
|
+ status = stateid_error_map(stateid);
|
|
goto out;
|
|
goto out;
|
|
|
|
+ }
|
|
if (nfs4_check_fh(current_fh, stp))
|
|
if (nfs4_check_fh(current_fh, stp))
|
|
goto out;
|
|
goto out;
|
|
if (!stp->st_stateowner->so_confirmed)
|
|
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);
|
|
sop = search_close_lru(stateid->si_stateownerid, flags);
|
|
if (sop == NULL)
|
|
if (sop == NULL)
|
|
- return nfserr_bad_stateid;
|
|
|
|
|
|
+ return stateid_error_map(stateid);
|
|
*sopp = sop;
|
|
*sopp = sop;
|
|
goto check_replay;
|
|
goto check_replay;
|
|
}
|
|
}
|
|
@@ -3228,8 +3262,10 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
if (!is_delegation_stateid(stateid))
|
|
if (!is_delegation_stateid(stateid))
|
|
goto out;
|
|
goto out;
|
|
dp = find_delegation_stateid(inode, stateid);
|
|
dp = find_delegation_stateid(inode, stateid);
|
|
- if (!dp)
|
|
|
|
|
|
+ if (!dp) {
|
|
|
|
+ status = stateid_error_map(stateid);
|
|
goto out;
|
|
goto out;
|
|
|
|
+ }
|
|
status = check_stateid_generation(stateid, &dp->dl_stateid, flags);
|
|
status = check_stateid_generation(stateid, &dp->dl_stateid, flags);
|
|
if (status)
|
|
if (status)
|
|
goto out;
|
|
goto out;
|
|
@@ -3456,7 +3492,7 @@ alloc_init_lock_stateid(struct nfs4_stateowner *sop, struct nfs4_file *fp, struc
|
|
stp->st_stateowner = sop;
|
|
stp->st_stateowner = sop;
|
|
get_nfs4_file(fp);
|
|
get_nfs4_file(fp);
|
|
stp->st_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_stateownerid = sop->so_id;
|
|
stp->st_stateid.si_fileid = fp->fi_id;
|
|
stp->st_stateid.si_fileid = fp->fi_id;
|
|
stp->st_stateid.si_generation = 0;
|
|
stp->st_stateid.si_generation = 0;
|