- Hold the vnode lock across unlink() so that the v_vflag check is safe.

- Fix the long broken error handling for VV_ROOT and VDIR.
This commit is contained in:
jeff 2002-08-21 03:55:35 +00:00
parent aeba6a13e4
commit a9972cd35a
2 changed files with 40 additions and 30 deletions

View File

@ -1142,7 +1142,8 @@ unlink(td, uap)
restart:
bwillwrite();
NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td);
NDINIT(&nd, DELETE, LOCKPARENT|LOCKLEAF, UIO_USERSPACE,
SCARG(uap, path), td);
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
@ -1154,28 +1155,32 @@ unlink(td, uap)
*
* XXX: can this only be a VDIR case?
*/
mp_fixme("Accessing vflags w/o the vn lock.");
if (vp->v_vflag & VV_ROOT)
error = EBUSY;
}
if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
NDFREE(&nd, NDF_ONLY_PNBUF);
vrele(vp);
vput(nd.ni_dvp);
if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
return (error);
goto restart;
}
VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
if (!error) {
if (error == 0) {
if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
NDFREE(&nd, NDF_ONLY_PNBUF);
if (vp == nd.ni_dvp)
vrele(vp);
else
vput(vp);
vput(nd.ni_dvp);
if ((error = vn_start_write(NULL, &mp,
V_XSLEEP | PCATCH)) != 0)
return (error);
goto restart;
}
VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
vn_finished_write(mp);
}
NDFREE(&nd, NDF_ONLY_PNBUF);
if (vp == nd.ni_dvp)
vrele(vp);
else
vput(vp);
vput(nd.ni_dvp);
vput(vp);
vn_finished_write(mp);
ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink");
ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink");
return (error);

View File

@ -1142,7 +1142,8 @@ unlink(td, uap)
restart:
bwillwrite();
NDINIT(&nd, DELETE, LOCKPARENT, UIO_USERSPACE, SCARG(uap, path), td);
NDINIT(&nd, DELETE, LOCKPARENT|LOCKLEAF, UIO_USERSPACE,
SCARG(uap, path), td);
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
@ -1154,28 +1155,32 @@ unlink(td, uap)
*
* XXX: can this only be a VDIR case?
*/
mp_fixme("Accessing vflags w/o the vn lock.");
if (vp->v_vflag & VV_ROOT)
error = EBUSY;
}
if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
NDFREE(&nd, NDF_ONLY_PNBUF);
vrele(vp);
vput(nd.ni_dvp);
if ((error = vn_start_write(NULL, &mp, V_XSLEEP | PCATCH)) != 0)
return (error);
goto restart;
}
VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
if (!error) {
if (error == 0) {
if (vn_start_write(nd.ni_dvp, &mp, V_NOWAIT) != 0) {
NDFREE(&nd, NDF_ONLY_PNBUF);
if (vp == nd.ni_dvp)
vrele(vp);
else
vput(vp);
vput(nd.ni_dvp);
if ((error = vn_start_write(NULL, &mp,
V_XSLEEP | PCATCH)) != 0)
return (error);
goto restart;
}
VOP_LEASE(nd.ni_dvp, td, td->td_ucred, LEASE_WRITE);
error = VOP_REMOVE(nd.ni_dvp, vp, &nd.ni_cnd);
vn_finished_write(mp);
}
NDFREE(&nd, NDF_ONLY_PNBUF);
if (vp == nd.ni_dvp)
vrele(vp);
else
vput(vp);
vput(nd.ni_dvp);
vput(vp);
vn_finished_write(mp);
ASSERT_VOP_UNLOCKED(nd.ni_dvp, "unlink");
ASSERT_VOP_UNLOCKED(nd.ni_vp, "unlink");
return (error);