diff options
author | Vadim Lobanov <vlobanov@speakeasy.net> | 2006-12-10 05:21:12 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.osdl.org> | 2006-12-10 12:57:22 -0500 |
commit | bbea9f69668a3d0cf9feba15a724cd02896f8675 (patch) | |
tree | bc58506e4daba4a04309181a5501ae4eb5424783 /kernel | |
parent | f3d19c90fb117a5f080310a4592929aa8e1ad8e9 (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.c | 2 | ||||
-rw-r--r-- | kernel/fork.c | 24 |
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 | ||
615 | static int count_open_files(struct fdtable *fdt) | 615 | static 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); |