svn commit: r228306 - head/sys/kern

Konstantin Belousov kib at FreeBSD.org
Tue Dec 6 11:24:04 UTC 2011


Author: kib
Date: Tue Dec  6 11:24:03 2011
New Revision: 228306
URL: http://svn.freebsd.org/changeset/base/228306

Log:
  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

Modified:
  head/sys/kern/sys_pipe.c

Modified: head/sys/kern/sys_pipe.c
==============================================================================
--- head/sys/kern/sys_pipe.c	Tue Dec  6 09:12:11 2011	(r228305)
+++ head/sys/kern/sys_pipe.c	Tue Dec  6 11:24:03 2011	(r228306)
@@ -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;


More information about the svn-src-all mailing list