summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_descrip.c
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2013-10-09 18:41:35 +0000
committerkib <kib@FreeBSD.org>2013-10-09 18:41:35 +0000
commit7ff487b3a2f97b08f82ffdc0b157adf5e886b4f7 (patch)
tree2e1d559a8bd647988a0fe39a70cedb9031ac987c /sys/kern/kern_descrip.c
parent9375280e4a91021ced232911b9805672cfb89824 (diff)
downloadFreeBSD-src-7ff487b3a2f97b08f82ffdc0b157adf5e886b4f7.zip
FreeBSD-src-7ff487b3a2f97b08f82ffdc0b157adf5e886b4f7.tar.gz
When growing the file descriptor table, new larger memory chunk is
allocated, but the old table is kept around to handle the case of threads still performing unlocked accesses to it. Grow the table exponentially instead of increasing its size by sizeof(long) * 8 chunks when overflowing. This mode significantly reduces the total memory use for the processes consuming large numbers of the file descriptors which open them one by one. Reported and tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Approved by: re (marius)
Diffstat (limited to 'sys/kern/kern_descrip.c')
-rw-r--r--sys/kern/kern_descrip.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 6bf0c60..c1f0d38 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -119,6 +119,7 @@ static int closefp(struct filedesc *fdp, int fd, struct file *fp,
static int fd_first_free(struct filedesc *fdp, int low, int size);
static int fd_last_used(struct filedesc *fdp, int size);
static void fdgrowtable(struct filedesc *fdp, int nfd);
+static void fdgrowtable_exp(struct filedesc *fdp, int nfd);
static void fdunused(struct filedesc *fdp, int fd);
static void fdused(struct filedesc *fdp, int fd);
static int fill_pipe_info(struct pipe *pi, struct kinfo_file *kif);
@@ -855,7 +856,7 @@ do_dup(struct thread *td, int flags, int old, int new,
return (EMFILE);
}
#endif
- fdgrowtable(fdp, new + 1);
+ fdgrowtable_exp(fdp, new + 1);
oldfde = &fdp->fd_ofiles[old];
}
newfde = &fdp->fd_ofiles[new];
@@ -1478,6 +1479,24 @@ filecaps_validate(const struct filecaps *fcaps, const char *func)
("%s: ioctls without CAP_IOCTL", func));
}
+static void
+fdgrowtable_exp(struct filedesc *fdp, int nfd)
+{
+ int nfd1, maxfd;
+
+ FILEDESC_XLOCK_ASSERT(fdp);
+
+ nfd1 = fdp->fd_nfiles * 2;
+ if (nfd1 < nfd)
+ nfd1 = nfd;
+ maxfd = getmaxfd(curproc);
+ if (maxfd < nfd1)
+ nfd1 = maxfd;
+ KASSERT(nfd <= nfd1,
+ ("too low nfd1 %d %d %d %d", nfd, fdp->fd_nfiles, maxfd, nfd1));
+ fdgrowtable(fdp, nfd1);
+}
+
/*
* Grow the file table to accomodate (at least) nfd descriptors.
*/
@@ -1596,7 +1615,7 @@ fdalloc(struct thread *td, int minfd, int *result)
* fd is already equal to first free descriptor >= minfd, so
* we only need to grow the table and we are done.
*/
- fdgrowtable(fdp, allocfd);
+ fdgrowtable_exp(fdp, allocfd);
}
/*
OpenPOWER on IntegriCloud