diff options
-rw-r--r-- | include/linux/oom.h | 1 | ||||
-rw-r--r-- | mm/ksm.c | 3 | ||||
-rw-r--r-- | mm/oom_kill.c | 19 | ||||
-rw-r--r-- | mm/swapfile.c | 2 |
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 | ||
43 | extern void compare_swap_oom_score_adj(int old_val, int new_val); | ||
43 | extern int test_set_oom_score_adj(int new_val); | 44 | extern int test_set_oom_score_adj(int new_val); |
44 | 45 | ||
45 | extern unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *mem, | 46 | extern unsigned int oom_badness(struct task_struct *p, struct mem_cgroup *mem, |
@@ -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; | |||
39 | int sysctl_oom_dump_tasks = 1; | 39 | int sysctl_oom_dump_tasks = 1; |
40 | static DEFINE_SPINLOCK(zone_scan_lock); | 40 | static 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 | */ | ||
51 | void 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 | /* |