Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 29 Jan 2009 10:40:47 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org
Subject:   svn commit: r187883 - in stable/7/sys: . contrib/pf dev/cxgb kern
Message-ID:  <200901291040.n0TAel2s051461@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200901291040.n0TAel2s051461>