svn commit: r187883 - in stable/7/sys: . contrib/pf dev/cxgb kern
Konstantin Belousov
kib at FreeBSD.org
Thu Jan 29 02:40:49 PST 2009
Author: kib
Date: Thu Jan 29 10:40:47 2009
New Revision: 187883
URL: http://svn.freebsd.org/changeset/base/187883
Log:
MFC r186896:
Do not call namei() while having another user-controlled vnode
locked. Lookup could attempt to recursively lock that vnode.
Do not call vn_start_write(V_WAIT) while vnode is locked, this may
result in a deadlock with suspension.
vfs_busy() the mountpoint before dropping vnode lock for vnode
that was used to look up the mountpoint, to prevent unmount in
between.
Modified:
stable/7/sys/ (props changed)
stable/7/sys/contrib/pf/ (props changed)
stable/7/sys/dev/cxgb/ (props changed)
stable/7/sys/kern/vfs_extattr.c
Modified: stable/7/sys/kern/vfs_extattr.c
==============================================================================
--- stable/7/sys/kern/vfs_extattr.c Thu Jan 29 10:33:32 2009 (r187882)
+++ stable/7/sys/kern/vfs_extattr.c Thu Jan 29 10:40:47 2009 (r187883)
@@ -86,52 +86,65 @@ extattrctl(td, uap)
AUDIT_ARG(text, attrname);
vfslocked = fnvfslocked = 0;
- /*
- * uap->filename is not always defined. If it is, grab a vnode lock,
- * which VFS_EXTATTRCTL() will later release.
- */
+ mp = NULL;
filename_vp = NULL;
if (uap->filename != NULL) {
- NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | LOCKLEAF |
- AUDITVNODE2, UIO_USERSPACE, uap->filename, td);
+ NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE2,
+ UIO_USERSPACE, uap->filename, td);
error = namei(&nd);
if (error)
return (error);
fnvfslocked = NDHASGIANT(&nd);
filename_vp = nd.ni_vp;
- NDFREE(&nd, NDF_NO_VP_RELE | NDF_NO_VP_UNLOCK);
+ NDFREE(&nd, NDF_NO_VP_RELE);
}
/* uap->path is always defined. */
- NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | AUDITVNODE1, UIO_USERSPACE,
- uap->path, td);
+ NDINIT(&nd, LOOKUP, MPSAFE | FOLLOW | LOCKLEAF | AUDITVNODE1,
+ UIO_USERSPACE, uap->path, td);
error = namei(&nd);
- if (error) {
- if (filename_vp != NULL)
- vput(filename_vp);
+ if (error)
goto out;
- }
vfslocked = NDHASGIANT(&nd);
mp = nd.ni_vp->v_mount;
- error = vn_start_write(nd.ni_vp, &mp_writable, V_WAIT | PCATCH);
- NDFREE(&nd, 0);
+ error = vfs_busy(mp, 0, NULL, td);
if (error) {
- if (filename_vp != NULL)
- vput(filename_vp);
+ NDFREE(&nd, 0);
+ mp = NULL;
goto out;
}
+ VOP_UNLOCK(nd.ni_vp, 0, td);
+ error = vn_start_write(nd.ni_vp, &mp_writable, V_WAIT | PCATCH);
+ NDFREE(&nd, NDF_NO_VP_UNLOCK);
+ if (error)
+ goto out;
+ if (filename_vp != NULL) {
+ /*
+ * uap->filename is not always defined. If it is,
+ * grab a vnode lock, which VFS_EXTATTRCTL() will
+ * later release.
+ */
+ error = vn_lock(filename_vp, LK_EXCLUSIVE, td);
+ if (error) {
+ vn_finished_write(mp_writable);
+ goto out;
+ }
+ }
error = VFS_EXTATTRCTL(mp, uap->cmd, filename_vp, uap->attrnamespace,
uap->attrname != NULL ? attrname : NULL, td);
vn_finished_write(mp_writable);
+out:
+ if (mp != NULL)
+ vfs_unbusy(mp, td);
+
/*
* VFS_EXTATTRCTL will have unlocked, but not de-ref'd, filename_vp,
* so vrele it if it is defined.
*/
if (filename_vp != NULL)
vrele(filename_vp);
-out:
VFS_UNLOCK_GIANT(fnvfslocked);
VFS_UNLOCK_GIANT(vfslocked);
return (error);
More information about the svn-src-stable-7
mailing list