diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/audit_watch.c | 8 | ||||
-rw-r--r-- | kernel/bpf/verifier.c | 3 | ||||
-rw-r--r-- | kernel/configs/tiny.config | 8 | ||||
-rw-r--r-- | kernel/cpuset.c | 15 | ||||
-rw-r--r-- | kernel/exit.c | 7 | ||||
-rw-r--r-- | kernel/fork.c | 23 | ||||
-rw-r--r-- | kernel/irq/msi.c | 1 | ||||
-rw-r--r-- | kernel/kexec_file.c | 3 | ||||
-rw-r--r-- | kernel/memremap.c | 9 | ||||
-rw-r--r-- | kernel/sched/bfs.c | 58 | ||||
-rw-r--r-- | kernel/sched/bfs_sched.h | 13 | ||||
-rw-r--r-- | kernel/sched/core.c | 22 | ||||
-rw-r--r-- | kernel/smpboot.c | 2 |
13 files changed, 101 insertions, 71 deletions
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c index d6709eb70..0d302a87f 100644 --- a/kernel/audit_watch.c +++ b/kernel/audit_watch.c @@ -19,6 +19,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <linux/file.h> #include <linux/kernel.h> #include <linux/audit.h> #include <linux/kthread.h> @@ -544,10 +545,11 @@ int audit_exe_compare(struct task_struct *tsk, struct audit_fsnotify_mark *mark) unsigned long ino; dev_t dev; - rcu_read_lock(); - exe_file = rcu_dereference(tsk->mm->exe_file); + exe_file = get_task_exe_file(tsk); + if (!exe_file) + return 0; ino = exe_file->f_inode->i_ino; dev = exe_file->f_inode->i_sb->s_dev; - rcu_read_unlock(); + fput(exe_file); return audit_mark_compare(mark, ino, dev); } diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index eec9f90ba..6d011c693 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -194,6 +194,7 @@ struct verifier_env { struct verifier_state_list **explored_states; /* search pruning optimization */ struct bpf_map *used_maps[MAX_USED_MAPS]; /* array of map's used by eBPF program */ u32 used_map_cnt; /* number of used maps */ + u32 id_gen; /* used to generate unique reg IDs */ bool allow_ptr_leaks; }; @@ -1277,7 +1278,7 @@ add_imm: /* dst_reg stays as pkt_ptr type and since some positive * integer value was added to the pointer, increment its 'id' */ - dst_reg->id++; + dst_reg->id = ++env->id_gen; /* something was added to pkt_ptr, set range and off to zero */ dst_reg->off = 0; diff --git a/kernel/configs/tiny.config b/kernel/configs/tiny.config index c2de56ab0..7fa0c4ae6 100644 --- a/kernel/configs/tiny.config +++ b/kernel/configs/tiny.config @@ -1,4 +1,12 @@ +# CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE is not set CONFIG_CC_OPTIMIZE_FOR_SIZE=y +# CONFIG_KERNEL_GZIP is not set +# CONFIG_KERNEL_BZIP2 is not set +# CONFIG_KERNEL_LZMA is not set CONFIG_KERNEL_XZ=y +# CONFIG_KERNEL_LZO is not set +# CONFIG_KERNEL_LZ4 is not set CONFIG_OPTIMIZE_INLINING=y +# CONFIG_SLAB is not set +# CONFIG_SLUB is not set CONFIG_SLOB=y diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 73e93e538..40b6ed559 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -2078,6 +2078,20 @@ static void cpuset_bind(struct cgroup_subsys_state *root_css) mutex_unlock(&cpuset_mutex); } +/* + * Make sure the new task conform to the current state of its parent, + * which could have been changed by cpuset just after it inherits the + * state from the parent and before it sits on the cgroup's task list. + */ +void cpuset_fork(struct task_struct *task) +{ + if (task_css_is_root(task, cpuset_cgrp_id)) + return; + + set_cpus_allowed_ptr(task, ¤t->cpus_allowed); + task->mems_allowed = current->mems_allowed; +} + struct cgroup_subsys cpuset_cgrp_subsys = { .css_alloc = cpuset_css_alloc, .css_online = cpuset_css_online, @@ -2088,6 +2102,7 @@ struct cgroup_subsys cpuset_cgrp_subsys = { .attach = cpuset_attach, .post_attach = cpuset_post_attach, .bind = cpuset_bind, + .fork = cpuset_fork, .legacy_cftypes = files, .early_init = true, }; diff --git a/kernel/exit.c b/kernel/exit.c index 6b91bca9f..10011db7b 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -768,12 +768,7 @@ void do_exit(long code) TASKS_RCU(preempt_enable()); exit_notify(tsk, group_dead); proc_exit_connector(tsk); -#ifdef CONFIG_NUMA - task_lock(tsk); - mpol_put(tsk->mempolicy); - tsk->mempolicy = NULL; - task_unlock(tsk); -#endif + mpol_put_task_policy(tsk); #ifdef CONFIG_FUTEX if (unlikely(current->pi_state_cache)) kfree(current->pi_state_cache); diff --git a/kernel/fork.c b/kernel/fork.c index 767d95257..d7485f782 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -801,6 +801,29 @@ struct file *get_mm_exe_file(struct mm_struct *mm) EXPORT_SYMBOL(get_mm_exe_file); /** + * get_task_exe_file - acquire a reference to the task's executable file + * + * Returns %NULL if task's mm (if any) has no associated executable file or + * this is a kernel thread with borrowed mm (see the comment above get_task_mm). + * User must release file via fput(). + */ +struct file *get_task_exe_file(struct task_struct *task) +{ + struct file *exe_file = NULL; + struct mm_struct *mm; + + task_lock(task); + mm = task->mm; + if (mm) { + if (!(task->flags & PF_KTHREAD)) + exe_file = get_mm_exe_file(mm); + } + task_unlock(task); + return exe_file; +} +EXPORT_SYMBOL(get_task_exe_file); + +/** * get_task_mm - acquire a reference to the task's mm * * Returns %NULL if the task has no mm. Checks PF_KTHREAD (meaning diff --git a/kernel/irq/msi.c b/kernel/irq/msi.c index 0afe671f1..6143b2f64 100644 --- a/kernel/irq/msi.c +++ b/kernel/irq/msi.c @@ -352,6 +352,7 @@ int msi_domain_alloc_irqs(struct irq_domain *domain, struct device *dev, ops->msi_finish(&arg, 0); for_each_msi_entry(desc, dev) { + virq = desc->irq; if (desc->nvec_used == 1) dev_dbg(dev, "irq %d for MSI\n", virq); else diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c index 503bc2d34..037c321c5 100644 --- a/kernel/kexec_file.c +++ b/kernel/kexec_file.c @@ -887,7 +887,10 @@ int kexec_load_purgatory(struct kimage *image, unsigned long min, return 0; out: vfree(pi->sechdrs); + pi->sechdrs = NULL; + vfree(pi->purgatory_buf); + pi->purgatory_buf = NULL; return ret; } diff --git a/kernel/memremap.c b/kernel/memremap.c index 017532193..c2eb3a057 100644 --- a/kernel/memremap.c +++ b/kernel/memremap.c @@ -253,6 +253,7 @@ static void devm_memremap_pages_release(struct device *dev, void *data) align_start = res->start & ~(SECTION_SIZE - 1); align_size = ALIGN(resource_size(res), SECTION_SIZE); arch_remove_memory(align_start, align_size); + untrack_pfn(NULL, PHYS_PFN(align_start), align_size); pgmap_radix_release(res); dev_WARN_ONCE(dev, pgmap->altmap && pgmap->altmap->alloc, "%s: failed to free all reserved pages\n", __func__); @@ -288,6 +289,7 @@ void *devm_memremap_pages(struct device *dev, struct resource *res, struct percpu_ref *ref, struct vmem_altmap *altmap) { resource_size_t key, align_start, align_size, align_end; + pgprot_t pgprot = PAGE_KERNEL; struct dev_pagemap *pgmap; struct page_map *page_map; int error, nid, is_ram; @@ -363,6 +365,11 @@ void *devm_memremap_pages(struct device *dev, struct resource *res, if (nid < 0) nid = numa_mem_id(); + error = track_pfn_remap(NULL, &pgprot, PHYS_PFN(align_start), 0, + align_size); + if (error) + goto err_pfn_remap; + error = arch_add_memory(nid, align_start, align_size, true); if (error) goto err_add_memory; @@ -383,6 +390,8 @@ void *devm_memremap_pages(struct device *dev, struct resource *res, return __va(res->start); err_add_memory: + untrack_pfn(NULL, PHYS_PFN(align_start), align_size); + err_pfn_remap: err_radix: pgmap_radix_release(res); devres_free(page_map); diff --git a/kernel/sched/bfs.c b/kernel/sched/bfs.c index 60b9ab785..67f93e752 100644 --- a/kernel/sched/bfs.c +++ b/kernel/sched/bfs.c @@ -35,7 +35,7 @@ #include <linux/init.h> #include <asm/uaccess.h> #include <linux/highmem.h> -#include <asm/mmu_context.h> +#include <linux/mmu_context.h> #include <linux/interrupt.h> #include <linux/capability.h> #include <linux/completion.h> @@ -137,7 +137,7 @@ void print_scheduler_version(void) { - printk(KERN_INFO "BFS CPU scheduler v0.497 by Con Kolivas.\n"); + printk(KERN_INFO "BFS CPU scheduler v0.502 by Con Kolivas.\n"); } /* @@ -676,6 +676,11 @@ static inline int queued_notrunning(void) return grq.qnr; } +static unsigned long rq_load_avg(struct rq *rq) +{ + return rq->soft_affined * SCHED_CAPACITY_SCALE; +} + #ifdef CONFIG_SMT_NICE static const cpumask_t *thread_cpumask(int cpu); @@ -748,41 +753,9 @@ static bool smt_should_schedule(struct task_struct *p, struct rq *this_rq) /* Sorry, you lose */ return false; } - -static unsigned long cpu_load_avg(struct rq *rq) -{ - return rq->soft_affined * SCHED_CAPACITY_SCALE; -} - -/* - * This is the proportion of SCHED_CAPACITY_SCALE (1024) used when each thread - * of a CPU with SMT siblings is in use. - */ -#define SCHED_SMT_LOAD (890) - -/* - * Load of a CPU with smt siblings should be considered to be the load from all - * the SMT siblings, thus will be >1 if both threads are in use since they are - * not full cores. - */ -static unsigned long smt_load_avg(struct rq *rq) -{ - unsigned long load = rq->soft_affined * SCHED_SMT_LOAD; - int cpu; - - for_each_cpu(cpu, thread_cpumask(rq->cpu)) - load += cpu_rq(cpu)->soft_affined * SCHED_SMT_LOAD; - return load; -} - -static unsigned long (*rq_load_avg)(struct rq *rq) = &cpu_load_avg; -#else +#else /* CONFIG_SMT_NICE */ #define smt_schedule(p, this_rq) (true) -static inline unsigned long rq_load_avg(struct rq *rq) -{ - return rq->soft_affined * SCHED_CAPACITY_SCALE; -} -#endif +#endif /* CONFIG_SMT_NICE */ #ifdef CONFIG_SMP /* * The cpu_idle_map stores a bitmap of all the CPUs currently idle to @@ -1055,21 +1028,13 @@ void set_task_cpu(struct task_struct *p, unsigned int cpu) */ smp_wmb(); if (p->on_rq) { - struct rq *rq; + struct rq *rq = task_rq(p); - /* - * set_task_cpu can be set on other CPUs so call cpufreq_trigger - * explicitly telling it what CPU is being updated as the value - * of soft_affined has changed. - */ - rq = task_rq(p); rq->soft_affined--; update_load_avg(rq); - other_cpufreq_trigger(tcpu, grq.niffies, rq->load_avg); rq = cpu_rq(cpu); rq->soft_affined++; update_load_avg(rq); - other_cpufreq_trigger(cpu, grq.niffies, rq->load_avg); } task_thread_info(p)->cpu = cpu; } @@ -7084,7 +7049,7 @@ void __init sched_init_smp(void) /* First check if this cpu is in the same node */ for_each_domain(cpu, sd) { - if (sd->level > SD_LV_NODE) + if (sd->level > SD_LV_MC) continue; /* Set locality to local node if not already found lower */ for_each_cpu(other_cpu, sched_domain_span(sd)) { @@ -7124,7 +7089,6 @@ void __init sched_init_smp(void) check_siblings = &check_smt_siblings; wake_siblings = &wake_smt_siblings; smt_schedule = &smt_should_schedule; - rq_load_avg = &smt_load_avg; } #endif grq_unlock_irq(); diff --git a/kernel/sched/bfs_sched.h b/kernel/sched/bfs_sched.h index d4a8be9be..e7fe1d0a5 100644 --- a/kernel/sched/bfs_sched.h +++ b/kernel/sched/bfs_sched.h @@ -207,23 +207,10 @@ static inline void cpufreq_trigger(u64 time, unsigned long util) if (data) data->func(data, time, util, SCHED_CAPACITY_SCALE); } - -static inline void other_cpufreq_trigger(int cpu, u64 time, unsigned long util) -{ - struct update_util_data *data; - - data = rcu_dereference_sched(*per_cpu_ptr(&cpufreq_update_util_data, cpu)); - if (data) - data->func(data, time, util, SCHED_CAPACITY_SCALE); -} #else static inline void cpufreq_trigger(u64 time, unsigned long util) { } - -static inline void other_cpufreq_trigger(int cpu, u64 time, unsigned long util) -{ -} #endif /* CONFIG_CPU_FREQ */ #ifdef arch_scale_freq_capacity diff --git a/kernel/sched/core.c b/kernel/sched/core.c index 97ee9ac7e..38eacc323 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c @@ -2015,6 +2015,28 @@ try_to_wake_up(struct task_struct *p, unsigned int state, int wake_flags) success = 1; /* we're going to change ->state */ cpu = task_cpu(p); + /* + * Ensure we load p->on_rq _after_ p->state, otherwise it would + * be possible to, falsely, observe p->on_rq == 0 and get stuck + * in smp_cond_load_acquire() below. + * + * sched_ttwu_pending() try_to_wake_up() + * [S] p->on_rq = 1; [L] P->state + * UNLOCK rq->lock -----. + * \ + * +--- RMB + * schedule() / + * LOCK rq->lock -----' + * UNLOCK rq->lock + * + * [task p] + * [S] p->state = UNINTERRUPTIBLE [L] p->on_rq + * + * Pairs with the UNLOCK+LOCK on rq->lock from the + * last wakeup of our task and the schedule that got our task + * current. + */ + smp_rmb(); if (p->on_rq && ttwu_remote(p, wake_flags)) goto stat; diff --git a/kernel/smpboot.c b/kernel/smpboot.c index ca4e5343a..0bcf0cfb2 100644 --- a/kernel/smpboot.c +++ b/kernel/smpboot.c @@ -122,12 +122,12 @@ static int smpboot_thread_fn(void *data) if (kthread_should_park()) { __set_current_state(TASK_RUNNING); - preempt_enable(); if (ht->park && td->status == HP_THREAD_ACTIVE) { BUG_ON(td->cpu != smp_processor_id()); ht->park(td->cpu); td->status = HP_THREAD_PARKED; } + preempt_enable(); kthread_parkme(); /* We might have been woken for stop */ continue; |