From owner-p4-projects@FreeBSD.ORG Sun Jun 7 11:22:39 2009 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id DDC921065676; Sun, 7 Jun 2009 11:22:37 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 9C574106564A for ; Sun, 7 Jun 2009 11:22:37 +0000 (UTC) (envelope-from zhaoshuai@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 886108FC1F for ; Sun, 7 Jun 2009 11:22:37 +0000 (UTC) (envelope-from zhaoshuai@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.3/8.14.3) with ESMTP id n57BMbu5086189 for ; Sun, 7 Jun 2009 11:22:37 GMT (envelope-from zhaoshuai@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.3/8.14.3/Submit) id n57BMb1A086187 for perforce@freebsd.org; Sun, 7 Jun 2009 11:22:37 GMT (envelope-from zhaoshuai@FreeBSD.org) Date: Sun, 7 Jun 2009 11:22:37 GMT Message-Id: <200906071122.n57BMb1A086187@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to zhaoshuai@FreeBSD.org using -f From: Zhao Shuai To: Perforce Change Reviews Cc: Subject: PERFORCE change 163701 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 07 Jun 2009 11:22:39 -0000 http://perforce.freebsd.org/chv.cgi?CH=163701 Change 163701 by zhaoshuai@zhaoshuai on 2009/06/07 11:21:54 add O_NONBLOCK handling in fifo_open() Affected files ... .. //depot/projects/soc2009/fifo/sys/fs/fifofs/fifo_vnops.c#9 edit Differences ... ==== //depot/projects/soc2009/fifo/sys/fs/fifofs/fifo_vnops.c#9 (text+ko) ==== @@ -40,6 +40,8 @@ #include #include #include +#include +#include #include #include #include @@ -114,6 +116,9 @@ .vop_write = VOP_PANIC, }; +struct mtx fifo_mtx; +MTX_SYSINIT(fifo, &fifo_mtx, "fifo mutex", MTX_DEF); + /* * Open called to set up a new instance of a fifo or * to find an active instance of a fifo. @@ -155,15 +160,77 @@ /* * General access to fi_readers and fi_writers is protected using * the vnode lock. + * + * Protect the increment of fi_readers and fi_writers and the + * associated calls to wakeup() with the fifo mutex in addition + * to the vnode lock. This allows the vnode lock to be dropped + * for the msleep() calls below, and using the fifo mutex with + * msleep() prevents the wakeup from being missed. */ - if (ap->a_mode & FREAD) + mtx_lock(&fifo_mtx); + if (ap->a_mode & FREAD) { fip->fi_readers++; + if (fip->fi_readers == 1 && fip->fi_writers > 0) + wakeup(&fip->fi_writers); + } if (ap->a_mode & FWRITE) { if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) return (ENXIO); fip->fi_writers++; + if (fip->fi_writers == 1 && fip->fi_readers > 0) + wakeup(&fip->fi_readers); } - + if ((ap->a_mode & O_NONBLOCK) == 0) { + if ((ap->a_mode & FREAD) && fip->fi_writers == 0) { + VOP_UNLOCK(vp, 0); + error = msleep(&fip->fi_readers, &fifo_mtx, + PDROP | PCATCH, "fifoor", 0); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + if (error) { + fip->fi_readers--; + if (fip->fi_readers == 0) { + generic_pipe_close(fip->fi_rpipe); + if (fip->fi_writers == 0) { + generic_pipe_close(fip->fi_wpipe); + vp->v_fifoinfo = NULL; + free(fip, M_VNODE); + } + } + return (error); + } + mtx_lock(&fifo_mtx); + /* + * We must have got woken up because we had a writer. + * That (and not still having one) is the condition + * that we must wait for. + */ + } + if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) { + VOP_UNLOCK(vp, 0); + error = msleep(&fip->fi_writers, &fifo_mtx, + PDROP | PCATCH, "fifoow", 0); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + if (error) { + fip->fi_writers--; + if (fip->fi_writers == 0) { + generic_pipe_close(fip->fi_wpipe); + if (fip->fi_readers == 0) { + generic_pipe_close(fip->fi_rpipe); + vp->v_fifoinfo = NULL; + free(fip, M_VNODE); + } + } + return (error); + } + /* + * We must have got woken up because we had + * a reader. That (and not still having one) + * is the condition that we must wait for. + */ + mtx_lock(&fifo_mtx); + } + } + mtx_unlock(&fifo_mtx); KASSERT(fp != NULL, ("can't fifo/vnode bypass")); KASSERT(fp->f_ops == &badfileops, ("not badfileops in fifo_open")); finit(fp, fp->f_flag, DTYPE_FIFO, fip, &fifo_ops_f);