svn commit: r186561 - head/sys/fs/pseudofs

Konstantin Belousov kib at FreeBSD.org
Mon Dec 29 12:12:23 UTC 2008


Author: kib
Date: Mon Dec 29 12:12:23 2008
New Revision: 186561
URL: http://svn.freebsd.org/changeset/base/186561

Log:
  Drop the pseudofs vnode lock around call to pfs_read handler. The handler
  may need to lock arbitrary vnodes, causing either lock order reversal or
  recursive vnode lock acquisition.
  
  Tested by:	pho
  Approved by:	des
  MFC after:	2 weeks

Modified:
  head/sys/fs/pseudofs/pseudofs_vnops.c

Modified: head/sys/fs/pseudofs/pseudofs_vnops.c
==============================================================================
--- head/sys/fs/pseudofs/pseudofs_vnops.c	Mon Dec 29 12:07:18 2008	(r186560)
+++ head/sys/fs/pseudofs/pseudofs_vnops.c	Mon Dec 29 12:12:23 2008	(r186561)
@@ -476,7 +476,7 @@ pfs_read(struct vop_read_args *va)
 	struct uio *uio = va->a_uio;
 	struct proc *proc;
 	struct sbuf *sb = NULL;
-	int error;
+	int error, locked;
 	unsigned int buflen, offset, resid;
 
 	PFS_TRACE(("%s", pn->pn_name));
@@ -502,13 +502,15 @@ pfs_read(struct vop_read_args *va)
 		PROC_UNLOCK(proc);
 	}
 
+	vhold(vn);
+	locked = VOP_ISLOCKED(vn);
+	VOP_UNLOCK(vn, 0);
+
 	if (pn->pn_flags & PFS_RAWRD) {
 		PFS_TRACE(("%lu resid", (unsigned long)uio->uio_resid));
 		error = pn_fill(curthread, proc, pn, NULL, uio);
 		PFS_TRACE(("%lu resid", (unsigned long)uio->uio_resid));
-		if (proc != NULL)
-			PRELE(proc);
-		PFS_RETURN (error);
+		goto ret;
 	}
 
 	/* beaucoup sanity checks so we don't ask for bogus allocation */
@@ -518,34 +520,35 @@ pfs_read(struct vop_read_args *va)
 	    (buflen = offset + resid + 1) < offset || buflen > INT_MAX) {
 		if (proc != NULL)
 			PRELE(proc);
-		PFS_RETURN (EINVAL);
+		error = EINVAL;
+		goto ret;
 	}
 	if (buflen > MAXPHYS + 1) {
-		if (proc != NULL)
-			PRELE(proc);
-		PFS_RETURN (EIO);
+		error = EIO;
+		goto ret;
 	}
 
 	sb = sbuf_new(sb, NULL, buflen, 0);
 	if (sb == NULL) {
-		if (proc != NULL)
-			PRELE(proc);
-		PFS_RETURN (EIO);
+		error = EIO;
+		goto ret;
 	}
 
 	error = pn_fill(curthread, proc, pn, sb, uio);
 
-	if (proc != NULL)
-		PRELE(proc);
-
 	if (error) {
 		sbuf_delete(sb);
-		PFS_RETURN (error);
+		goto ret;
 	}
 
 	sbuf_finish(sb);
 	error = uiomove_frombuf(sbuf_data(sb), sbuf_len(sb), uio);
 	sbuf_delete(sb);
+ret:
+	vn_lock(vn, locked | LK_RETRY);
+	vdrop(vn);
+	if (proc != NULL)
+		PRELE(proc);
 	PFS_RETURN (error);
 }
 


More information about the svn-src-head mailing list