nfsd: Fix handling of the error case for nfsvno_open
Using done_namei instead of ni_startdir did not fix the crashes reported in the PR. Upon looking more closely at the code, the only case where the code near the end of nfsvno_open() needs to be executed is when nfsvno_namei() has succeeded, but a subsequent error was detected. This patch uses done_namei to indicate this case. Also, nfsvno_relpathbuf() should only be called for this case and not whenever nfsvno_open() is called with nd_repstat != 0. A bug was introduced here when the HASBUF flag was deleted. Reviewed by: mjg PR: 268971 Tested by: ish@amail.plala.or.jp MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D38430
This commit is contained in:
parent
fa3f665542
commit
ded5f2954e
@ -1916,16 +1916,20 @@ nfsvno_open(struct nfsrv_descript *nd, struct nameidata *ndp,
|
||||
stateidp, stp, vp, nd, p, nd->nd_repstat);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else if (done_namei) {
|
||||
/*
|
||||
* done_namei is set when nfsvno_namei() has completed
|
||||
* successfully, but a subsequent error was set in
|
||||
* nd_repstat. As such, cleanup of the nfsvno_namei()
|
||||
* results is required.
|
||||
*/
|
||||
nfsvno_relpathbuf(ndp);
|
||||
if (done_namei && create == NFSV4OPEN_CREATE) {
|
||||
if (ndp->ni_dvp == ndp->ni_vp)
|
||||
vrele(ndp->ni_dvp);
|
||||
else
|
||||
vput(ndp->ni_dvp);
|
||||
if (ndp->ni_vp)
|
||||
vput(ndp->ni_vp);
|
||||
}
|
||||
if (ndp->ni_dvp == ndp->ni_vp)
|
||||
vrele(ndp->ni_dvp);
|
||||
else
|
||||
vput(ndp->ni_dvp);
|
||||
if (ndp->ni_vp)
|
||||
vput(ndp->ni_vp);
|
||||
}
|
||||
*vpp = vp;
|
||||
|
||||
|
@ -3043,7 +3043,6 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
|
||||
if (!nd->nd_repstat) {
|
||||
nd->nd_repstat = nfsvno_namei(nd, &named, dp, 0, exp,
|
||||
&dirp);
|
||||
done_namei = true;
|
||||
} else {
|
||||
vrele(dp);
|
||||
nfsvno_relpathbuf(&named);
|
||||
@ -3051,7 +3050,7 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
|
||||
if (create == NFSV4OPEN_CREATE) {
|
||||
switch (how) {
|
||||
case NFSCREATE_UNCHECKED:
|
||||
if (done_namei && named.ni_vp != NULL) {
|
||||
if (nd->nd_repstat == 0 && named.ni_vp != NULL) {
|
||||
/*
|
||||
* Clear the setable attribute bits, except
|
||||
* for Size, if it is being truncated.
|
||||
@ -3063,13 +3062,14 @@ nfsrvd_open(struct nfsrv_descript *nd, __unused int isdgram,
|
||||
}
|
||||
break;
|
||||
case NFSCREATE_GUARDED:
|
||||
if (done_namei && named.ni_vp != NULL &&
|
||||
nd->nd_repstat == 0)
|
||||
if (nd->nd_repstat == 0 && named.ni_vp != NULL) {
|
||||
nd->nd_repstat = EEXIST;
|
||||
done_namei = true;
|
||||
}
|
||||
break;
|
||||
case NFSCREATE_EXCLUSIVE:
|
||||
exclusive_flag = 1;
|
||||
if (done_namei && named.ni_vp == NULL)
|
||||
if (nd->nd_repstat == 0 && named.ni_vp == NULL)
|
||||
nva.na_mode = 0;
|
||||
break;
|
||||
case NFSCREATE_EXCLUSIVE41:
|
||||
|
Loading…
Reference in New Issue
Block a user