summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/audit_watch.c8
-rw-r--r--kernel/bpf/verifier.c3
-rw-r--r--kernel/configs/tiny.config8
-rw-r--r--kernel/cpuset.c15
-rw-r--r--kernel/exit.c7
-rw-r--r--kernel/fork.c23
-rw-r--r--kernel/irq/msi.c1
-rw-r--r--kernel/kexec_file.c3
-rw-r--r--kernel/memremap.c9
-rw-r--r--kernel/sched/bfs.c58
-rw-r--r--kernel/sched/bfs_sched.h13
-rw-r--r--kernel/sched/core.c22
-rw-r--r--kernel/smpboot.c2
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, &current->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;