aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/fork.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/fork.c')
-rw-r--r--kernel/fork.c101
1 files changed, 67 insertions, 34 deletions
diff --git a/kernel/fork.c b/kernel/fork.c
index 7e1ead9a6ba4..8149f3602881 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -35,6 +35,7 @@
35#include <linux/syscalls.h> 35#include <linux/syscalls.h>
36#include <linux/jiffies.h> 36#include <linux/jiffies.h>
37#include <linux/futex.h> 37#include <linux/futex.h>
38#include <linux/rcupdate.h>
38#include <linux/ptrace.h> 39#include <linux/ptrace.h>
39#include <linux/mount.h> 40#include <linux/mount.h>
40#include <linux/audit.h> 41#include <linux/audit.h>
@@ -176,6 +177,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
176 177
177 /* One for us, one for whoever does the "release_task()" (usually parent) */ 178 /* One for us, one for whoever does the "release_task()" (usually parent) */
178 atomic_set(&tsk->usage,2); 179 atomic_set(&tsk->usage,2);
180 atomic_set(&tsk->fs_excl, 0);
179 return tsk; 181 return tsk;
180} 182}
181 183
@@ -564,24 +566,53 @@ static inline int copy_fs(unsigned long clone_flags, struct task_struct * tsk)
564 return 0; 566 return 0;
565} 567}
566 568
567static int count_open_files(struct files_struct *files, int size) 569static int count_open_files(struct fdtable *fdt)
568{ 570{
571 int size = fdt->max_fdset;
569 int i; 572 int i;
570 573
571 /* Find the last open fd */ 574 /* Find the last open fd */
572 for (i = size/(8*sizeof(long)); i > 0; ) { 575 for (i = size/(8*sizeof(long)); i > 0; ) {
573 if (files->open_fds->fds_bits[--i]) 576 if (fdt->open_fds->fds_bits[--i])
574 break; 577 break;
575 } 578 }
576 i = (i+1) * 8 * sizeof(long); 579 i = (i+1) * 8 * sizeof(long);
577 return i; 580 return i;
578} 581}
579 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 = &newf->fdtab;
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];
602 INIT_RCU_HEAD(&fdt->rcu);
603 fdt->free_files = NULL;
604 fdt->next = NULL;
605 rcu_assign_pointer(newf->fdt, fdt);
606out:
607 return newf;
608}
609
580static int copy_files(unsigned long clone_flags, struct task_struct * tsk) 610static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
581{ 611{
582 struct files_struct *oldf, *newf; 612 struct files_struct *oldf, *newf;
583 struct file **old_fds, **new_fds; 613 struct file **old_fds, **new_fds;
584 int open_files, size, i, error = 0, expand; 614 int open_files, size, i, error = 0, expand;
615 struct fdtable *old_fdt, *new_fdt;
585 616
586 /* 617 /*
587 * A background process may not have any files ... 618 * A background process may not have any files ...
@@ -602,35 +633,27 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
602 */ 633 */
603 tsk->files = NULL; 634 tsk->files = NULL;
604 error = -ENOMEM; 635 error = -ENOMEM;
605 newf = kmem_cache_alloc(files_cachep, SLAB_KERNEL); 636 newf = alloc_files();
606 if (!newf) 637 if (!newf)
607 goto out; 638 goto out;
608 639
609 atomic_set(&newf->count, 1);
610
611 spin_lock_init(&newf->file_lock);
612 newf->next_fd = 0;
613 newf->max_fds = NR_OPEN_DEFAULT;
614 newf->max_fdset = __FD_SETSIZE;
615 newf->close_on_exec = &newf->close_on_exec_init;
616 newf->open_fds = &newf->open_fds_init;
617 newf->fd = &newf->fd_array[0];
618
619 spin_lock(&oldf->file_lock); 640 spin_lock(&oldf->file_lock);
620 641 old_fdt = files_fdtable(oldf);
621 open_files = count_open_files(oldf, oldf->max_fdset); 642 new_fdt = files_fdtable(newf);
643 size = old_fdt->max_fdset;
644 open_files = count_open_files(old_fdt);
622 expand = 0; 645 expand = 0;
623 646
624 /* 647 /*
625 * Check whether we need to allocate a larger fd array or fd set. 648 * Check whether we need to allocate a larger fd array or fd set.
626 * Note: we're not a clone task, so the open count won't change. 649 * Note: we're not a clone task, so the open count won't change.
627 */ 650 */
628 if (open_files > newf->max_fdset) { 651 if (open_files > new_fdt->max_fdset) {
629 newf->max_fdset = 0; 652 new_fdt->max_fdset = 0;
630 expand = 1; 653 expand = 1;
631 } 654 }
632 if (open_files > newf->max_fds) { 655 if (open_files > new_fdt->max_fds) {
633 newf->max_fds = 0; 656 new_fdt->max_fds = 0;
634 expand = 1; 657 expand = 1;
635 } 658 }
636 659
@@ -642,14 +665,21 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
642 spin_unlock(&newf->file_lock); 665 spin_unlock(&newf->file_lock);
643 if (error < 0) 666 if (error < 0)
644 goto out_release; 667 goto out_release;
668 new_fdt = files_fdtable(newf);
669 /*
670 * Reacquire the oldf lock and a pointer to its fd table
671 * who knows it may have a new bigger fd table. We need
672 * the latest pointer.
673 */
645 spin_lock(&oldf->file_lock); 674 spin_lock(&oldf->file_lock);
675 old_fdt = files_fdtable(oldf);
646 } 676 }
647 677
648 old_fds = oldf->fd; 678 old_fds = old_fdt->fd;
649 new_fds = newf->fd; 679 new_fds = new_fdt->fd;
650 680
651 memcpy(newf->open_fds->fds_bits, oldf->open_fds->fds_bits, open_files/8); 681 memcpy(new_fdt->open_fds->fds_bits, old_fdt->open_fds->fds_bits, open_files/8);
652 memcpy(newf->close_on_exec->fds_bits, oldf->close_on_exec->fds_bits, open_files/8); 682 memcpy(new_fdt->close_on_exec->fds_bits, old_fdt->close_on_exec->fds_bits, open_files/8);
653 683
654 for (i = open_files; i != 0; i--) { 684 for (i = open_files; i != 0; i--) {
655 struct file *f = *old_fds++; 685 struct file *f = *old_fds++;
@@ -662,24 +692,24 @@ static int copy_files(unsigned long clone_flags, struct task_struct * tsk)
662 * is partway through open(). So make sure that this 692 * is partway through open(). So make sure that this
663 * fd is available to the new process. 693 * fd is available to the new process.
664 */ 694 */
665 FD_CLR(open_files - i, newf->open_fds); 695 FD_CLR(open_files - i, new_fdt->open_fds);
666 } 696 }
667 *new_fds++ = f; 697 rcu_assign_pointer(*new_fds++, f);
668 } 698 }
669 spin_unlock(&oldf->file_lock); 699 spin_unlock(&oldf->file_lock);
670 700
671 /* compute the remainder to be cleared */ 701 /* compute the remainder to be cleared */
672 size = (newf->max_fds - open_files) * sizeof(struct file *); 702 size = (new_fdt->max_fds - open_files) * sizeof(struct file *);
673 703
674 /* This is long word aligned thus could use a optimized version */ 704 /* This is long word aligned thus could use a optimized version */
675 memset(new_fds, 0, size); 705 memset(new_fds, 0, size);
676 706
677 if (newf->max_fdset > open_files) { 707 if (new_fdt->max_fdset > open_files) {
678 int left = (newf->max_fdset-open_files)/8; 708 int left = (new_fdt->max_fdset-open_files)/8;
679 int start = open_files / (8 * sizeof(unsigned long)); 709 int start = open_files / (8 * sizeof(unsigned long));
680 710
681 memset(&newf->open_fds->fds_bits[start], 0, left); 711 memset(&new_fdt->open_fds->fds_bits[start], 0, left);
682 memset(&newf->close_on_exec->fds_bits[start], 0, left); 712 memset(&new_fdt->close_on_exec->fds_bits[start], 0, left);
683 } 713 }
684 714
685 tsk->files = newf; 715 tsk->files = newf;
@@ -688,9 +718,9 @@ out:
688 return error; 718 return error;
689 719
690out_release: 720out_release:
691 free_fdset (newf->close_on_exec, newf->max_fdset); 721 free_fdset (new_fdt->close_on_exec, new_fdt->max_fdset);
692 free_fdset (newf->open_fds, newf->max_fdset); 722 free_fdset (new_fdt->open_fds, new_fdt->max_fdset);
693 free_fd_array(newf->fd, newf->max_fds); 723 free_fd_array(new_fdt->fd, new_fdt->max_fds);
694 kmem_cache_free(files_cachep, newf); 724 kmem_cache_free(files_cachep, newf);
695 goto out; 725 goto out;
696} 726}
@@ -1115,6 +1145,9 @@ static task_t *copy_process(unsigned long clone_flags,
1115 __get_cpu_var(process_counts)++; 1145 __get_cpu_var(process_counts)++;
1116 } 1146 }
1117 1147
1148 if (!current->signal->tty && p->signal->tty)
1149 p->signal->tty = NULL;
1150
1118 nr_threads++; 1151 nr_threads++;
1119 total_forks++; 1152 total_forks++;
1120 write_unlock_irq(&tasklist_lock); 1153 write_unlock_irq(&tasklist_lock);