aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/oom.h1
-rw-r--r--mm/ksm.c3
-rw-r--r--mm/oom_kill.c19
-rw-r--r--mm/swapfile.c2
4 files changed, 23 insertions, 2 deletions
diff --git a/include/linux/oom.h b/include/linux/oom.h
index 13b7b02e599a..6f9d04a85336 100644
--- a/include/linux/oom.h
+++ b/include/linux/oom.h
@@ -40,6 +40,7 @@ enum oom_constraint {
40 CONSTRAINT_MEMCG, 40 CONSTRAINT_MEMCG,
41}; 41};
42 42
43extern void compare_swap_oom_score_adj(int old_val, int new_val);
43extern int test_set_oom_score_adj(int new_val); 44extern int test_set_oom_score_adj(int new_val);
44 45
45extern unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *mem, 46extern unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *mem,
diff --git a/mm/ksm.c b/mm/ksm.c
index 9a68b0cf0a1c..310544a379ae 100644
--- a/mm/ksm.c
+++ b/mm/ksm.c
@@ -1905,7 +1905,8 @@ static ssize_t run_store(struct kobject *kobj, struct kobj_attribute *attr,
1905 1905
1906 oom_score_adj = test_set_oom_score_adj(OOM_SCORE_ADJ_MAX); 1906 oom_score_adj = test_set_oom_score_adj(OOM_SCORE_ADJ_MAX);
1907 err = unmerge_and_remove_all_rmap_items(); 1907 err = unmerge_and_remove_all_rmap_items();
1908 test_set_oom_score_adj(oom_score_adj); 1908 compare_swap_oom_score_adj(OOM_SCORE_ADJ_MAX,
1909 oom_score_adj);
1909 if (err) { 1910 if (err) {
1910 ksm_run = KSM_RUN_STOP; 1911 ksm_run = KSM_RUN_STOP;
1911 count = err; 1912 count = err;
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 2b97e8f04607..e916168b6e0a 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -39,6 +39,25 @@ int sysctl_oom_kill_allocating_task;
39int sysctl_oom_dump_tasks = 1; 39int sysctl_oom_dump_tasks = 1;
40static DEFINE_SPINLOCK(zone_scan_lock); 40static DEFINE_SPINLOCK(zone_scan_lock);
41 41
42/*
43 * compare_swap_oom_score_adj() - compare and swap current's oom_score_adj
44 * @old_val: old oom_score_adj for compare
45 * @new_val: new oom_score_adj for swap
46 *
47 * Sets the oom_score_adj value for current to @new_val iff its present value is
48 * @old_val. Usually used to reinstate a previous value to prevent racing with
49 * userspacing tuning the value in the interim.
50 */
51void compare_swap_oom_score_adj(int old_val, int new_val)
52{
53 struct sighand_struct *sighand = current->sighand;
54
55 spin_lock_irq(&sighand->siglock);
56 if (current->signal->oom_score_adj == old_val)
57 current->signal->oom_score_adj = new_val;
58 spin_unlock_irq(&sighand->siglock);
59}
60
42/** 61/**
43 * test_set_oom_score_adj() - set current's oom_score_adj and return old value 62 * test_set_oom_score_adj() - set current's oom_score_adj and return old value
44 * @new_val: new oom_score_adj value 63 * @new_val: new oom_score_adj value
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 17bc224bce68..c9d654009125 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -1617,7 +1617,7 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
1617 1617
1618 oom_score_adj = test_set_oom_score_adj(OOM_SCORE_ADJ_MAX); 1618 oom_score_adj = test_set_oom_score_adj(OOM_SCORE_ADJ_MAX);
1619 err = try_to_unuse(type); 1619 err = try_to_unuse(type);
1620 test_set_oom_score_adj(oom_score_adj); 1620 compare_swap_oom_score_adj(OOM_SCORE_ADJ_MAX, oom_score_adj);
1621 1621
1622 if (err) { 1622 if (err) {
1623 /* 1623 /*