|
@@ -2183,7 +2183,8 @@ static struct lock_manager_operations nfsd_lease_mng_ops = {
|
|
|
|
|
|
|
|
|
|
__be32
|
|
__be32
|
|
-nfsd4_process_open1(struct nfsd4_open *open)
|
|
|
|
|
|
+nfsd4_process_open1(struct nfsd4_compound_state *cstate,
|
|
|
|
+ struct nfsd4_open *open)
|
|
{
|
|
{
|
|
clientid_t *clientid = &open->op_clientid;
|
|
clientid_t *clientid = &open->op_clientid;
|
|
struct nfs4_client *clp = NULL;
|
|
struct nfs4_client *clp = NULL;
|
|
@@ -2206,6 +2207,9 @@ nfsd4_process_open1(struct nfsd4_open *open)
|
|
return nfserr_expired;
|
|
return nfserr_expired;
|
|
goto renew;
|
|
goto renew;
|
|
}
|
|
}
|
|
|
|
+ /* When sessions are used, skip open sequenceid processing */
|
|
|
|
+ if (nfsd4_has_session(cstate))
|
|
|
|
+ goto renew;
|
|
if (!sop->so_confirmed) {
|
|
if (!sop->so_confirmed) {
|
|
/* Replace unconfirmed owners without checking for replay. */
|
|
/* Replace unconfirmed owners without checking for replay. */
|
|
clp = sop->so_client;
|
|
clp = sop->so_client;
|
|
@@ -2483,6 +2487,7 @@ out:
|
|
__be32
|
|
__be32
|
|
nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
|
|
nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
|
|
{
|
|
{
|
|
|
|
+ struct nfsd4_compoundres *resp = rqstp->rq_resp;
|
|
struct nfs4_file *fp = NULL;
|
|
struct nfs4_file *fp = NULL;
|
|
struct inode *ino = current_fh->fh_dentry->d_inode;
|
|
struct inode *ino = current_fh->fh_dentry->d_inode;
|
|
struct nfs4_stateid *stp = NULL;
|
|
struct nfs4_stateid *stp = NULL;
|
|
@@ -2541,9 +2546,14 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
|
|
release_open_stateid(stp);
|
|
release_open_stateid(stp);
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
|
|
+ if (nfsd4_has_session(&resp->cstate))
|
|
|
|
+ update_stateid(&stp->st_stateid);
|
|
}
|
|
}
|
|
memcpy(&open->op_stateid, &stp->st_stateid, sizeof(stateid_t));
|
|
memcpy(&open->op_stateid, &stp->st_stateid, sizeof(stateid_t));
|
|
|
|
|
|
|
|
+ if (nfsd4_has_session(&resp->cstate))
|
|
|
|
+ open->op_stateowner->so_confirmed = 1;
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* Attempt to hand out a delegation. No error return, because the
|
|
* Attempt to hand out a delegation. No error return, because the
|
|
* OPEN succeeds even if we fail.
|
|
* OPEN succeeds even if we fail.
|
|
@@ -2564,7 +2574,8 @@ out:
|
|
* To finish the open response, we just need to set the rflags.
|
|
* To finish the open response, we just need to set the rflags.
|
|
*/
|
|
*/
|
|
open->op_rflags = NFS4_OPEN_RESULT_LOCKTYPE_POSIX;
|
|
open->op_rflags = NFS4_OPEN_RESULT_LOCKTYPE_POSIX;
|
|
- if (!open->op_stateowner->so_confirmed)
|
|
|
|
|
|
+ if (!open->op_stateowner->so_confirmed &&
|
|
|
|
+ !nfsd4_has_session(&resp->cstate))
|
|
open->op_rflags |= NFS4_OPEN_RESULT_CONFIRM;
|
|
open->op_rflags |= NFS4_OPEN_RESULT_CONFIRM;
|
|
|
|
|
|
return status;
|
|
return status;
|
|
@@ -2781,8 +2792,15 @@ grace_disallows_io(struct inode *inode)
|
|
return locks_in_grace() && mandatory_lock(inode);
|
|
return locks_in_grace() && mandatory_lock(inode);
|
|
}
|
|
}
|
|
|
|
|
|
-static int check_stateid_generation(stateid_t *in, stateid_t *ref)
|
|
|
|
|
|
+static int check_stateid_generation(stateid_t *in, stateid_t *ref, int flags)
|
|
{
|
|
{
|
|
|
|
+ /*
|
|
|
|
+ * When sessions are used the stateid generation number is ignored
|
|
|
|
+ * when it is zero.
|
|
|
|
+ */
|
|
|
|
+ if ((flags & HAS_SESSION) && in->si_generation == 0)
|
|
|
|
+ goto out;
|
|
|
|
+
|
|
/* If the client sends us a stateid from the future, it's buggy: */
|
|
/* If the client sends us a stateid from the future, it's buggy: */
|
|
if (in->si_generation > ref->si_generation)
|
|
if (in->si_generation > ref->si_generation)
|
|
return nfserr_bad_stateid;
|
|
return nfserr_bad_stateid;
|
|
@@ -2798,6 +2816,7 @@ static int check_stateid_generation(stateid_t *in, stateid_t *ref)
|
|
*/
|
|
*/
|
|
if (in->si_generation < ref->si_generation)
|
|
if (in->si_generation < ref->si_generation)
|
|
return nfserr_old_stateid;
|
|
return nfserr_old_stateid;
|
|
|
|
+out:
|
|
return nfs_ok;
|
|
return nfs_ok;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -2825,6 +2844,9 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
|
|
if (grace_disallows_io(ino))
|
|
if (grace_disallows_io(ino))
|
|
return nfserr_grace;
|
|
return nfserr_grace;
|
|
|
|
|
|
|
|
+ if (nfsd4_has_session(cstate))
|
|
|
|
+ flags |= HAS_SESSION;
|
|
|
|
+
|
|
if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
|
|
if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
|
|
return check_special_stateids(current_fh, stateid, flags);
|
|
return check_special_stateids(current_fh, stateid, flags);
|
|
|
|
|
|
@@ -2837,7 +2859,8 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
|
|
dp = find_delegation_stateid(ino, stateid);
|
|
dp = find_delegation_stateid(ino, stateid);
|
|
if (!dp)
|
|
if (!dp)
|
|
goto out;
|
|
goto out;
|
|
- status = check_stateid_generation(stateid, &dp->dl_stateid);
|
|
|
|
|
|
+ status = check_stateid_generation(stateid, &dp->dl_stateid,
|
|
|
|
+ flags);
|
|
if (status)
|
|
if (status)
|
|
goto out;
|
|
goto out;
|
|
status = nfs4_check_delegmode(dp, flags);
|
|
status = nfs4_check_delegmode(dp, flags);
|
|
@@ -2854,7 +2877,8 @@ nfs4_preprocess_stateid_op(struct nfsd4_compound_state *cstate,
|
|
goto out;
|
|
goto out;
|
|
if (!stp->st_stateowner->so_confirmed)
|
|
if (!stp->st_stateowner->so_confirmed)
|
|
goto out;
|
|
goto out;
|
|
- status = check_stateid_generation(stateid, &stp->st_stateid);
|
|
|
|
|
|
+ status = check_stateid_generation(stateid, &stp->st_stateid,
|
|
|
|
+ flags);
|
|
if (status)
|
|
if (status)
|
|
goto out;
|
|
goto out;
|
|
status = nfs4_check_openmode(stp, flags);
|
|
status = nfs4_check_openmode(stp, flags);
|
|
@@ -2905,6 +2929,10 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
|
|
|
|
|
|
if (STALE_STATEID(stateid))
|
|
if (STALE_STATEID(stateid))
|
|
return nfserr_stale_stateid;
|
|
return nfserr_stale_stateid;
|
|
|
|
+
|
|
|
|
+ if (nfsd4_has_session(cstate))
|
|
|
|
+ flags |= HAS_SESSION;
|
|
|
|
+
|
|
/*
|
|
/*
|
|
* We return BAD_STATEID if filehandle doesn't match stateid,
|
|
* We return BAD_STATEID if filehandle doesn't match stateid,
|
|
* the confirmed flag is incorrecly set, or the generation
|
|
* the confirmed flag is incorrecly set, or the generation
|
|
@@ -2961,7 +2989,7 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
|
|
* For the moment, we ignore the possibility of
|
|
* For the moment, we ignore the possibility of
|
|
* generation number wraparound.
|
|
* generation number wraparound.
|
|
*/
|
|
*/
|
|
- if (seqid != sop->so_seqid)
|
|
|
|
|
|
+ if (!(flags & HAS_SESSION) && seqid != sop->so_seqid)
|
|
goto check_replay;
|
|
goto check_replay;
|
|
|
|
|
|
if (sop->so_confirmed && flags & CONFIRM) {
|
|
if (sop->so_confirmed && flags & CONFIRM) {
|
|
@@ -2974,7 +3002,7 @@ nfs4_preprocess_seqid_op(struct nfsd4_compound_state *cstate, u32 seqid,
|
|
" confirmed yet!\n");
|
|
" confirmed yet!\n");
|
|
return nfserr_bad_stateid;
|
|
return nfserr_bad_stateid;
|
|
}
|
|
}
|
|
- status = check_stateid_generation(stateid, &stp->st_stateid);
|
|
|
|
|
|
+ status = check_stateid_generation(stateid, &stp->st_stateid, flags);
|
|
if (status)
|
|
if (status)
|
|
return status;
|
|
return status;
|
|
renew_client(sop->so_client);
|
|
renew_client(sop->so_client);
|
|
@@ -3169,11 +3197,14 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
stateid_t *stateid = &dr->dr_stateid;
|
|
stateid_t *stateid = &dr->dr_stateid;
|
|
struct inode *inode;
|
|
struct inode *inode;
|
|
__be32 status;
|
|
__be32 status;
|
|
|
|
+ int flags = 0;
|
|
|
|
|
|
if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0)))
|
|
if ((status = fh_verify(rqstp, &cstate->current_fh, S_IFREG, 0)))
|
|
return status;
|
|
return status;
|
|
inode = cstate->current_fh.fh_dentry->d_inode;
|
|
inode = cstate->current_fh.fh_dentry->d_inode;
|
|
|
|
|
|
|
|
+ if (nfsd4_has_session(cstate))
|
|
|
|
+ flags |= HAS_SESSION;
|
|
nfs4_lock_state();
|
|
nfs4_lock_state();
|
|
status = nfserr_bad_stateid;
|
|
status = nfserr_bad_stateid;
|
|
if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
|
|
if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
|
|
@@ -3187,7 +3218,7 @@ nfsd4_delegreturn(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
|
|
dp = find_delegation_stateid(inode, stateid);
|
|
dp = find_delegation_stateid(inode, stateid);
|
|
if (!dp)
|
|
if (!dp)
|
|
goto out;
|
|
goto out;
|
|
- status = check_stateid_generation(stateid, &dp->dl_stateid);
|
|
|
|
|
|
+ status = check_stateid_generation(stateid, &dp->dl_stateid, flags);
|
|
if (status)
|
|
if (status)
|
|
goto out;
|
|
goto out;
|
|
renew_client(dp->dl_client);
|
|
renew_client(dp->dl_client);
|