]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - kernel/fork.c
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux.git] / kernel / fork.c
index 2852d0e76ea3b905693a454f36e21524c14a8b54..60763c043aa3c7d71da8c3a1eaa78b4b0b634c68 100644 (file)
@@ -125,6 +125,15 @@ int nr_threads;                    /* The idle threads do not count.. */
 
 static int max_threads;                /* tunable limit on nr_threads */
 
+#define NAMED_ARRAY_INDEX(x)   [x] = __stringify(x)
+
+static const char * const resident_page_types[] = {
+       NAMED_ARRAY_INDEX(MM_FILEPAGES),
+       NAMED_ARRAY_INDEX(MM_ANONPAGES),
+       NAMED_ARRAY_INDEX(MM_SWAPENTS),
+       NAMED_ARRAY_INDEX(MM_SHMEMPAGES),
+};
+
 DEFINE_PER_CPU(unsigned long, process_counts) = 0;
 
 __cacheline_aligned DEFINE_RWLOCK(tasklist_lock);  /* outer */
@@ -645,12 +654,15 @@ static void check_mm(struct mm_struct *mm)
 {
        int i;
 
+       BUILD_BUG_ON_MSG(ARRAY_SIZE(resident_page_types) != NR_MM_COUNTERS,
+                        "Please make sure 'struct resident_page_types[]' is updated as well");
+
        for (i = 0; i < NR_MM_COUNTERS; i++) {
                long x = atomic_long_read(&mm->rss_stat.count[i]);
 
                if (unlikely(x))
-                       printk(KERN_ALERT "BUG: Bad rss-counter state "
-                                         "mm:%p idx:%d val:%ld\n", mm, i, x);
+                       pr_alert("BUG: Bad rss-counter state mm:%p type:%s val:%ld\n",
+                                mm, resident_page_types[i], x);
        }
 
        if (mm_pgtables_bytes(mm))
@@ -768,6 +780,7 @@ static void set_max_threads(unsigned int max_threads_suggested)
 int arch_task_struct_size __read_mostly;
 #endif
 
+#ifndef CONFIG_ARCH_TASK_STRUCT_ALLOCATOR
 static void task_struct_whitelist(unsigned long *offset, unsigned long *size)
 {
        /* Fetch thread_struct whitelist for the architecture. */
@@ -782,6 +795,7 @@ static void task_struct_whitelist(unsigned long *offset, unsigned long *size)
        else
                *offset += offsetof(struct task_struct, thread);
 }
+#endif /* CONFIG_ARCH_TASK_STRUCT_ALLOCATOR */
 
 void __init fork_init(void)
 {
@@ -1007,7 +1021,6 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p,
        mm_init_owner(mm, p);
        RCU_INIT_POINTER(mm->exe_file, NULL);
        mmu_notifier_mm_init(mm);
-       hmm_mm_init(mm);
        init_tlb_flush_pending(mm);
 #if defined(CONFIG_TRANSPARENT_HUGEPAGE) && !USE_SPLIT_PMD_PTLOCKS
        mm->pmd_huge_pte = NULL;
@@ -1517,28 +1530,17 @@ void __cleanup_sighand(struct sighand_struct *sighand)
        }
 }
 
-#ifdef CONFIG_POSIX_TIMERS
 /*
  * Initialize POSIX timer handling for a thread group.
  */
 static void posix_cpu_timers_init_group(struct signal_struct *sig)
 {
+       struct posix_cputimers *pct = &sig->posix_cputimers;
        unsigned long cpu_limit;
 
        cpu_limit = READ_ONCE(sig->rlim[RLIMIT_CPU].rlim_cur);
-       if (cpu_limit != RLIM_INFINITY) {
-               sig->cputime_expires.prof_exp = cpu_limit * NSEC_PER_SEC;
-               sig->cputimer.running = true;
-       }
-
-       /* The timer lists. */
-       INIT_LIST_HEAD(&sig->cpu_timers[0]);
-       INIT_LIST_HEAD(&sig->cpu_timers[1]);
-       INIT_LIST_HEAD(&sig->cpu_timers[2]);
+       posix_cputimers_group_init(pct, cpu_limit);
 }
-#else
-static inline void posix_cpu_timers_init_group(struct signal_struct *sig) { }
-#endif
 
 static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
 {
@@ -1640,23 +1642,6 @@ static void rt_mutex_init_task(struct task_struct *p)
 #endif
 }
 
-#ifdef CONFIG_POSIX_TIMERS
-/*
- * Initialize POSIX timer handling for a single task.
- */
-static void posix_cpu_timers_init(struct task_struct *tsk)
-{
-       tsk->cputime_expires.prof_exp = 0;
-       tsk->cputime_expires.virt_exp = 0;
-       tsk->cputime_expires.sched_exp = 0;
-       INIT_LIST_HEAD(&tsk->cpu_timers[0]);
-       INIT_LIST_HEAD(&tsk->cpu_timers[1]);
-       INIT_LIST_HEAD(&tsk->cpu_timers[2]);
-}
-#else
-static inline void posix_cpu_timers_init(struct task_struct *tsk) { }
-#endif
-
 static inline void init_task_pid_links(struct task_struct *task)
 {
        enum pid_type type;
@@ -1690,6 +1675,14 @@ static inline void rcu_copy_process(struct task_struct *p)
 #endif /* #ifdef CONFIG_TASKS_RCU */
 }
 
+struct pid *pidfd_pid(const struct file *file)
+{
+       if (file->f_op == &pidfd_fops)
+               return file->private_data;
+
+       return ERR_PTR(-EBADF);
+}
+
 static int pidfd_release(struct inode *inode, struct file *file)
 {
        struct pid *pid = file->private_data;
@@ -1935,7 +1928,7 @@ static __latent_entropy struct task_struct *copy_process(
        task_io_accounting_init(&p->ioac);
        acct_clear_integrals(p);
 
-       posix_cpu_timers_init(p);
+       posix_cputimers_init(&p->posix_cputimers);
 
        p->io_context = NULL;
        audit_set_context(p, NULL);
@@ -2338,6 +2331,8 @@ struct mm_struct *copy_init_mm(void)
  *
  * It copies the process, and if successful kick-starts
  * it and waits for it to finish using the VM if required.
+ *
+ * args->exit_signal is expected to be checked for sanity by the caller.
  */
 long _do_fork(struct kernel_clone_args *args)
 {
@@ -2562,6 +2557,14 @@ noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs,
        if (copy_from_user(&args, uargs, size))
                return -EFAULT;
 
+       /*
+        * Verify that higher 32bits of exit_signal are unset and that
+        * it is a valid signal
+        */
+       if (unlikely((args.exit_signal & ~((u64)CSIGNAL)) ||
+                    !valid_signal(args.exit_signal)))
+               return -EINVAL;
+
        *kargs = (struct kernel_clone_args){
                .flags          = args.flags,
                .pidfd          = u64_to_user_ptr(args.pidfd),