Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 11 Jun 2012 22:05:26 +0000 (UTC)
From:      Pawel Jakub Dawidek <pjd@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r236935 - head/sys/kern
Message-ID:  <201206112205.q5BM5QIv013266@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: pjd
Date: Mon Jun 11 22:05:26 2012
New Revision: 236935
URL: http://svn.freebsd.org/changeset/base/236935

Log:
  fdgrowtable() no longer drops the filedesc lock so it is enough to
  retry finding free file descriptor only once after fdgrowtable().
  
  Spotted by:	pluknet
  MFC after:	1 month

Modified:
  head/sys/kern/kern_descrip.c

Modified: head/sys/kern/kern_descrip.c
==============================================================================
--- head/sys/kern/kern_descrip.c	Mon Jun 11 21:56:37 2012	(r236934)
+++ head/sys/kern/kern_descrip.c	Mon Jun 11 22:05:26 2012	(r236935)
@@ -1478,29 +1478,33 @@ fdalloc(struct thread *td, int minfd, in
 	/*
 	 * Search the bitmap for a free descriptor.  If none is found, try
 	 * to grow the file table.  Keep at it until we either get a file
-	 * descriptor or run into process or system limits; fdgrowtable()
-	 * may drop the filedesc lock, so we're in a race.
+	 * descriptor or run into process or system limits.
 	 */
-	for (;;) {
-		fd = fd_first_free(fdp, minfd, fdp->fd_nfiles);
-		if (fd >= maxfd)
-			return (EMFILE);
-		if (fd < fdp->fd_nfiles)
-			break;
+	fd = fd_first_free(fdp, minfd, fdp->fd_nfiles);
+	if (fd >= maxfd)
+		return (EMFILE);
+	if (fd >= fdp->fd_nfiles) {
 #ifdef RACCT
 		PROC_LOCK(p);
-		error = racct_set(p, RACCT_NOFILE, min(fdp->fd_nfiles * 2, maxfd));
+		error = racct_set(p, RACCT_NOFILE,
+		    min(fdp->fd_nfiles * 2, maxfd));
 		PROC_UNLOCK(p);
 		if (error != 0)
 			return (EMFILE);
 #endif
 		fdgrowtable(fdp, min(fdp->fd_nfiles * 2, maxfd));
+		/* Retry... */
+		fd = fd_first_free(fdp, minfd, fdp->fd_nfiles);
+		if (fd >= maxfd)
+			return (EMFILE);
 	}
 
 	/*
 	 * Perform some sanity checks, then mark the file descriptor as
 	 * used and return it to the caller.
 	 */
+	KASSERT((unsigned int)fd < min(maxfd, fdp->fd_nfiles),
+	    ("invalid descriptor %d", fd));
 	KASSERT(!fdisused(fdp, fd),
 	    ("fd_first_free() returned non-free descriptor"));
 	KASSERT(fdp->fd_ofiles[fd] == NULL, ("file descriptor isn't free"));



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201206112205.q5BM5QIv013266>