aboutsummaryrefslogtreecommitdiff
path: root/mm
diff options
context:
space:
mode:
Diffstat (limited to 'mm')
-rw-r--r--mm/memory.c13
-rw-r--r--mm/memory_hotplug.c4
-rw-r--r--mm/vmstat.c95
3 files changed, 26 insertions, 86 deletions
diff --git a/mm/memory.c b/mm/memory.c
index a8e1bbad1ae0..ed674188e9fc 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3232,6 +3232,10 @@ static int do_anonymous_page(struct mm_struct *mm, struct vm_area_struct *vma,
pte_unmap(page_table);
+ /* File mapping without ->vm_ops ? */
+ if (vma->vm_flags & VM_SHARED)
+ return VM_FAULT_SIGBUS;
+
/* Check if we need to add a guard page to the stack */
if (check_stack_guard_page(vma, address) < 0)
return VM_FAULT_SIGSEGV;
@@ -3497,6 +3501,9 @@ static int do_linear_fault(struct mm_struct *mm, struct vm_area_struct *vma,
- vma->vm_start) >> PAGE_SHIFT) + vma->vm_pgoff;
pte_unmap(page_table);
+ /* The VMA was not fully populated on mmap() or missing VM_DONTEXPAND */
+ if (!vma->vm_ops->fault)
+ return VM_FAULT_SIGBUS;
return __do_fault(mm, vma, address, pmd, pgoff, flags, orig_pte);
}
@@ -3708,11 +3715,9 @@ int handle_pte_fault(struct mm_struct *mm,
entry = *pte;
if (!pte_present(entry)) {
if (pte_none(entry)) {
- if (vma->vm_ops) {
- if (likely(vma->vm_ops->fault))
- return do_linear_fault(mm, vma, address,
+ if (vma->vm_ops)
+ return do_linear_fault(mm, vma, address,
pte, pmd, flags, entry);
- }
return do_anonymous_page(mm, vma, address,
pte, pmd, flags);
}
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 2298237db142..d85d3a0e06ce 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1803,8 +1803,10 @@ void try_offline_node(int nid)
* wait_table may be allocated from boot memory,
* here only free if it's allocated by vmalloc.
*/
- if (is_vmalloc_addr(zone->wait_table))
+ if (is_vmalloc_addr(zone->wait_table)) {
vfree(zone->wait_table);
+ zone->wait_table = NULL;
+ }
}
}
EXPORT_SYMBOL(try_offline_node);
diff --git a/mm/vmstat.c b/mm/vmstat.c
index 5242d6da7181..e0264625bb90 100644
--- a/mm/vmstat.c
+++ b/mm/vmstat.c
@@ -14,7 +14,6 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/cpu.h>
-#include <linux/cpumask.h>
#include <linux/vmstat.h>
#include <linux/sched.h>
#include <linux/math64.h>
@@ -439,12 +438,11 @@ EXPORT_SYMBOL(dec_zone_page_state);
* with the global counters. These could cause remote node cache line
* bouncing and will have to be only done when necessary.
*/
-bool refresh_cpu_vm_stats(int cpu)
+void refresh_cpu_vm_stats(int cpu)
{
struct zone *zone;
int i;
int global_diff[NR_VM_ZONE_STAT_ITEMS] = { 0, };
- bool vm_activity = false;
for_each_populated_zone(zone) {
struct per_cpu_pageset *p;
@@ -491,21 +489,14 @@ bool refresh_cpu_vm_stats(int cpu)
if (p->expire)
continue;
- if (p->pcp.count) {
- vm_activity = true;
+ if (p->pcp.count)
drain_zone_pages(zone, &p->pcp);
- }
#endif
}
for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
- if (global_diff[i]) {
+ if (global_diff[i])
atomic_long_add(global_diff[i], &vm_stat[i]);
- vm_activity = true;
- }
-
- return vm_activity;
-
}
/*
@@ -1190,70 +1181,20 @@ static const struct file_operations proc_vmstat_file_operations = {
#ifdef CONFIG_SMP
static DEFINE_PER_CPU(struct delayed_work, vmstat_work);
int sysctl_stat_interval __read_mostly = HZ;
-static struct cpumask vmstat_off_cpus;
-struct delayed_work vmstat_monitor_work;
-
-static inline bool need_vmstat(int cpu)
-{
- struct zone *zone;
- int i;
-
- for_each_populated_zone(zone) {
- struct per_cpu_pageset *p;
- p = per_cpu_ptr(zone->pageset, cpu);
-
- for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
- if (p->vm_stat_diff[i])
- return true;
-
- if (zone_to_nid(zone) != numa_node_id() && p->pcp.count)
- return true;
- }
-
- return false;
-}
-
-static void vmstat_update(struct work_struct *w);
-
-static void start_cpu_timer(int cpu)
+static void vmstat_update(struct work_struct *w)
{
- struct delayed_work *work = &per_cpu(vmstat_work, cpu);
-
- cpumask_clear_cpu(cpu, &vmstat_off_cpus);
- schedule_delayed_work_on(cpu, work, __round_jiffies_relative(HZ, cpu));
+ refresh_cpu_vm_stats(smp_processor_id());
+ schedule_delayed_work(&__get_cpu_var(vmstat_work),
+ round_jiffies_relative(sysctl_stat_interval));
}
-static void __cpuinit setup_cpu_timer(int cpu)
+static void __cpuinit start_cpu_timer(int cpu)
{
struct delayed_work *work = &per_cpu(vmstat_work, cpu);
INIT_DEFERRABLE_WORK(work, vmstat_update);
- start_cpu_timer(cpu);
-}
-
-static void vmstat_update_monitor(struct work_struct *w)
-{
- int cpu;
-
- for_each_cpu_and(cpu, &vmstat_off_cpus, cpu_online_mask)
- if (need_vmstat(cpu))
- start_cpu_timer(cpu);
-
- queue_delayed_work(system_unbound_wq, &vmstat_monitor_work,
- round_jiffies_relative(sysctl_stat_interval));
-}
-
-
-static void vmstat_update(struct work_struct *w)
-{
- int cpu = smp_processor_id();
-
- if (likely(refresh_cpu_vm_stats(cpu)))
- schedule_delayed_work(&__get_cpu_var(vmstat_work),
- round_jiffies_relative(sysctl_stat_interval));
- else
- cpumask_set_cpu(cpu, &vmstat_off_cpus);
+ schedule_delayed_work_on(cpu, work, __round_jiffies_relative(HZ, cpu));
}
/*
@@ -1270,19 +1211,17 @@ static int __cpuinit vmstat_cpuup_callback(struct notifier_block *nfb,
case CPU_ONLINE:
case CPU_ONLINE_FROZEN:
refresh_zone_stat_thresholds();
- setup_cpu_timer(cpu);
+ start_cpu_timer(cpu);
node_set_state(cpu_to_node(cpu), N_CPU);
break;
case CPU_DOWN_PREPARE:
case CPU_DOWN_PREPARE_FROZEN:
- if (!cpumask_test_cpu(cpu, &vmstat_off_cpus)) {
- cancel_delayed_work_sync(&per_cpu(vmstat_work, cpu));
- per_cpu(vmstat_work, cpu).work.func = NULL;
- }
+ cancel_delayed_work_sync(&per_cpu(vmstat_work, cpu));
+ per_cpu(vmstat_work, cpu).work.func = NULL;
break;
case CPU_DOWN_FAILED:
case CPU_DOWN_FAILED_FROZEN:
- setup_cpu_timer(cpu);
+ start_cpu_timer(cpu);
break;
case CPU_DEAD:
case CPU_DEAD_FROZEN:
@@ -1305,14 +1244,8 @@ static int __init setup_vmstat(void)
register_cpu_notifier(&vmstat_notifier);
- INIT_DEFERRABLE_WORK(&vmstat_monitor_work,
- vmstat_update_monitor);
- queue_delayed_work(system_unbound_wq,
- &vmstat_monitor_work,
- round_jiffies_relative(HZ));
-
for_each_online_cpu(cpu)
- setup_cpu_timer(cpu);
+ start_cpu_timer(cpu);
#endif
#ifdef CONFIG_PROC_FS
proc_create("buddyinfo", S_IRUGO, NULL, &fragmentation_file_operations);