|
@@ -4016,7 +4016,8 @@ static struct nfs4_delegation *find_deleg_stateid(struct nfs4_client *cl, statei
|
|
|
{
|
|
|
struct nfs4_stid *ret;
|
|
|
|
|
|
- ret = find_stateid_by_type(cl, s, NFS4_DELEG_STID);
|
|
|
+ ret = find_stateid_by_type(cl, s,
|
|
|
+ NFS4_DELEG_STID|NFS4_REVOKED_DELEG_STID);
|
|
|
if (!ret)
|
|
|
return NULL;
|
|
|
return delegstateid(ret);
|
|
@@ -4039,6 +4040,12 @@ nfs4_check_deleg(struct nfs4_client *cl, struct nfsd4_open *open,
|
|
|
deleg = find_deleg_stateid(cl, &open->op_delegate_stateid);
|
|
|
if (deleg == NULL)
|
|
|
goto out;
|
|
|
+ if (deleg->dl_stid.sc_type == NFS4_REVOKED_DELEG_STID) {
|
|
|
+ nfs4_put_stid(&deleg->dl_stid);
|
|
|
+ if (cl->cl_minorversion)
|
|
|
+ status = nfserr_deleg_revoked;
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
flags = share_access_to_flags(open->op_share_access);
|
|
|
status = nfs4_check_delegmode(deleg, flags);
|
|
|
if (status) {
|
|
@@ -4908,6 +4915,16 @@ nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate,
|
|
|
struct nfs4_stid **s, struct nfsd_net *nn)
|
|
|
{
|
|
|
__be32 status;
|
|
|
+ bool return_revoked = false;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * only return revoked delegations if explicitly asked.
|
|
|
+ * otherwise we report revoked or bad_stateid status.
|
|
|
+ */
|
|
|
+ if (typemask & NFS4_REVOKED_DELEG_STID)
|
|
|
+ return_revoked = true;
|
|
|
+ else if (typemask & NFS4_DELEG_STID)
|
|
|
+ typemask |= NFS4_REVOKED_DELEG_STID;
|
|
|
|
|
|
if (ZERO_STATEID(stateid) || ONE_STATEID(stateid))
|
|
|
return nfserr_bad_stateid;
|
|
@@ -4922,6 +4939,12 @@ nfsd4_lookup_stateid(struct nfsd4_compound_state *cstate,
|
|
|
*s = find_stateid_by_type(cstate->clp, stateid, typemask);
|
|
|
if (!*s)
|
|
|
return nfserr_bad_stateid;
|
|
|
+ if (((*s)->sc_type == NFS4_REVOKED_DELEG_STID) && !return_revoked) {
|
|
|
+ nfs4_put_stid(*s);
|
|
|
+ if (cstate->minorversion)
|
|
|
+ return nfserr_deleg_revoked;
|
|
|
+ return nfserr_bad_stateid;
|
|
|
+ }
|
|
|
return nfs_ok;
|
|
|
}
|
|
|
|