Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 31 Jan 2004 21:23:46 -0500 (EST)
From:      Robert Watson <rwatson@FreeBSD.org>
To:        current@FreeBSD.org
Subject:   Coalescing pipe allocation
Message-ID:  <Pine.NEB.3.96L.1040131211448.17012A-100000@fledge.watson.org>

next in thread | raw e-mail | index | archive | help

I was recently doing some system call benchmarking, and was a little
surprised to find that allocating pipes takes a lot more time than
allocating sockets.  It turns out a lot of this cost is associated with
registering for VM mappings in the pipe map.  However, some of it is due
to performing several memory allocations for each pipe:

(1) Allocate the read pipe (zone allocation)
(2) Allocate the write pipe (zone allocation)
(3) Allocate a shared mutex (malloc)

The attached patch uses a single zone to hold 'struct pipepair', which
contains two struct pipes (each direction), and the mutex, as well as the
MAC label pointer.  The result is about the same amount of storage (got to
take out mutex pointers, reduced to one MAC label pointer, but gained two
flags fields and pipe pair back pointers).  However, it does give me an 8%
or 9% performance improvement on 10,000 iterations of the following
micro-benchmark: 

        for (i = 0; i < num; i++) {
                int fd[2];
                if (pipe(fd) == -1) {
                        perror("pipe");
                        exit(-1);
                }

                close(fd[0]);
                close(fd[1]);
        }

This change does have one disadvantage: previously, we would free each
half of the pipe after it was closed, so we'd release slightly under half
the pipe structure memory on half close.  If the environment keeps around
a lot of half-closed pipes, that might be an observable difference.  On
the other hand, with this patch, the kmem mappings for the pipe buffers
are *not* cached by UMA, and are released on half-close, so the vast
majority of memory is released on half-close.  The result is that close()
is also a bit faster.

Much of the remaining cost of allocating pipes appears to come from the
cost of setting up the VM mappings.  I think it would make sense to also
cache those using UMA, perhaps with the pipepair structures, perhaps not.
This is slightly complicated by the use of a smaller number of big pipes
that, when expended, give way to small pipes.  I imagine this would have a
substantial further cost savings, and will experiment with that tonight --
however, it presupposes the attached change first.

I have not yet macro-benchmarked this change.  It will either have a
slight performance benefit if half-closed pipes aren't used extensively or
it doesn't make a difference, be a wash, or if half-closed pipes turn up a
lot, potentially slightly negatively impact performance (seems unlikely). 
I'll look at a bit of macro-benchmarking this evening as well.  However,
I'd appreciate any review of the current patch in the mean time :-).  A
large chunk of this patch is MAC-related, and I'll be doing separate
testing for that later also.  Most reviewers will probably want to ignore
that.

Robert N M Watson             FreeBSD Core Team, TrustedBSD Projects
robert@fledge.watson.org      Senior Research Scientist, McAfee Research

--- //depot/vendor/freebsd/src/sys/kern/kern_mac.c	2003/11/16 15:35:29
+++ //depot/user/rwatson/pipe/sys/kern/kern_mac.c	2004/01/31 15:47:02
@@ -745,7 +745,7 @@
 		pipe = fp->f_data;
 		intlabel = mac_pipe_label_alloc();
 		PIPE_LOCK(pipe);
-		mac_copy_pipe_label(pipe->pipe_label, intlabel);
+		mac_copy_pipe_label(pipe->pipe_pair->pp_label, intlabel);
 		PIPE_UNLOCK(pipe);
 		error = mac_externalize_pipe_label(intlabel, elements,
 		    buffer, mac.m_buflen);
@@ -953,8 +953,8 @@
 		if (error == 0) {
 			pipe = fp->f_data;
 			PIPE_LOCK(pipe);
-			error = mac_pipe_label_set(td->td_ucred, pipe,
-			    intlabel);
+			error = mac_pipe_label_set(td->td_ucred,
+			    pipe->pipe_pair, intlabel);
 			PIPE_UNLOCK(pipe);
 		}
 		mac_pipe_label_free(intlabel);
--- //depot/vendor/freebsd/src/sys/kern/sys_pipe.c	2004/01/31 15:05:28
+++ //depot/user/rwatson/pipe/sys/kern/sys_pipe.c	2004/01/31 18:13:59
@@ -179,7 +179,7 @@
 static void pipeinit(void *dummy __unused);
 static void pipeclose(struct pipe *cpipe);
 static void pipe_free_kmem(struct pipe *cpipe);
-static int pipe_create(struct pipe **cpipep);
+static int pipe_create(struct pipe *pipe);
 static __inline int pipelock(struct pipe *cpipe, int catch);
 static __inline void pipeunlock(struct pipe *cpipe);
 static __inline void pipeselwakeup(struct pipe *cpipe);
@@ -191,6 +191,11 @@
 #endif
 static int pipespace(struct pipe *cpipe, int size);
 
+static void	pipe_zone_ctor(void *mem, int size, void *arg);
+static void	pipe_zone_dtor(void *mem, int size, void *arg);
+static void	pipe_zone_init(void *mem, int size);
+static void	pipe_zone_fini(void *mem, int size);
+
 static uma_zone_t pipe_zone;
 
 SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_ANY, pipeinit, NULL);
@@ -199,13 +204,96 @@
 pipeinit(void *dummy __unused)
 {
 
-	pipe_zone = uma_zcreate("PIPE", sizeof(struct pipe), NULL,
-	    NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
+	pipe_zone = uma_zcreate("PIPE", sizeof(struct pipepair),
+	    pipe_zone_ctor, pipe_zone_dtor, pipe_zone_init, pipe_zone_fini,
+	    UMA_ALIGN_PTR, 0);
 	KASSERT(pipe_zone != NULL, ("pipe_zone not initialized"));
 }
 
+static void
+pipe_zone_ctor(void *mem, int size, void *arg)
+{
+	struct pipepair *pp;
+	struct pipe *rpipe, *wpipe;
+
+	KASSERT(size == sizeof(*pp), ("pipe_zone_ctor: wrong size"));
+
+	pp = (struct pipepair *)mem;
+
+	/*
+	 * We zero both pipe endpoints to make sure all the kmem pointers
+	 * are NULL, flag fields are zero'd, etc.  We timestamp both
+	 * endpoints with the same time.
+	 */
+	rpipe = &pp->pp_rpipe;
+	bzero(rpipe, sizeof(*rpipe));
+	vfs_timestamp(&rpipe->pipe_ctime);
+	rpipe->pipe_atime = rpipe->pipe_mtime = rpipe->pipe_ctime;
+
+	wpipe = &pp->pp_wpipe;
+	bzero(wpipe, sizeof(*wpipe));
+	wpipe->pipe_ctime = rpipe->pipe_ctime;
+	wpipe->pipe_atime = wpipe->pipe_mtime = rpipe->pipe_ctime;
+
+	rpipe->pipe_peer = wpipe;
+	rpipe->pipe_pair = pp;
+	wpipe->pipe_peer = rpipe;
+	wpipe->pipe_pair = pp;
+
+	/*
+	 * Mark both endpoints as present; they will later get free'd
+	 * one at a time.  When both are free'd, then the whole pair
+	 * is released.
+	 */
+	rpipe->pipe_present = 1;
+	wpipe->pipe_present = 1;
+
+	/*
+	 * Eventually, the MAC Framework may initialize the label
+	 * in ctor or init, but for now we do it elswhere to avoid
+	 * blocking in ctor or init.
+	 */
+	pp->pp_label = NULL;
+
+}
+
+static void
+pipe_zone_dtor(void *mem, int size, void *arg)
+{
+	struct pipepair *pp;
+
+	KASSERT(size == sizeof(*pp), ("pipe_zone_dtor: wrong size"));
+
+	pp = (struct pipepair *)mem;
+}
+
+static void
+pipe_zone_init(void *mem, int size)
+{
+	struct pipepair *pp;
+
+	KASSERT(size == sizeof(*pp), ("pipe_zone_init: wrong size"));
+
+	pp = (struct pipepair *)mem;
+
+	mtx_init(&pp->pp_mtx, "pipe mutex", NULL, MTX_DEF | MTX_RECURSE);
+}
+
+static void
+pipe_zone_fini(void *mem, int size)
+{
+	struct pipepair *pp;
+
+	KASSERT(size == sizeof(*pp), ("pipe_zone_fini: wrong size"));
+
+	pp = (struct pipepair *)mem;
+
+	mtx_destroy(&pp->pp_mtx);
+}
+
 /*
- * The pipe system call for the DTYPE_PIPE type of pipes
+ * The pipe system call for the DTYPE_PIPE type of pipes.  If we fail,
+ * let the zone pick up the pieces via pipeclose().
  */
 
 /* ARGSUSED */
@@ -218,12 +306,25 @@
 {
 	struct filedesc *fdp = td->td_proc->p_fd;
 	struct file *rf, *wf;
+	struct pipepair *pp;
 	struct pipe *rpipe, *wpipe;
-	struct mtx *pmtx;
 	int fd, error;
 
-	rpipe = wpipe = NULL;
-	if (pipe_create(&rpipe) || pipe_create(&wpipe)) {
+	pp = uma_zalloc(pipe_zone, M_WAITOK);
+#ifdef MAC
+	/*
+	 * struct pipe represents a pipe endpoint.  The MAC label is shared
+	 * between the connected endpoints.  As a result mac_init_pipe() and
+	 * mac_create_pipe() should only be called on one of the endpoints
+	 * after they have been connected.
+	 */
+	mac_init_pipe(pp);
+	mac_create_pipe(td->td_ucred, pp);
+#endif
+	rpipe = &pp->pp_rpipe;
+	wpipe = &pp->pp_wpipe;
+
+	if (pipe_create(rpipe) || pipe_create(wpipe)) {
 		pipeclose(rpipe);
 		pipeclose(wpipe);
 		return (ENFILE);
@@ -278,21 +379,6 @@
 	FILE_UNLOCK(wf);
 	fdrop(wf, td);
 	td->td_retval[1] = fd;
-	rpipe->pipe_peer = wpipe;
-	wpipe->pipe_peer = rpipe;
-#ifdef MAC
-	/*
-	 * struct pipe represents a pipe endpoint.  The MAC label is shared
-	 * between the connected endpoints.  As a result mac_init_pipe() and
-	 * mac_create_pipe() should only be called on one of the endpoints
-	 * after they have been connected.
-	 */
-	mac_init_pipe(rpipe);
-	mac_create_pipe(td->td_ucred, rpipe);
-#endif
-	pmtx = malloc(sizeof(*pmtx), M_TEMP, M_WAITOK | M_ZERO);
-	mtx_init(pmtx, "pipe mutex", NULL, MTX_DEF | MTX_RECURSE);
-	rpipe->pipe_mtxp = wpipe->pipe_mtxp = pmtx;
 	fdrop(rf, td);
 
 	return (0);
@@ -314,8 +400,7 @@
 	static int curfail = 0;
 	static struct timeval lastfail;
 
-	KASSERT(cpipe->pipe_mtxp == NULL || !mtx_owned(PIPE_MTX(cpipe)),
-	       ("pipespace: pipe mutex locked"));
+	KASSERT(!mtx_owned(PIPE_MTX(cpipe)), ("pipespace: pipe mutex locked"));
 
 	size = round_page(size);
 	/*
@@ -349,60 +434,28 @@
 }
 
 /*
- * initialize and allocate VM and memory for pipe
+ * Initialize and allocate VM and memory for pipe.  The structure
+ * will start out zero'd from the ctor, so we just manage the kmem.
  */
 static int
-pipe_create(cpipep)
-	struct pipe **cpipep;
+pipe_create(pipe)
+	struct pipe *pipe;
 {
-	struct pipe *cpipe;
 	int error;
 
-	*cpipep = uma_zalloc(pipe_zone, M_WAITOK);
-	if (*cpipep == NULL)
-		return (ENOMEM);
-
-	cpipe = *cpipep;
-
-	/*
-	 * protect so pipeclose() doesn't follow a junk pointer
-	 * if pipespace() fails.
-	 */
-	bzero(&cpipe->pipe_sel, sizeof(cpipe->pipe_sel));
-	cpipe->pipe_state = 0;
-	cpipe->pipe_peer = NULL;
-	cpipe->pipe_busy = 0;
-
-#ifndef PIPE_NODIRECT
-	/*
-	 * pipe data structure initializations to support direct pipe I/O
-	 */
-	cpipe->pipe_map.cnt = 0;
-	cpipe->pipe_map.kva = 0;
-	cpipe->pipe_map.pos = 0;
-	cpipe->pipe_map.npages = 0;
-	/* cpipe->pipe_map.ms[] = invalid */
-#endif
-
-	cpipe->pipe_mtxp = NULL;	/* avoid pipespace assertion */
 	/*
 	 * Reduce to 1/4th pipe size if we're over our global max.
 	 */
 	if (amountpipekva > maxpipekva / 2)
-		error = pipespace(cpipe, SMALL_PIPE_SIZE);
+		error = pipespace(pipe, SMALL_PIPE_SIZE);
 	else
-		error = pipespace(cpipe, PIPE_SIZE);
+		error = pipespace(pipe, PIPE_SIZE);
 	if (error)
 		return (error);
 
-	vfs_timestamp(&cpipe->pipe_ctime);
-	cpipe->pipe_atime = cpipe->pipe_ctime;
-	cpipe->pipe_mtime = cpipe->pipe_ctime;
-
 	return (0);
 }
 
-
 /*
  * lock a pipe for I/O, blocking other access
  */
@@ -477,7 +530,7 @@
 		goto unlocked_error;
 
 #ifdef MAC
-	error = mac_check_pipe_read(active_cred, rpipe);
+	error = mac_check_pipe_read(active_cred, rpipe->pipe_pair);
 	if (error)
 		goto locked_error;
 #endif
@@ -890,7 +943,7 @@
 		return (EPIPE);
 	}
 #ifdef MAC
-	error = mac_check_pipe_write(active_cred, wpipe);
+	error = mac_check_pipe_write(active_cred, wpipe->pipe_pair);
 	if (error) {
 		PIPE_UNLOCK(rpipe);
 		return (error);
@@ -1180,7 +1233,7 @@
 	PIPE_LOCK(mpipe);
 
 #ifdef MAC
-	error = mac_check_pipe_ioctl(active_cred, mpipe, cmd, data);
+	error = mac_check_pipe_ioctl(active_cred, mpipe->pipe_pair, cmd, data);
 	if (error) {
 		PIPE_UNLOCK(mpipe);
 		return (error);
@@ -1252,7 +1305,7 @@
 	wpipe = rpipe->pipe_peer;
 	PIPE_LOCK(rpipe);
 #ifdef MAC
-	error = mac_check_pipe_poll(active_cred, rpipe);
+	error = mac_check_pipe_poll(active_cred, rpipe->pipe_pair);
 	if (error)
 		goto locked_error;
 #endif
@@ -1308,7 +1361,7 @@
 	int error;
 
 	PIPE_LOCK(pipe);
-	error = mac_check_pipe_stat(active_cred, pipe);
+	error = mac_check_pipe_stat(active_cred, pipe->pipe_pair);
 	PIPE_UNLOCK(pipe);
 	if (error)
 		return (error);
@@ -1350,8 +1403,8 @@
 	struct pipe *cpipe;
 {
 
-	KASSERT(cpipe->pipe_mtxp == NULL || !mtx_owned(PIPE_MTX(cpipe)),
-	       ("pipe_free_kmem: pipe mutex locked"));
+	KASSERT(!mtx_owned(PIPE_MTX(cpipe)),
+	    ("pipe_free_kmem: pipe mutex locked"));
 
 	if (cpipe->pipe_buffer.buffer != NULL) {
 		if (cpipe->pipe_buffer.size > PIPE_SIZE)
@@ -1385,17 +1438,15 @@
 pipeclose(cpipe)
 	struct pipe *cpipe;
 {
+	struct pipepair *pp;
 	struct pipe *ppipe;
 	int hadpeer;
 
-	if (cpipe == NULL)
-		return;
+	KASSERT(cpipe != NULL, ("pipeclose: cpipe == NULL"));
 
 	hadpeer = 0;
-
-	/* partially created pipes won't have a valid mutex. */
-	if (PIPE_MTX(cpipe) != NULL)
-		PIPE_LOCK(cpipe);
+	PIPE_LOCK(cpipe);
+	pp = cpipe->pipe_pair;
 
 	pipeselwakeup(cpipe);
 
@@ -1409,35 +1460,43 @@
 		msleep(cpipe, PIPE_MTX(cpipe), PRIBIO, "pipecl", 0);
 	}
 
-#ifdef MAC
-	if (cpipe->pipe_label != NULL && cpipe->pipe_peer == NULL)
-		mac_destroy_pipe(cpipe);
-#endif
 
 	/*
-	 * Disconnect from peer
+	 * Disconnect from peer, if any.
 	 */
-	if ((ppipe = cpipe->pipe_peer) != NULL) {
+	ppipe = cpipe->pipe_peer;
+	if (ppipe->pipe_present != 0) {
 		hadpeer++;
 		pipeselwakeup(ppipe);
 
 		ppipe->pipe_state |= PIPE_EOF;
 		wakeup(ppipe);
 		KNOTE(&ppipe->pipe_sel.si_note, 0);
-		ppipe->pipe_peer = NULL;
 	}
+
 	/*
-	 * free resources
+	 * Mark this endpoint as free.  Release kmem resources.  We
+	 * don't mark this endpoint as unused until we've finished
+	 * doing that, or the pipe might disappear out from under
+	 * us.
+	 */
+	PIPE_UNLOCK(cpipe);
+	pipe_free_kmem(cpipe);
+	PIPE_LOCK(cpipe);
+	cpipe->pipe_present = 0;
+
+	/*
+	 * If both endpoints are now closed, release the memory for the
+	 * pipe pair.  If not, unlock.
 	 */
-	if (PIPE_MTX(cpipe) != NULL) {
+	if (ppipe->pipe_present == 0) {
+		PIPE_UNLOCK(cpipe);
+#ifdef MAC
+		mac_pipe_destroy(pp);
+#endif
+		uma_zfree(pipe_zone, cpipe->pipe_pair);
+	} else
 		PIPE_UNLOCK(cpipe);
-		if (!hadpeer) {
-			mtx_destroy(PIPE_MTX(cpipe));
-			free(PIPE_MTX(cpipe), M_TEMP);
-		}
-	}
-	pipe_free_kmem(cpipe);
-	uma_zfree(pipe_zone, cpipe);
 }
 
 /*ARGSUSED*/
--- //depot/vendor/freebsd/src/sys/security/mac/mac_pipe.c	2003/11/11 19:15:41
+++ //depot/user/rwatson/pipe/sys/security/mac/mac_pipe.c	2004/01/31 15:47:02
@@ -73,11 +73,10 @@
 }
 
 void
-mac_init_pipe(struct pipe *pipe)
+mac_init_pipe(struct pipepair *pp)
 {
 
-	pipe->pipe_label = pipe->pipe_peer->pipe_label =
-	    mac_pipe_label_alloc();
+	pp->pp_label = mac_pipe_label_alloc();
 }
 
 void
@@ -90,11 +89,11 @@
 }
 
 void
-mac_destroy_pipe(struct pipe *pipe)
+mac_destroy_pipe(struct pipepair *pp)
 {
 
-	mac_pipe_label_free(pipe->pipe_label);
-	pipe->pipe_label = NULL;
+	mac_pipe_label_free(pp->pp_label);
+	pp->pp_label = NULL;
 }
 
 void
@@ -126,123 +125,125 @@
 }
 
 void
-mac_create_pipe(struct ucred *cred, struct pipe *pipe)
+mac_create_pipe(struct ucred *cred, struct pipepair *pp)
 {
 
-	MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
+	MAC_PERFORM(create_pipe, cred, pp, pp->pp_label);
 }
 
 static void
-mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel)
+mac_relabel_pipe(struct ucred *cred, struct pipepair *pp,
+    struct label *newlabel)
 {
 
-	MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel);
+	MAC_PERFORM(relabel_pipe, cred, pp, pp->pp_label, newlabel);
 }
 
 int
-mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
-    void *data)
+mac_check_pipe_ioctl(struct ucred *cred, struct pipepair *pp,
+    unsigned long cmd, void *data)
 {
 	int error;
 
-	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
+	mtx_assert(&pp->pp_mtx, MA_OWNED);
 
 	if (!mac_enforce_pipe)
 		return (0);
 
-	MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
+	MAC_CHECK(check_pipe_ioctl, cred, pp, pp->pp_label, cmd, data);
 
 	return (error);
 }
 
 int
-mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
+mac_check_pipe_poll(struct ucred *cred, struct pipepair *pp)
 {
 	int error;
 
-	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
+	mtx_assert(&pp->pp_mtx, MA_OWNED);
 
 	if (!mac_enforce_pipe)
 		return (0);
 
-	MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
+	MAC_CHECK(check_pipe_poll, cred, pp, pp->pp_label);
 
 	return (error);
 }
 
 int
-mac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
+mac_check_pipe_read(struct ucred *cred, struct pipepair *pp)
 {
 	int error;
 
-	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
+	mtx_assert(&pp->pp_mtx, MA_OWNED);
 
 	if (!mac_enforce_pipe)
 		return (0);
 
-	MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
+	MAC_CHECK(check_pipe_read, cred, pp, pp->pp_label);
 
 	return (error);
 }
 
 static int
-mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
+mac_check_pipe_relabel(struct ucred *cred, struct pipepair *pp,
     struct label *newlabel)
 {
 	int error;
 
-	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
+	mtx_assert(&pp->pp_mtx, MA_OWNED);
 
 	if (!mac_enforce_pipe)
 		return (0);
 
-	MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
+	MAC_CHECK(check_pipe_relabel, cred, pp, pp->pp_label, newlabel);
 
 	return (error);
 }
 
 int
-mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
+mac_check_pipe_stat(struct ucred *cred, struct pipepair *pp)
 {
 	int error;
 
-	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
+	mtx_assert(&pp->pp_mtx, MA_OWNED);
 
 	if (!mac_enforce_pipe)
 		return (0);
 
-	MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
+	MAC_CHECK(check_pipe_stat, cred, pp, pp->pp_label);
 
 	return (error);
 }
 
 int
-mac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
+mac_check_pipe_write(struct ucred *cred, struct pipepair *pp)
 {
 	int error;
 
-	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
+	mtx_assert(&pp->pp_mtx, MA_OWNED);
 
 	if (!mac_enforce_pipe)
 		return (0);
 
-	MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
+	MAC_CHECK(check_pipe_write, cred, pp, pp->pp_label);
 
 	return (error);
 }
 
 int
-mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
+mac_pipe_label_set(struct ucred *cred, struct pipepair *pp,
+    struct label *label)
 {
 	int error;
 
-	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
+	mtx_assert(&pp->pp_mtx, MA_OWNED);
 
-	error = mac_check_pipe_relabel(cred, pipe, label);
+	error = mac_check_pipe_relabel(cred, pp, label);
 	if (error)
 		return (error);
 
-	mac_relabel_pipe(cred, pipe, label);
+	mac_relabel_pipe(cred, pp, label);
 
 	return (0);
 }
--- //depot/vendor/freebsd/src/sys/security/mac_biba/mac_biba.c	2003/12/17 06:55:44
+++ //depot/user/rwatson/pipe/sys/security/mac_biba/mac_biba.c	2004/01/31 15:47:02
@@ -1017,7 +1017,7 @@
 }
 
 static void
-mac_biba_create_pipe(struct ucred *cred, struct pipe *pipe,
+mac_biba_create_pipe(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel)
 {
 	struct mac_biba *source, *dest;
@@ -1054,7 +1054,7 @@
 }
 
 static void
-mac_biba_relabel_pipe(struct ucred *cred, struct pipe *pipe,
+mac_biba_relabel_pipe(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel, struct label *newlabel)
 {
 	struct mac_biba *source, *dest;
@@ -1588,7 +1588,7 @@
 }
 
 static int
-mac_biba_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe,
+mac_biba_check_pipe_ioctl(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data)
 {
 
@@ -1601,7 +1601,7 @@
 }
 
 static int
-mac_biba_check_pipe_poll(struct ucred *cred, struct pipe *pipe,
+mac_biba_check_pipe_poll(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel)
 {
 	struct mac_biba *subj, *obj;
@@ -1619,7 +1619,7 @@
 }
 
 static int
-mac_biba_check_pipe_read(struct ucred *cred, struct pipe *pipe,
+mac_biba_check_pipe_read(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel)
 {
 	struct mac_biba *subj, *obj;
@@ -1637,7 +1637,7 @@
 }
 
 static int
-mac_biba_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
+mac_biba_check_pipe_relabel(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel, struct label *newlabel)
 {
 	struct mac_biba *subj, *obj, *new;
@@ -1688,7 +1688,7 @@
 }
 
 static int
-mac_biba_check_pipe_stat(struct ucred *cred, struct pipe *pipe,
+mac_biba_check_pipe_stat(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel)
 {
 	struct mac_biba *subj, *obj;
@@ -1706,7 +1706,7 @@
 }
 
 static int
-mac_biba_check_pipe_write(struct ucred *cred, struct pipe *pipe,
+mac_biba_check_pipe_write(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel)
 {
 	struct mac_biba *subj, *obj;
--- //depot/vendor/freebsd/src/sys/security/mac_lomac/mac_lomac.c	2003/12/17 06:55:44
+++ //depot/user/rwatson/pipe/sys/security/mac_lomac/mac_lomac.c	2004/01/31 15:47:02
@@ -1156,7 +1156,7 @@
 }
 
 static void
-mac_lomac_create_pipe(struct ucred *cred, struct pipe *pipe,
+mac_lomac_create_pipe(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel)
 {
 	struct mac_lomac *source, *dest;
@@ -1193,7 +1193,7 @@
 }
 
 static void
-mac_lomac_relabel_pipe(struct ucred *cred, struct pipe *pipe,
+mac_lomac_relabel_pipe(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel, struct label *newlabel)
 {
 	struct mac_lomac *source, *dest;
@@ -1798,7 +1798,7 @@
 }
 
 static int
-mac_lomac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe,
+mac_lomac_check_pipe_ioctl(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data)
 {
 
@@ -1811,7 +1811,7 @@
 }
 
 static int
-mac_lomac_check_pipe_read(struct ucred *cred, struct pipe *pipe,
+mac_lomac_check_pipe_read(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel)
 {
 	struct mac_lomac *subj, *obj;
@@ -1829,7 +1829,7 @@
 }
 
 static int
-mac_lomac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
+mac_lomac_check_pipe_relabel(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel, struct label *newlabel)
 {
 	struct mac_lomac *subj, *obj, *new;
@@ -1880,7 +1880,7 @@
 }
 
 static int
-mac_lomac_check_pipe_write(struct ucred *cred, struct pipe *pipe,
+mac_lomac_check_pipe_write(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel)
 {
 	struct mac_lomac *subj, *obj;
--- //depot/vendor/freebsd/src/sys/security/mac_mls/mac_mls.c	2003/12/17 06:55:44
+++ //depot/user/rwatson/pipe/sys/security/mac_mls/mac_mls.c	2004/01/31 15:47:02
@@ -987,7 +987,7 @@
 }
 
 static void
-mac_mls_create_pipe(struct ucred *cred, struct pipe *pipe,
+mac_mls_create_pipe(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel)
 {
 	struct mac_mls *source, *dest;
@@ -1024,7 +1024,7 @@
 }
 
 static void
-mac_mls_relabel_pipe(struct ucred *cred, struct pipe *pipe,
+mac_mls_relabel_pipe(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel, struct label *newlabel)
 {
 	struct mac_mls *source, *dest;
@@ -1479,7 +1479,7 @@
 }
 
 static int
-mac_mls_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe,
+mac_mls_check_pipe_ioctl(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data)
 {
 
@@ -1492,7 +1492,7 @@
 }
 
 static int
-mac_mls_check_pipe_poll(struct ucred *cred, struct pipe *pipe,
+mac_mls_check_pipe_poll(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel)
 {
 	struct mac_mls *subj, *obj;
@@ -1510,7 +1510,7 @@
 }
 
 static int
-mac_mls_check_pipe_read(struct ucred *cred, struct pipe *pipe,
+mac_mls_check_pipe_read(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel)
 {
 	struct mac_mls *subj, *obj;
@@ -1528,7 +1528,7 @@
 }
 
 static int
-mac_mls_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
+mac_mls_check_pipe_relabel(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel, struct label *newlabel)
 {
 	struct mac_mls *subj, *obj, *new;
@@ -1579,7 +1579,7 @@
 }
 
 static int
-mac_mls_check_pipe_stat(struct ucred *cred, struct pipe *pipe,
+mac_mls_check_pipe_stat(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel)
 {
 	struct mac_mls *subj, *obj;
@@ -1597,7 +1597,7 @@
 }
 
 static int
-mac_mls_check_pipe_write(struct ucred *cred, struct pipe *pipe,
+mac_mls_check_pipe_write(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel)
 {
 	struct mac_mls *subj, *obj;
--- //depot/vendor/freebsd/src/sys/security/mac_test/mac_test.c	2003/12/17 06:55:44
+++ //depot/user/rwatson/pipe/sys/security/mac_test/mac_test.c	2004/01/31 15:47:02
@@ -803,7 +803,7 @@
 }
 
 static void
-mac_test_create_pipe(struct ucred *cred, struct pipe *pipe,
+mac_test_create_pipe(struct ucred *cred, struct pipepair *pp,
    struct label *pipelabel)
 {
 
@@ -831,7 +831,7 @@
 }
 
 static void
-mac_test_relabel_pipe(struct ucred *cred, struct pipe *pipe,
+mac_test_relabel_pipe(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel, struct label *newlabel)
 {
 
@@ -1247,7 +1247,7 @@
 }
 
 static int
-mac_test_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe,
+mac_test_check_pipe_ioctl(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data)
 {
 
@@ -1258,7 +1258,7 @@
 }
 
 static int
-mac_test_check_pipe_poll(struct ucred *cred, struct pipe *pipe,
+mac_test_check_pipe_poll(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel)
 {
 
@@ -1269,7 +1269,7 @@
 }
 
 static int
-mac_test_check_pipe_read(struct ucred *cred, struct pipe *pipe,
+mac_test_check_pipe_read(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel)
 {
 
@@ -1280,7 +1280,7 @@
 }
 
 static int
-mac_test_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
+mac_test_check_pipe_relabel(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel, struct label *newlabel)
 {
 
@@ -1292,7 +1292,7 @@
 }
 
 static int
-mac_test_check_pipe_stat(struct ucred *cred, struct pipe *pipe,
+mac_test_check_pipe_stat(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel)
 {
 
@@ -1303,7 +1303,7 @@
 }
 
 static int
-mac_test_check_pipe_write(struct ucred *cred, struct pipe *pipe,
+mac_test_check_pipe_write(struct ucred *cred, struct pipepair *pp,
     struct label *pipelabel)
 {
 
--- //depot/vendor/freebsd/src/sys/sys/mac.h	2003/12/17 06:55:44
+++ //depot/user/rwatson/pipe/sys/sys/mac.h	2004/01/31 15:47:02
@@ -120,7 +120,7 @@
 struct proc;
 struct sockaddr;
 struct socket;
-struct pipe;
+struct pipepair;
 struct thread;
 struct timespec;
 struct ucred;
@@ -142,7 +142,7 @@
 int	mac_init_inpcb(struct inpcb *, int flag);
 int	mac_init_ipq(struct ipq *, int flag);
 int	mac_init_socket(struct socket *, int flag);
-void	mac_init_pipe(struct pipe *);
+void	mac_init_pipe(struct pipepair *);
 int	mac_init_mbuf(struct mbuf *mbuf, int flag);
 int	mac_init_mbuf_tag(struct m_tag *, int flag);
 void	mac_init_mount(struct mount *);
@@ -157,7 +157,7 @@
 void	mac_destroy_inpcb(struct inpcb *);
 void	mac_destroy_ipq(struct ipq *);
 void	mac_destroy_socket(struct socket *);
-void	mac_destroy_pipe(struct pipe *);
+void	mac_destroy_pipe(struct pipepair *);
 void	mac_destroy_proc(struct proc *);
 void	mac_destroy_mbuf_tag(struct m_tag *);
 void	mac_destroy_mount(struct mount *);
@@ -202,7 +202,7 @@
 	    struct socket *socket);
 void	mac_set_socket_peer_from_socket(struct socket *oldsocket,
 	    struct socket *newsocket);
-void	mac_create_pipe(struct ucred *cred, struct pipe *pipe);
+void	mac_create_pipe(struct ucred *cred, struct pipepair *pp);
 
 /*
  * Labeling event operations: network objects.
@@ -255,12 +255,12 @@
 int	mac_check_kld_stat(struct ucred *cred);
 int	mac_check_kld_unload(struct ucred *cred);
 int	mac_check_mount_stat(struct ucred *cred, struct mount *mp);
-int	mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe,
+int	mac_check_pipe_ioctl(struct ucred *cred, struct pipepair *pp,
 	    unsigned long cmd, void *data);
-int	mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe);
-int	mac_check_pipe_read(struct ucred *cred, struct pipe *pipe);
-int	mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe);
-int	mac_check_pipe_write(struct ucred *cred, struct pipe *pipe);
+int	mac_check_pipe_poll(struct ucred *cred, struct pipepair *pp);
+int	mac_check_pipe_read(struct ucred *cred, struct pipepair *pp);
+int	mac_check_pipe_stat(struct ucred *cred, struct pipepair *pp);
+int	mac_check_pipe_write(struct ucred *cred, struct pipepair *pp);
 int	mac_check_proc_debug(struct ucred *cred, struct proc *proc);
 int	mac_check_proc_sched(struct ucred *cred, struct proc *proc);
 int	mac_check_proc_signal(struct ucred *cred, struct proc *proc,
@@ -351,7 +351,7 @@
 	    struct ifnet *ifnet);
 int	mac_setsockopt_label(struct ucred *cred, struct socket *so,
 	    struct mac *extmac);
-int	mac_pipe_label_set(struct ucred *cred, struct pipe *pipe,
+int	mac_pipe_label_set(struct ucred *cred, struct pipepair *pp,
 	    struct label *label);
 void	mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred);
 
--- //depot/vendor/freebsd/src/sys/sys/mac_policy.h	2003/12/17 06:55:44
+++ //depot/user/rwatson/pipe/sys/sys/mac_policy.h	2004/01/31 15:47:02
@@ -60,7 +60,7 @@
 struct mac_policy_conf;
 struct mbuf;
 struct mount;
-struct pipe;
+struct pipepair;
 struct sbuf;
 struct socket;
 struct ucred;
@@ -199,7 +199,7 @@
 		    struct label *newsocketlabel);
 	void	(*mpo_relabel_socket)(struct ucred *cred, struct socket *so,
 		    struct label *oldlabel, struct label *newlabel);
-	void	(*mpo_relabel_pipe)(struct ucred *cred, struct pipe *pipe,
+	void	(*mpo_relabel_pipe)(struct ucred *cred, struct pipepair *pp,
 		    struct label *oldlabel, struct label *newlabel);
 	void	(*mpo_set_socket_peer_from_mbuf)(struct mbuf *mbuf,
 		    struct label *mbuflabel, struct socket *so,
@@ -207,7 +207,7 @@
 	void	(*mpo_set_socket_peer_from_socket)(struct socket *oldsocket,
 		    struct label *oldsocketlabel, struct socket *newsocket,
 		    struct label *newsocketpeerlabel);
-	void	(*mpo_create_pipe)(struct ucred *cred, struct pipe *pipe,
+	void	(*mpo_create_pipe)(struct ucred *cred, struct pipepair *pp,
 		    struct label *pipelabel);
 
 	/*
@@ -312,19 +312,20 @@
 	int	(*mpo_check_kld_unload)(struct ucred *cred);
 	int	(*mpo_check_mount_stat)(struct ucred *cred, struct mount *mp,
 		    struct label *mntlabel);
-	int	(*mpo_check_pipe_ioctl)(struct ucred *cred, struct pipe *pipe,
-		    struct label *pipelabel, unsigned long cmd, void *data); 
-	int	(*mpo_check_pipe_poll)(struct ucred *cred, struct pipe *pipe,
-		    struct label *pipelabel);
-	int	(*mpo_check_pipe_read)(struct ucred *cred, struct pipe *pipe,
-		    struct label *pipelabel);
+	int	(*mpo_check_pipe_ioctl)(struct ucred *cred,
+		    struct pipepair *pp, struct label *pipelabel,
+		    unsigned long cmd, void *data); 
+	int	(*mpo_check_pipe_poll)(struct ucred *cred,
+		    struct pipepair *pp, struct label *pipelabel);
+	int	(*mpo_check_pipe_read)(struct ucred *cred,
+		    struct pipepair *pp, struct label *pipelabel);
 	int	(*mpo_check_pipe_relabel)(struct ucred *cred,
-		    struct pipe *pipe, struct label *pipelabel,
+		    struct pipepair *pp, struct label *pipelabel,
 		    struct label *newlabel);
-	int	(*mpo_check_pipe_stat)(struct ucred *cred, struct pipe *pipe,
-		    struct label *pipelabel);
-	int	(*mpo_check_pipe_write)(struct ucred *cred, struct pipe *pipe,
-		    struct label *pipelabel);
+	int	(*mpo_check_pipe_stat)(struct ucred *cred,
+		    struct pipepair *pp, struct label *pipelabel);
+	int	(*mpo_check_pipe_write)(struct ucred *cred,
+		    struct pipepair *pp, struct label *pipelabel);
 	int	(*mpo_check_proc_debug)(struct ucred *cred,
 		    struct proc *proc);
 	int	(*mpo_check_proc_sched)(struct ucred *cred,
--- //depot/vendor/freebsd/src/sys/sys/pipe.h	2003/11/11 19:15:41
+++ //depot/user/rwatson/pipe/sys/sys/pipe.h	2004/01/31 18:12:16
@@ -113,13 +113,24 @@
 	struct	timespec pipe_ctime;	/* time of status change */
 	struct	sigio *pipe_sigio;	/* information for async I/O */
 	struct	pipe *pipe_peer;	/* link with other direction */
+	struct	pipepair *pipe_pair;	/* container structure pointer */
 	u_int	pipe_state;		/* pipe status info */
 	int	pipe_busy;		/* busy flag, mostly to handle rundown sanely */
-	struct	label *pipe_label;	/* pipe MAC label - shared */
-	struct	mtx *pipe_mtxp;		/* shared mutex between both pipes */
+	int	pipe_present;		/* still present? */
+};
+
+/*
+ * Container structure to hold the two pipe endpoints, mutex, and label
+ * pointer.
+ */
+struct pipepair {
+	struct pipe	pp_rpipe;
+	struct pipe	pp_wpipe;
+	struct mtx	pp_mtx;
+	struct label	*pp_label;
 };
 
-#define PIPE_MTX(pipe)		(pipe)->pipe_mtxp
+#define PIPE_MTX(pipe)		(&(pipe)->pipe_pair->pp_mtx)
 #define PIPE_LOCK(pipe)		mtx_lock(PIPE_MTX(pipe))
 #define PIPE_UNLOCK(pipe)	mtx_unlock(PIPE_MTX(pipe))
 #define PIPE_LOCK_ASSERT(pipe, type)  mtx_assert(PIPE_MTX(pipe), (type))



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.NEB.3.96L.1040131211448.17012A-100000>