Date: Mon, 29 Dec 2008 12:12:23 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r186561 - head/sys/fs/pseudofs Message-ID: <200812291212.mBTCCN0I056860@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200812291212.mBTCCN0I056860>