diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c --- a/sys/fs/nfsserver/nfs_nfsdport.c +++ b/sys/fs/nfsserver/nfs_nfsdport.c @@ -1916,16 +1916,20 @@ 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; diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c --- a/sys/fs/nfsserver/nfs_nfsdserv.c +++ b/sys/fs/nfsserver/nfs_nfsdserv.c @@ -3043,7 +3043,6 @@ 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 @@ 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 @@ } 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: