aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorVadim Lobanov <vlobanov@speakeasy.net>2006-12-10 05:21:12 -0500
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-10 12:57:22 -0500
commitbbea9f69668a3d0cf9feba15a724cd02896f8675 (patch)
treebc58506e4daba4a04309181a5501ae4eb5424783 /kernel
parentf3d19c90fb117a5f080310a4592929aa8e1ad8e9 (diff)
[PATCH] fdtable: Make fdarray and fdsets equal in size
Currently, each fdtable supports three dynamically-sized arrays of data: the fdarray and two fdsets. The code allows the number of fds supported by the fdarray (fdtable->max_fds) to differ from the number of fds supported by each of the fdsets (fdtable->max_fdset). In practice, it is wasteful for these two sizes to differ: whenever we hit a limit on the smaller-capacity structure, we will reallocate the entire fdtable and all the dynamic arrays within it, so any delta in the memory used by the larger-capacity structure will never be touched at all. Rather than hogging this excess, we shouldn't even allocate it in the first place, and keep the capacities of the fdarray and the fdsets equal. This patch removes fdtable->max_fdset. As an added bonus, most of the supporting code becomes simpler. Signed-off-by: Vadim Lobanov <vlobanov@speakeasy.net> Cc: Christoph Hellwig <hch@lst.de> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Dipankar Sarma <dipankar@in.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/exit.c2
-rw-r--r--kernel/fork.c24
2 files changed, 7 insertions, 19 deletions
diff --git a/kernel/exit.c b/kernel/exit.c
index 03e64fe4a14a..5f77e76b4f97 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -425,7 +425,7 @@ static void close_files(struct files_struct * files)
425 for (;;) { 425 for (;;) {
426 unsigned long set; 426 unsigned long set;
427 i = j * __NFDBITS; 427 i = j * __NFDBITS;
428 if (i >= fdt->max_fdset || i >= fdt->max_fds) 428 if (i >= fdt->max_fds)
429 break; 429 break;
430 set = fdt->open_fds->fds_bits[j++]; 430 set = fdt->open_fds->fds_bits[j++];
431 while (set) { 431 while (set) {
diff --git a/kernel/fork.c b/kernel/fork.c
index 30eab4f063cd..aba595424f78 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -614,7 +614,7 @@ static inline int copy_fs(unsigned long clone_flags, struct task_struct * tsk)
614 614
615static int count_open_files(struct fdtable *fdt) 615static int count_open_files(struct fdtable *fdt)
616{ 616{
617 int size = fdt->max_fdset; 617 int size = fdt->max_fds;
618 int i; 618 int i;
619 619
620 /* Find the last open fd */ 620 /* Find the last open fd */
@@ -641,7 +641,6 @@ static struct files_struct *alloc_files(void)
641 newf->next_fd = 0; 641 newf->next_fd = 0;
642 fdt = &newf->fdtab; 642 fdt = &newf->fdtab;
643 fdt->max_fds = NR_OPEN_DEFAULT; 643 fdt->max_fds = NR_OPEN_DEFAULT;
644 fdt->max_fdset = EMBEDDED_FD_SET_SIZE;
645 fdt->close_on_exec = (fd_set *)&newf->close_on_exec_init; 644 fdt->close_on_exec = (fd_set *)&newf->close_on_exec_init;
646 fdt->open_fds = (fd_set *)&newf->open_fds_init; 645 fdt->open_fds = (fd_set *)&newf->open_fds_init;
647 fdt->fd = &newf->fd_array[0]; 646 fdt->fd = &newf->fd_array[0];
@@ -662,7 +661,7 @@ static struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
662{ 661{
663 struct files_struct *newf; 662 struct files_struct *newf;
664 struct file **old_fds, **new_fds; 663 struct file **old_fds, **new_fds;
665 int open_files, size, i, expand; 664 int open_files, size, i;
666 struct fdtable *old_fdt, *new_fdt; 665 struct fdtable *old_fdt, *new_fdt;
667 666
668 *errorp = -ENOMEM; 667 *errorp = -ENOMEM;
@@ -673,25 +672,14 @@ static struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
673 spin_lock(&oldf->file_lock); 672 spin_lock(&oldf->file_lock);
674 old_fdt = files_fdtable(oldf); 673 old_fdt = files_fdtable(oldf);
675 new_fdt = files_fdtable(newf); 674 new_fdt = files_fdtable(newf);
676 size = old_fdt->max_fdset;
677 open_files = count_open_files(old_fdt); 675 open_files = count_open_files(old_fdt);
678 expand = 0;
679 676
680 /* 677 /*
681 * Check whether we need to allocate a larger fd array or fd set. 678 * Check whether we need to allocate a larger fd array and fd set.
682 * Note: we're not a clone task, so the open count won't change. 679 * Note: we're not a clone task, so the open count won't change.
683 */ 680 */
684 if (open_files > new_fdt->max_fdset) {
685 new_fdt->max_fdset = 0;
686 expand = 1;
687 }
688 if (open_files > new_fdt->max_fds) { 681 if (open_files > new_fdt->max_fds) {
689 new_fdt->max_fds = 0; 682 new_fdt->max_fds = 0;
690 expand = 1;
691 }
692
693 /* if the old fdset gets grown now, we'll only copy up to "size" fds */
694 if (expand) {
695 spin_unlock(&oldf->file_lock); 683 spin_unlock(&oldf->file_lock);
696 spin_lock(&newf->file_lock); 684 spin_lock(&newf->file_lock);
697 *errorp = expand_files(newf, open_files-1); 685 *errorp = expand_files(newf, open_files-1);
@@ -739,8 +727,8 @@ static struct files_struct *dup_fd(struct files_struct *oldf, int *errorp)
739 /* This is long word aligned thus could use a optimized version */ 727 /* This is long word aligned thus could use a optimized version */
740 memset(new_fds, 0, size); 728 memset(new_fds, 0, size);
741 729
742 if (new_fdt->max_fdset > open_files) { 730 if (new_fdt->max_fds > open_files) {
743 int left = (new_fdt->max_fdset-open_files)/8; 731 int left = (new_fdt->max_fds-open_files)/8;
744 int start = open_files / (8 * sizeof(unsigned long)); 732 int start = open_files / (8 * sizeof(unsigned long));
745 733
746 memset(&new_fdt->open_fds->fds_bits[start], 0, left); 734 memset(&new_fdt->open_fds->fds_bits[start], 0, left);