Skip to content

Commit

Permalink
OS-6275 lx pipe buffer is too small
Browse files Browse the repository at this point in the history
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Approved by: Jason King <jason.king@joyent.com>
  • Loading branch information
jjelinek committed Sep 5, 2017
1 parent 9105a02 commit 58cb943
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 26 deletions.
33 changes: 31 additions & 2 deletions usr/src/uts/common/brand/lx/syscall/lx_pipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ lx_pipe_setsz(stdata_t *str, uint_t size, boolean_t is_init)
stdata_t *mate;
lx_zone_data_t *lxzd = ztolxzd(curzone);
uint_t max_size = lxzd->lxzd_pipe_max_sz;

fifonode_t *fnp1, *fnp2;

size = P2ROUNDUP(size, PAGESIZE);
if (size == 0) {
Expand Down Expand Up @@ -94,7 +94,14 @@ lx_pipe_setsz(stdata_t *str, uint_t size, boolean_t is_init)
}

if (!STRMATED(str)) {
return (strqset(RD(str->sd_wrq), QHIWAT, 0, (intptr_t)size));
err = strqset(RD(str->sd_wrq), QHIWAT, 0, (intptr_t)size);
if (err == 0) {
fnp1 = VTOF(str->sd_vnode);
mutex_enter(&fnp1->fn_lock->flk_lock);
fnp1->fn_hiwat = size;
mutex_exit(&fnp1->fn_lock->flk_lock);
}
return (err);
}

/*
Expand All @@ -116,6 +123,28 @@ lx_pipe_setsz(stdata_t *str, uint_t size, boolean_t is_init)
if ((err = strqset(RD(str->sd_wrq), QHIWAT, 0, (intptr_t)size)) == 0) {
err = strqset(RD(mate->sd_wrq), QHIWAT, 0, (intptr_t)size);
}

if (err == 0) {
fnp1 = VTOF(str->sd_vnode);
fnp2 = VTOF(str->sd_mate->sd_vnode);

/*
* See fnode_constructor. Both sides should have the same
* lock. We expect our callers to ensure that the vnodes
* are VFIFO and have v_op == fifovnops.
*/
ASSERT(str->sd_vnode->v_type == VFIFO);
ASSERT(str->sd_mate->sd_vnode->v_type == VFIFO);
ASSERT(fnp1->fn_lock == fnp2->fn_lock);

mutex_enter(&fnp1->fn_lock->flk_lock);

fnp1->fn_hiwat = size;
fnp2->fn_hiwat = size;

mutex_exit(&fnp1->fn_lock->flk_lock);
}

return (err);
}

Expand Down
12 changes: 5 additions & 7 deletions usr/src/uts/common/fs/fifofs/fifosubr.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

/*
* Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2017 Joyent, Inc.
*/

/*
Expand Down Expand Up @@ -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

/*
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -1164,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);
}
Expand Down
15 changes: 8 additions & 7 deletions usr/src/uts/common/fs/fifofs/fifovnops.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
*/

/*
* Copyright 2015, Joyent, Inc.
* Copyright 2017, Joyent, Inc.
* Copyright (c) 2017 by Delphix. All rights reserved.
*/

Expand Down Expand Up @@ -787,11 +787,11 @@ fifo_read(struct vnode *vp, struct uio *uiop, int ioflag, struct cred *crp,
/*
* 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;
Expand Down Expand Up @@ -904,7 +904,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
Expand Down Expand Up @@ -962,7 +962,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;
Expand Down Expand Up @@ -1198,7 +1198,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);

Expand Down Expand Up @@ -1817,7 +1818,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;
Expand Down
12 changes: 2 additions & 10 deletions usr/src/uts/common/sys/fs/fifonode.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2017 Joyent, Inc.
*/

/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
Expand Down Expand Up @@ -83,6 +84,7 @@ struct fifonode {
struct msgb *fn_tail; /* last message to read */
fifolock_t *fn_lock; /* pointer to per fifo lock */
uint_t fn_count; /* Number of bytes on fn_mp */
uint_t fn_hiwat; /* pipe (fifofast) high water */
kcondvar_t fn_wait_cv; /* fifo conditional variable */
ushort_t fn_wcnt; /* number of writers */
ushort_t fn_rcnt; /* number of readers */
Expand Down Expand Up @@ -147,16 +149,6 @@ typedef struct fifodata {

#if defined(_KERNEL)

/*
* Fifohiwat defined as a variable is to allow tuning of the high
* water mark if needed. It is not meant to be released.
*/
#if FIFODEBUG
extern int Fifohiwat;
#else /* FIFODEBUG */
#define Fifohiwat FIFOHIWAT
#endif /* FIFODEBUG */

extern struct vnodeops *fifo_vnodeops;
extern const struct fs_operation_def fifo_vnodeops_template[];
extern struct kmem_cache *fnode_cache;
Expand Down

0 comments on commit 58cb943

Please sign in to comment.