fifo / named pipe patch testers wanted
Don Lewis
truckman at FreeBSD.org
Thu May 13 05:00:36 PDT 2004
Using the vnode mutex in fifo_open() causes lock order problems when
combined with some of the network stack locking changes that are in
progress. The patch below modifies fifo_open() to use a private mutex
in place of the vnode mutex. There is also some minor optimization of a
couple of calls to fifo_cleanup(). This patch has passed my torture
testing, but it could probably use some more testing by anyone who
heavily uses named pipes, especially with select(), kqueue(), and SIGIO.
Index: sys/fs/fifofs/fifo_vnops.c
===================================================================
RCS file: /home/ncvs/src/sys/fs/fifofs/fifo_vnops.c,v
retrieving revision 1.93
diff -u -r1.93 fifo_vnops.c
--- sys/fs/fifofs/fifo_vnops.c 7 Apr 2004 20:45:59 -0000 1.93
+++ sys/fs/fifofs/fifo_vnops.c 11 May 2004 03:03:39 -0000
@@ -122,6 +122,9 @@
VNODEOP_SET(fifo_vnodeop_opv_desc);
+struct mtx fifo_mtx;
+MTX_SYSINIT(fifo, &fifo_mtx, "fifo mutex", MTX_DEF);
+
int
fifo_vnoperate(ap)
struct vop_generic_args /* {
@@ -217,28 +220,25 @@
* the vnode lock.
*
* Protect the increment of fi_readers and fi_writers and the
- * associated calls to wakeup() with the vnode interlock in
- * addition to the vnode lock. This allows the vnode lock to
- * be dropped for the msleep() calls below, and using the vnode
- * interlock as the msleep() mutex prevents the wakeup from
- * being missed.
+ * 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.
*/
- VI_LOCK(vp);
+ mtx_lock(&fifo_mtx);
if (ap->a_mode & FREAD) {
fip->fi_readers++;
if (fip->fi_readers == 1) {
fip->fi_writesock->so_state &= ~SS_CANTSENDMORE;
if (fip->fi_writers > 0) {
wakeup(&fip->fi_writers);
- VI_UNLOCK(vp);
sowwakeup(fip->fi_writesock);
- VI_LOCK(vp);
}
}
}
if (ap->a_mode & FWRITE) {
if ((ap->a_mode & O_NONBLOCK) && fip->fi_readers == 0) {
- VI_UNLOCK(vp);
+ mtx_unlock(&fifo_mtx);
return (ENXIO);
}
fip->fi_writers++;
@@ -246,26 +246,25 @@
fip->fi_readsock->so_state &= ~SS_CANTRCVMORE;
if (fip->fi_readers > 0) {
wakeup(&fip->fi_readers);
- VI_UNLOCK(vp);
sorwakeup(fip->fi_writesock);
- VI_LOCK(vp);
}
}
}
if ((ap->a_mode & O_NONBLOCK) == 0) {
if ((ap->a_mode & FREAD) && fip->fi_writers == 0) {
VOP_UNLOCK(vp, 0, td);
- error = msleep(&fip->fi_readers, VI_MTX(vp),
- PCATCH | PSOCK, "fifoor", 0);
- vn_lock(vp, LK_EXCLUSIVE | LK_RETRY | LK_INTERLOCK, td);
+ error = msleep(&fip->fi_readers, &fifo_mtx,
+ PDROP | PCATCH | PSOCK, "fifoor", 0);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
if (error) {
fip->fi_readers--;
- if (fip->fi_readers == 0)
+ if (fip->fi_readers == 0) {
socantsendmore(fip->fi_writesock);
- fifo_cleanup(vp);
+ fifo_cleanup(vp);
+ }
return (error);
}
- VI_LOCK(vp);
+ mtx_lock(&fifo_mtx);
/*
* We must have got woken up because we had a writer.
* That (and not still having one) is the condition
@@ -274,15 +273,15 @@
}
if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) {
VOP_UNLOCK(vp, 0, td);
- error = msleep(&fip->fi_writers, VI_MTX(vp),
- PCATCH | PSOCK, "fifoow", 0);
- vn_lock(vp,
- LK_EXCLUSIVE | LK_RETRY | LK_INTERLOCK, td);
+ error = msleep(&fip->fi_writers, &fifo_mtx,
+ PDROP | PCATCH | PSOCK, "fifoow", 0);
+ vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
if (error) {
fip->fi_writers--;
- if (fip->fi_writers == 0)
+ if (fip->fi_writers == 0) {
socantrcvmore(fip->fi_readsock);
- fifo_cleanup(vp);
+ fifo_cleanup(vp);
+ }
return (error);
}
/*
@@ -293,7 +292,7 @@
return (0);
}
}
- VI_UNLOCK(vp);
+ mtx_unlock(&fifo_mtx);
return (0);
}
More information about the freebsd-current
mailing list