summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_descrip.c
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2012-06-11 22:05:26 +0000
committerpjd <pjd@FreeBSD.org>2012-06-11 22:05:26 +0000
commitea4cd345da2829316a13c218d8bffbb0e5df06f9 (patch)
tree0a78997a1740b5392ad5fbb12006018592ec4cc6 /sys/kern/kern_descrip.c
parentfece26df6f404ac528422ccf427a99e286577eaf (diff)
downloadFreeBSD-src-ea4cd345da2829316a13c218d8bffbb0e5df06f9.zip
FreeBSD-src-ea4cd345da2829316a13c218d8bffbb0e5df06f9.tar.gz
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
Diffstat (limited to 'sys/kern/kern_descrip.c')
-rw-r--r--sys/kern/kern_descrip.c22
1 files changed, 13 insertions, 9 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 8126206..61e13c1 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -1478,29 +1478,33 @@ fdalloc(struct thread *td, int minfd, int *result)
/*
* 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"));
OpenPOWER on IntegriCloud