summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_extattr.c
diff options
context:
space:
mode:
authorjeff <jeff@FreeBSD.org>2002-08-21 03:55:35 +0000
committerjeff <jeff@FreeBSD.org>2002-08-21 03:55:35 +0000
commita9972cd35ac1c0c8bbc48e9de134af68e32a14ee (patch)
tree034467187e2ff6622dd0e3f48ecfafa26e89cd88 /sys/kern/vfs_extattr.c
parentaeba6a13e430ec0e07926ccf816584cb24e0c3c1 (diff)
downloadFreeBSD-src-a9972cd35ac1c0c8bbc48e9de134af68e32a14ee.zip
FreeBSD-src-a9972cd35ac1c0c8bbc48e9de134af68e32a14ee.tar.gz
- 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.
Diffstat (limited to 'sys/kern/vfs_extattr.c')
-rw-r--r--sys/kern/vfs_extattr.c35
1 files changed, 20 insertions, 15 deletions
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c
index c09fbd7..48c0151 100644
--- a/sys/kern/vfs_extattr.c
+++ b/sys/kern/vfs_extattr.c
@@ -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 @@ restart:
*
* 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);
OpenPOWER on IntegriCloud