summaryrefslogtreecommitdiffstats
path: root/sys/kern/sys_pipe.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2011-12-06 11:24:03 +0000
committerkib <kib@FreeBSD.org>2011-12-06 11:24:03 +0000
commit12e8232d4db8b80e5a4da1575bcfad518f1f867b (patch)
tree4991fc8f0939a0565805b4cebbf3b5db11f617b8 /sys/kern/sys_pipe.c
parentf8f306b32a4ee9cf17446f1997817dafecceb424 (diff)
downloadFreeBSD-src-12e8232d4db8b80e5a4da1575bcfad518f1f867b.zip
FreeBSD-src-12e8232d4db8b80e5a4da1575bcfad518f1f867b.tar.gz
Most users of pipe(2) do not call fstat(2) on the returned pipe descriptors.
Optimize for the case, by lazily allocating the pipe inode number at the fstat(2) time. If alloc_unr(9) returns failure, do not fail fstat(2), since uses of inode numbers are even rare then fstat(2), but provide zero inode forever. Note that alloc_unr() failure is unlikely due to total number of pipes in the system limited by the number of file descriptors. Based on the submission by: gianni MFC after: 2 weeks
Diffstat (limited to 'sys/kern/sys_pipe.c')
-rw-r--r--sys/kern/sys_pipe.c37
1 files changed, 28 insertions, 9 deletions
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index 2b6eb66..9a4448a 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -569,12 +569,7 @@ pipe_create(pipe, backing)
/* If we're not backing this pipe, no need to do anything. */
error = 0;
}
- if (error == 0) {
- pipe->pipe_ino = alloc_unr(pipeino_unr);
- if (pipe->pipe_ino == -1)
- /* pipeclose will clear allocated kva */
- error = ENOMEM;
- }
+ pipe->pipe_ino = -1;
return (error);
}
@@ -1398,16 +1393,40 @@ pipe_stat(fp, ub, active_cred, td)
struct ucred *active_cred;
struct thread *td;
{
- struct pipe *pipe = fp->f_data;
+ struct pipe *pipe;
+ int new_unr;
#ifdef MAC
int error;
+#endif
+ pipe = fp->f_data;
PIPE_LOCK(pipe);
+#ifdef MAC
error = mac_pipe_check_stat(active_cred, pipe->pipe_pair);
- PIPE_UNLOCK(pipe);
- if (error)
+ if (error) {
+ PIPE_UNLOCK(pipe);
return (error);
+ }
#endif
+ /*
+ * Lazily allocate an inode number for the pipe. Most pipe
+ * users do not call fstat(2) on the pipe, which means that
+ * postponing the inode allocation until it is must be
+ * returned to userland is useful. If alloc_unr failed,
+ * assign st_ino zero instead of returning an error.
+ * Special pipe_ino values:
+ * -1 - not yet initialized;
+ * 0 - alloc_unr failed, return 0 as st_ino forever.
+ */
+ if (pipe->pipe_ino == (ino_t)-1) {
+ new_unr = alloc_unr(pipeino_unr);
+ if (new_unr != -1)
+ pipe->pipe_ino = new_unr;
+ else
+ pipe->pipe_ino = 0;
+ }
+ PIPE_UNLOCK(pipe);
+
bzero(ub, sizeof(*ub));
ub->st_mode = S_IFIFO;
ub->st_blksize = PAGE_SIZE;
OpenPOWER on IntegriCloud