summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/fs/fifofs
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/fs/fifofs')
-rw-r--r--usr/src/uts/common/fs/fifofs/fifosubr.c19
-rw-r--r--usr/src/uts/common/fs/fifofs/fifovnops.c40
2 files changed, 35 insertions, 24 deletions
diff --git a/usr/src/uts/common/fs/fifofs/fifosubr.c b/usr/src/uts/common/fs/fifofs/fifosubr.c
index 6e56000ffe..a908f91267 100644
--- a/usr/src/uts/common/fs/fifofs/fifosubr.c
+++ b/usr/src/uts/common/fs/fifofs/fifosubr.c
@@ -22,6 +22,7 @@
/*
* Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2017 Joyent, Inc.
*/
/*
@@ -61,7 +62,6 @@
#if FIFODEBUG
int Fifo_fastmode = 1; /* pipes/fifos will be opened in fast mode */
int Fifo_verbose = 0; /* msg when switching out of fast mode */
-int Fifohiwat = FIFOHIWAT; /* Modifiable FIFO high water mark */
#endif
/*
@@ -196,6 +196,7 @@ fnode_constructor(void *buf, void *cdrarg, int kmflags)
fnp->fn_dest = fnp;
fnp->fn_mp = NULL;
fnp->fn_count = 0;
+ fnp->fn_hiwat = FIFOHIWAT;
fnp->fn_rsynccnt = 0;
fnp->fn_wsynccnt = 0;
fnp->fn_wwaitcnt = 0;
@@ -388,11 +389,7 @@ fifoinit(int fstype, char *name)
pipe_constructor, pipe_destructor, NULL,
(void *)(sizeof (fifodata_t)), NULL, 0);
-#if FIFODEBUG
- if (Fifohiwat < FIFOHIWAT)
- Fifohiwat = FIFOHIWAT;
-#endif /* FIFODEBUG */
- fifo_strdata.qi_minfo->mi_hiwat = Fifohiwat;
+ fifo_strdata.qi_minfo->mi_hiwat = FIFOHIWAT;
return (0);
}
@@ -614,9 +611,12 @@ fifo_stropen(vnode_t **vpp, int flag, cred_t *crp, int dotwist, int lockheld)
/*
* The other end of the pipe is almost closed so
* reject any other open on this end of the pipe
- * This only happens with a pipe mounted under namefs
+ * This normally only happens with a pipe mounted under namefs, but
+ * we can also see an open via proc/fd, which should still succeed.
+ * To indicate the proc/fd case the FKLYR flag is passed.
*/
- if ((fnp->fn_flag & (FIFOCLOSE|ISPIPE)) == (FIFOCLOSE|ISPIPE)) {
+ if ((fnp->fn_flag & (FIFOCLOSE|ISPIPE)) == (FIFOCLOSE|ISPIPE) &&
+ (flag & FKLYR) == 0) {
fifo_cleanup(oldvp, flag);
cv_broadcast(&fnp->fn_wait_cv);
if (!lockheld)
@@ -1161,7 +1161,8 @@ fifo_wakewriter(fifonode_t *fn_dest, fifolock_t *fn_lock)
int fn_dflag = fn_dest->fn_flag;
ASSERT(MUTEX_HELD(&fn_lock->flk_lock));
- ASSERT(fn_dest->fn_dest->fn_count < Fifohiwat);
+ ASSERT(fn_dest->fn_dest->fn_count < fn_dest->fn_dest->fn_hiwat);
+
if ((fn_dflag & FIFOWANTW)) {
cv_broadcast(&fn_dest->fn_wait_cv);
}
diff --git a/usr/src/uts/common/fs/fifofs/fifovnops.c b/usr/src/uts/common/fs/fifofs/fifovnops.c
index c1b4652633..ceec9bd012 100644
--- a/usr/src/uts/common/fs/fifofs/fifovnops.c
+++ b/usr/src/uts/common/fs/fifofs/fifovnops.c
@@ -28,7 +28,7 @@
*/
/*
- * Copyright 2015, Joyent, Inc.
+ * Copyright 2017, Joyent, Inc.
* Copyright (c) 2017 by Delphix. All rights reserved.
*/
@@ -104,10 +104,6 @@ static int fifo_setsecattr(struct vnode *, vsecattr_t *, int, struct cred *,
static int fifo_getsecattr(struct vnode *, vsecattr_t *, int, struct cred *,
caller_context_t *);
-/* functions local to this file */
-static boolean_t fifo_stayfast_enter(fifonode_t *);
-static void fifo_stayfast_exit(fifonode_t *);
-
/*
* Define the data structures external to this file.
*/
@@ -645,7 +641,7 @@ fifo_close(vnode_t *vp, int flag, int count, offset_t offset, cred_t *crp,
* (3) write-only FIFO with no data
* (4) no data and FNDELAY flag is set.
* Otherwise return
- * EAGAIN if FNONBLOCK is set and no data to read
+ * EAGAIN if FNONBLOCK is set and no data to read or FIFORDBLOCK is set
* EINTR if signal received while waiting for data
*
* While there is no data to read....
@@ -681,7 +677,7 @@ fifo_read(struct vnode *vp, struct uio *uiop, int ioflag, struct cred *crp,
* Check for data on our input queue
*/
- while (fnp->fn_count == 0) {
+ while (fnp->fn_count == 0 || (fnp->fn_flag & FIFORDBLOCK) != 0) {
/*
* No data on first attempt and no writer, then EOF
*/
@@ -731,6 +727,7 @@ fifo_read(struct vnode *vp, struct uio *uiop, int ioflag, struct cred *crp,
}
ASSERT(fnp->fn_mp != NULL);
+ VERIFY((fnp->fn_flag & FIFORDBLOCK) == 0);
/* For pipes copy should not bypass cache */
uiop->uio_extflg |= UIO_COPY_CACHED;
@@ -772,6 +769,18 @@ fifo_read(struct vnode *vp, struct uio *uiop, int ioflag, struct cred *crp,
&fn_lock->flk_lock))
goto trywake;
+ /*
+ * If another thread snuck in and started to
+ * consume data using read-blocking out of
+ * the pipe while we were blocked in the
+ * cv_wait, then since we have already consumed
+ * some of the data out of the pipe we need
+ * to return with a short read.
+ */
+ if ((fnp->fn_flag & FIFORDBLOCK) != 0) {
+ goto trywake;
+ }
+
if (!(fnp->fn_flag & FIFOFAST))
goto stream_mode;
}
@@ -787,11 +796,11 @@ trywake:
/*
* wake up any blocked writers, processes
* sleeping on POLLWRNORM, or processes waiting for SIGPOLL
- * Note: checking for fn_count < Fifohiwat emulates
+ * Note: checking for fn_count < fn_hiwat emulates
* STREAMS functionality when low water mark is 0
*/
if (fn_dest->fn_flag & (FIFOWANTW | FIFOHIWATW) &&
- fnp->fn_count < Fifohiwat) {
+ fnp->fn_count < fn_dest->fn_hiwat) {
fifo_wakewriter(fn_dest, fn_lock);
}
goto done;
@@ -904,7 +913,7 @@ fifo_write(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *crp,
/*
* check to make sure we are not over high water mark
*/
- while (fn_dest->fn_count >= Fifohiwat) {
+ while (fn_dest->fn_count >= fn_dest->fn_hiwat) {
/*
* Indicate that we have gone over high
* water mark
@@ -962,7 +971,7 @@ fifo_write(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *crp,
* then we must break the message up into PIPE_BUF
* chunks to stay compliant with STREAMS
*/
- if (uiop->uio_resid + fn_dest->fn_count > Fifohiwat)
+ if (uiop->uio_resid + fn_dest->fn_count > fn_dest->fn_hiwat)
size = MIN(uiop->uio_resid, PIPE_BUF);
else
size = uiop->uio_resid;
@@ -1213,7 +1222,8 @@ fifo_fastioctl(vnode_t *vp, int cmd, intptr_t arg, int mode, cred_t *cr,
if (arg != 0) {
goto turn_fastoff;
}
- *rvalp = (fnp->fn_dest->fn_count < Fifohiwat) ? 1 : 0;
+ *rvalp = (fnp->fn_dest->fn_count < fnp->fn_dest->fn_hiwat) ?
+ 1 : 0;
mutex_exit(&fn_lock->flk_lock);
return (0);
@@ -1827,7 +1837,7 @@ fifo_poll(vnode_t *vp, short events, int anyyet, short *reventsp,
retevents = POLLHUP;
} else if (events & (POLLWRNORM | POLLWRBAND)) {
if (events & POLLWRNORM) {
- if (fn_dest->fn_count < Fifohiwat)
+ if (fn_dest->fn_count < fn_dest->fn_hiwat)
retevents = POLLWRNORM;
else
fnp->fn_flag |= FIFOHIWATW;
@@ -1996,7 +2006,7 @@ fifo_getsecattr(struct vnode *vp, vsecattr_t *vsap, int flag, struct cred *crp,
* the lock.
* If the fifo switches into stream mode while we are waiting, return failure.
*/
-static boolean_t
+boolean_t
fifo_stayfast_enter(fifonode_t *fnp)
{
ASSERT(MUTEX_HELD(&fnp->fn_lock->flk_lock));
@@ -2018,7 +2028,7 @@ fifo_stayfast_enter(fifonode_t *fnp)
* - threads wanting to turn into stream mode waiting in fifo_fastoff(),
* - other writers threads waiting in fifo_stayfast_enter().
*/
-static void
+void
fifo_stayfast_exit(fifonode_t *fnp)
{
fifonode_t *fn_dest = fnp->fn_dest;