PERFORCE change 163701 for review
Zhao Shuai
zhaoshuai at FreeBSD.org
Sun Jun 7 11:22:39 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=163701
Change 163701 by zhaoshuai at 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 <sys/filedesc.h>
#include <sys/filio.h>
#include <sys/fcntl.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/unistd.h>
#include <sys/vnode.h>
@@ -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);
More information about the p4-projects
mailing list