aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/exit.c21
-rw-r--r--kernel/fork.c82
2 files changed, 63 insertions, 40 deletions
diff --git a/kernel/exit.c b/kernel/exit.c
index 5b0fb9f09f21..83beb1e93b18 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -368,17 +368,19 @@ EXPORT_SYMBOL(daemonize);
368static inline void close_files(struct files_struct * files) 368static inline void close_files(struct files_struct * files)
369{ 369{
370 int i, j; 370 int i, j;
371 struct fdtable *fdt;
371 372
372 j = 0; 373 j = 0;
374 fdt = files_fdtable(files);
373 for (;;) { 375 for (;;) {
374 unsigned long set; 376 unsigned long set;
375 i = j * __NFDBITS; 377 i = j * __NFDBITS;
376 if (i >= files->max_fdset || i >= files->max_fds) 378 if (i >= fdt->max_fdset || i >= fdt->max_fds)
377 break; 379 break;
378 set = files->open_fds->fds_bits[j++]; 380 set = fdt->open_fds->fds_bits[j++];
379 while (set) { 381 while (set) {
380 if (set & 1) { 382 if (set & 1) {
381 struct file * file = xchg(&files->fd[i], NULL); 383 struct file * file = xchg(&fdt->fd[i], NULL);
382 if (file) 384 if (file)
383 filp_close(file, files); 385 filp_close(file, files);
384 } 386 }
@@ -403,16 +405,19 @@ struct files_struct *get_files_struct(struct task_struct *task)
403 405
404void fastcall put_files_struct(struct files_struct *files) 406void fastcall put_files_struct(struct files_struct *files)
405{ 407{
408 struct fdtable *fdt;
409
406 if (atomic_dec_and_test(&files->count)) { 410 if (atomic_dec_and_test(&files->count)) {
407 close_files(files); 411 close_files(files);
408 /* 412 /*
409 * Free the fd and fdset arrays if we expanded them. 413 * Free the fd and fdset arrays if we expanded them.
410 */ 414 */
411 if (files->fd != &files->fd_array[0]) 415 fdt = files_fdtable(files);
412 free_fd_array(files->fd, files->max_fds); 416 if (fdt->fd != &files->fd_array[0])
413 if (files->max_fdset > __FD_SETSIZE) { 417 free_fd_array(fdt->fd, fdt->max_fds);
414 free_fdset(files->open_fds, files->max_fdset); 418 if (fdt->max_fdset > __FD_SETSIZE) {
415 free_fdset(files->close_on_exec, files->max_fdset); 419 free_fdset(fdt->open_fds, fdt->max_fdset);
420 free_fdset(fdt->close_on_exec, fdt->max_fdset);
416 } 421 }
417 kmem_cache_free(files_cachep, files); 422 kmem_cache_free(files_cachep, files);
418 } 423 }
diff --git a/kernel/fork.c b/kernel/fork.c
index b25802065031..ecc694debb50 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -568,21 +568,47 @@ static inline int copy_fs(unsigned long clone_flags, struct task_struct * tsk)
568static int count_open_files(struct files_struct *files, int size) 568static int count_open_files(struct files_struct *files, int size)
569{ 569{
570 int i; 570 int i;
571 struct fdtable *fdt;
571 572
572 /* Find the last open fd */ 573 /* Find the last open fd */
574 fdt = files_fdtable(files);
573 for (i = size/(8*sizeof(long)); i > 0; ) { 575 for (i = size/(8*sizeof(long)); i > 0; ) {
574 if (files->open_fds->fds_bits[--i]) 576 if (fdt->open_fds->fds_bits[--i])
575 break; 577 break;
576 } 578 }
577 i = (i+1) * 8 * sizeof(long); 579 i = (i+1) * 8 * sizeof(long);
578 return i; 580 return i;
579} 581}
580 582
583static struct files_struct *alloc_files(void)
584{
585 struct files_struct *newf;
586 struct fdtable *fdt;
587
588 newf = kmem_cache_alloc(files_cachep, SLAB_KERNEL);
589 if (!newf)
590 goto out;
591
592 atomic_set(&newf->count, 1);
593
594 spin_lock_init(&newf->file_lock);
595 fdt = files_fdtable(newf);
596 fdt->next_fd = 0;
597 fdt->max_fds = NR_OPEN_DEFAULT;
598 fdt->max_fdset = __FD_SETSIZE;
599 fdt->close_on_exec = &newf->close_on_exec_init;
600 fdt->open_fds = &newf->open_fds_init;
601 fdt->fd = &newf->fd_array[0];
602out:
603 return newf;
604}
605
581static int copy_files(unsigned long clone_flags, struct task_struct * tsk) 606static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
582{ 607{
583 struct files_struct *oldf, *newf; 608 struct files_struct *oldf, *newf;
584 struct file **old_fds, **new_fds; 609 struct file **old_fds, **new_fds;
585 int open_files, size, i, error = 0, expand; 610 int open_files, size, i, error = 0, expand;
611 struct fdtable *old_fdt, *new_fdt;
586 612
587 /* 613 /*
588 * A background process may not have any files ... 614 * A background process may not have any files ...
@@ -603,35 +629,27 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
603 */ 629 */
604 tsk->files = NULL; 630 tsk->files = NULL;
605 error = -ENOMEM; 631 error = -ENOMEM;
606 newf = kmem_cache_alloc(files_cachep, SLAB_KERNEL); 632 newf = alloc_files();
607 if (!newf) 633 if (!newf)
608 goto out; 634 goto out;
609 635
610 atomic_set(&newf->count, 1);
611
612 spin_lock_init(&newf->file_lock);
613 newf->next_fd = 0;
614 newf->max_fds = NR_OPEN_DEFAULT;
615 newf->max_fdset = __FD_SETSIZE;
616 newf->close_on_exec = &newf->close_on_exec_init;
617 newf->open_fds = &newf->open_fds_init;
618 newf->fd = &newf->fd_array[0];
619
620 spin_lock(&oldf->file_lock); 636 spin_lock(&oldf->file_lock);
621 637 old_fdt = files_fdtable(oldf);
622 open_files = count_open_files(oldf, oldf->max_fdset); 638 new_fdt = files_fdtable(newf);
639 size = old_fdt->max_fdset;
640 open_files = count_open_files(oldf, old_fdt->max_fdset);
623 expand = 0; 641 expand = 0;
624 642
625 /* 643 /*
626 * Check whether we need to allocate a larger fd array or fd set. 644 * Check whether we need to allocate a larger fd array or fd set.
627 * Note: we're not a clone task, so the open count won't change. 645 * Note: we're not a clone task, so the open count won't change.
628 */ 646 */
629 if (open_files > newf->max_fdset) { 647 if (open_files > new_fdt->max_fdset) {
630 newf->max_fdset = 0; 648 new_fdt->max_fdset = 0;
631 expand = 1; 649 expand = 1;
632 } 650 }
633 if (open_files > newf->max_fds) { 651 if (open_files > new_fdt->max_fds) {
634 newf->max_fds = 0; 652 new_fdt->max_fds = 0;
635 expand = 1; 653 expand = 1;
636 } 654 }
637 655
@@ -646,11 +664,11 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
646 spin_lock(&oldf->file_lock); 664 spin_lock(&oldf->file_lock);
647 } 665 }
648 666
649 old_fds = oldf->fd; 667 old_fds = old_fdt->fd;
650 new_fds = newf->fd; 668 new_fds = new_fdt->fd;
651 669
652 memcpy(newf->open_fds->fds_bits, oldf->open_fds->fds_bits, open_files/8); 670 memcpy(new_fdt->open_fds->fds_bits, old_fdt->open_fds->fds_bits, open_files/8);
653 memcpy(newf->close_on_exec->fds_bits, oldf->close_on_exec->fds_bits, open_files/8); 671 memcpy(new_fdt->close_on_exec->fds_bits, old_fdt->close_on_exec->fds_bits, open_files/8);
654 672
655 for (i = open_files; i != 0; i--) { 673 for (i = open_files; i != 0; i--) {
656 struct file *f = *old_fds++; 674 struct file *f = *old_fds++;
@@ -663,24 +681,24 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
663 * is partway through open(). So make sure that this 681 * is partway through open(). So make sure that this
664 * fd is available to the new process. 682 * fd is available to the new process.
665 */ 683 */
666 FD_CLR(open_files - i, newf->open_fds); 684 FD_CLR(open_files - i, new_fdt->open_fds);
667 } 685 }
668 *new_fds++ = f; 686 *new_fds++ = f;
669 } 687 }
670 spin_unlock(&oldf->file_lock); 688 spin_unlock(&oldf->file_lock);
671 689
672 /* compute the remainder to be cleared */ 690 /* compute the remainder to be cleared */
673 size = (newf->max_fds - open_files) * sizeof(struct file *); 691 size = (new_fdt->max_fds - open_files) * sizeof(struct file *);
674 692
675 /* This is long word aligned thus could use a optimized version */ 693 /* This is long word aligned thus could use a optimized version */
676 memset(new_fds, 0, size); 694 memset(new_fds, 0, size);
677 695
678 if (newf->max_fdset > open_files) { 696 if (new_fdt->max_fdset > open_files) {
679 int left = (newf->max_fdset-open_files)/8; 697 int left = (new_fdt->max_fdset-open_files)/8;
680 int start = open_files / (8 * sizeof(unsigned long)); 698 int start = open_files / (8 * sizeof(unsigned long));
681 699
682 memset(&newf->open_fds->fds_bits[start], 0, left); 700 memset(&new_fdt->open_fds->fds_bits[start], 0, left);
683 memset(&newf->close_on_exec->fds_bits[start], 0, left); 701 memset(&new_fdt->close_on_exec->fds_bits[start], 0, left);
684 } 702 }
685 703
686 tsk->files = newf; 704 tsk->files = newf;
@@ -689,9 +707,9 @@ out:
689 return error; 707 return error;
690 708
691out_release: 709out_release:
692 free_fdset (newf->close_on_exec, newf->max_fdset); 710 free_fdset (new_fdt->close_on_exec, new_fdt->max_fdset);
693 free_fdset (newf->open_fds, newf->max_fdset); 711 free_fdset (new_fdt->open_fds, new_fdt->max_fdset);
694 free_fd_array(newf->fd, newf->max_fds); 712 free_fd_array(new_fdt->fd, new_fdt->max_fds);
695 kmem_cache_free(files_cachep, newf); 713 kmem_cache_free(files_cachep, newf);
696 goto out; 714 goto out;
697} 715}