|
@@ -3325,6 +3325,8 @@ static struct nfs4_delegation *find_deleg_stateid(struct nfs4_client *cl, statei
|
|
|
ret = find_stateid_by_type(cl, s, NFS4_DELEG_STID);
|
|
|
if (!ret)
|
|
|
return NULL;
|
|
|
+ /* FIXME: move into find_stateid_by_type */
|
|
|
+ atomic_inc(&ret->sc_count);
|
|
|
return delegstateid(ret);
|
|
|
}
|
|
|
|
|
@@ -3340,14 +3342,18 @@ nfs4_check_deleg(struct nfs4_client *cl, struct nfsd4_open *open,
|
|
|
{
|
|
|
int flags;
|
|
|
__be32 status = nfserr_bad_stateid;
|
|
|
+ struct nfs4_delegation *deleg;
|
|
|
|
|
|
- *dp = find_deleg_stateid(cl, &open->op_delegate_stateid);
|
|
|
- if (*dp == NULL)
|
|
|
+ deleg = find_deleg_stateid(cl, &open->op_delegate_stateid);
|
|
|
+ if (deleg == NULL)
|
|
|
goto out;
|
|
|
flags = share_access_to_flags(open->op_share_access);
|
|
|
- status = nfs4_check_delegmode(*dp, flags);
|
|
|
- if (status)
|
|
|
- *dp = NULL;
|
|
|
+ status = nfs4_check_delegmode(deleg, flags);
|
|
|
+ if (status) {
|
|
|
+ nfs4_put_stid(&deleg->dl_stid);
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+ *dp = deleg;
|
|
|
out:
|
|
|
if (!nfsd4_is_deleg_cur(open))
|
|
|
return nfs_ok;
|
|
@@ -3828,6 +3834,8 @@ out:
|
|
|
if (!(open->op_openowner->oo_flags & NFS4_OO_CONFIRMED) &&
|
|
|
!nfsd4_has_session(&resp->cstate))
|
|
|
open->op_rflags |= NFS4_OPEN_RESULT_CONFIRM;
|
|
|
+ if (dp)
|
|
|
+ nfs4_put_stid(&dp->dl_stid);
|
|
|
|
|
|
return status;
|
|
|
}
|