diff options
Diffstat (limited to 'mm/oom_kill.c')
-rw-r--r-- | mm/oom_kill.c | 81 |
1 files changed, 20 insertions, 61 deletions
diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 26ea8636758f..3a2484884cfd 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c | |||
@@ -843,7 +843,7 @@ static bool task_will_free_mem(struct task_struct *task) | |||
843 | return ret; | 843 | return ret; |
844 | } | 844 | } |
845 | 845 | ||
846 | static void __oom_kill_process(struct task_struct *victim) | 846 | static void __oom_kill_process(struct task_struct *victim, const char *message) |
847 | { | 847 | { |
848 | struct task_struct *p; | 848 | struct task_struct *p; |
849 | struct mm_struct *mm; | 849 | struct mm_struct *mm; |
@@ -874,8 +874,9 @@ static void __oom_kill_process(struct task_struct *victim) | |||
874 | */ | 874 | */ |
875 | do_send_sig_info(SIGKILL, SEND_SIG_PRIV, victim, PIDTYPE_TGID); | 875 | do_send_sig_info(SIGKILL, SEND_SIG_PRIV, victim, PIDTYPE_TGID); |
876 | mark_oom_victim(victim); | 876 | mark_oom_victim(victim); |
877 | pr_err("Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB, shmem-rss:%lukB\n", | 877 | pr_err("%s: Killed process %d (%s) total-vm:%lukB, anon-rss:%lukB, file-rss:%lukB, shmem-rss:%lukB\n", |
878 | task_pid_nr(victim), victim->comm, K(victim->mm->total_vm), | 878 | message, task_pid_nr(victim), victim->comm, |
879 | K(victim->mm->total_vm), | ||
879 | K(get_mm_counter(victim->mm, MM_ANONPAGES)), | 880 | K(get_mm_counter(victim->mm, MM_ANONPAGES)), |
880 | K(get_mm_counter(victim->mm, MM_FILEPAGES)), | 881 | K(get_mm_counter(victim->mm, MM_FILEPAGES)), |
881 | K(get_mm_counter(victim->mm, MM_SHMEMPAGES))); | 882 | K(get_mm_counter(victim->mm, MM_SHMEMPAGES))); |
@@ -926,24 +927,20 @@ static void __oom_kill_process(struct task_struct *victim) | |||
926 | * Kill provided task unless it's secured by setting | 927 | * Kill provided task unless it's secured by setting |
927 | * oom_score_adj to OOM_SCORE_ADJ_MIN. | 928 | * oom_score_adj to OOM_SCORE_ADJ_MIN. |
928 | */ | 929 | */ |
929 | static int oom_kill_memcg_member(struct task_struct *task, void *unused) | 930 | static int oom_kill_memcg_member(struct task_struct *task, void *message) |
930 | { | 931 | { |
931 | if (task->signal->oom_score_adj != OOM_SCORE_ADJ_MIN) { | 932 | if (task->signal->oom_score_adj != OOM_SCORE_ADJ_MIN && |
933 | !is_global_init(task)) { | ||
932 | get_task_struct(task); | 934 | get_task_struct(task); |
933 | __oom_kill_process(task); | 935 | __oom_kill_process(task, message); |
934 | } | 936 | } |
935 | return 0; | 937 | return 0; |
936 | } | 938 | } |
937 | 939 | ||
938 | static void oom_kill_process(struct oom_control *oc, const char *message) | 940 | static void oom_kill_process(struct oom_control *oc, const char *message) |
939 | { | 941 | { |
940 | struct task_struct *p = oc->chosen; | 942 | struct task_struct *victim = oc->chosen; |
941 | unsigned int points = oc->chosen_points; | ||
942 | struct task_struct *victim = p; | ||
943 | struct task_struct *child; | ||
944 | struct task_struct *t; | ||
945 | struct mem_cgroup *oom_group; | 943 | struct mem_cgroup *oom_group; |
946 | unsigned int victim_points = 0; | ||
947 | static DEFINE_RATELIMIT_STATE(oom_rs, DEFAULT_RATELIMIT_INTERVAL, | 944 | static DEFINE_RATELIMIT_STATE(oom_rs, DEFAULT_RATELIMIT_INTERVAL, |
948 | DEFAULT_RATELIMIT_BURST); | 945 | DEFAULT_RATELIMIT_BURST); |
949 | 946 | ||
@@ -952,57 +949,18 @@ static void oom_kill_process(struct oom_control *oc, const char *message) | |||
952 | * its children or threads, just give it access to memory reserves | 949 | * its children or threads, just give it access to memory reserves |
953 | * so it can die quickly | 950 | * so it can die quickly |
954 | */ | 951 | */ |
955 | task_lock(p); | 952 | task_lock(victim); |
956 | if (task_will_free_mem(p)) { | 953 | if (task_will_free_mem(victim)) { |
957 | mark_oom_victim(p); | 954 | mark_oom_victim(victim); |
958 | wake_oom_reaper(p); | 955 | wake_oom_reaper(victim); |
959 | task_unlock(p); | 956 | task_unlock(victim); |
960 | put_task_struct(p); | 957 | put_task_struct(victim); |
961 | return; | 958 | return; |
962 | } | 959 | } |
963 | task_unlock(p); | 960 | task_unlock(victim); |
964 | 961 | ||
965 | if (__ratelimit(&oom_rs)) | 962 | if (__ratelimit(&oom_rs)) |
966 | dump_header(oc, p); | 963 | dump_header(oc, victim); |
967 | |||
968 | pr_err("%s: Kill process %d (%s) score %u or sacrifice child\n", | ||
969 | message, task_pid_nr(p), p->comm, points); | ||
970 | |||
971 | /* | ||
972 | * If any of p's children has a different mm and is eligible for kill, | ||
973 | * the one with the highest oom_badness() score is sacrificed for its | ||
974 | * parent. This attempts to lose the minimal amount of work done while | ||
975 | * still freeing memory. | ||
976 | */ | ||
977 | read_lock(&tasklist_lock); | ||
978 | |||
979 | /* | ||
980 | * The task 'p' might have already exited before reaching here. The | ||
981 | * put_task_struct() will free task_struct 'p' while the loop still try | ||
982 | * to access the field of 'p', so, get an extra reference. | ||
983 | */ | ||
984 | get_task_struct(p); | ||
985 | for_each_thread(p, t) { | ||
986 | list_for_each_entry(child, &t->children, sibling) { | ||
987 | unsigned int child_points; | ||
988 | |||
989 | if (process_shares_mm(child, p->mm)) | ||
990 | continue; | ||
991 | /* | ||
992 | * oom_badness() returns 0 if the thread is unkillable | ||
993 | */ | ||
994 | child_points = oom_badness(child, | ||
995 | oc->memcg, oc->nodemask, oc->totalpages); | ||
996 | if (child_points > victim_points) { | ||
997 | put_task_struct(victim); | ||
998 | victim = child; | ||
999 | victim_points = child_points; | ||
1000 | get_task_struct(victim); | ||
1001 | } | ||
1002 | } | ||
1003 | } | ||
1004 | put_task_struct(p); | ||
1005 | read_unlock(&tasklist_lock); | ||
1006 | 964 | ||
1007 | /* | 965 | /* |
1008 | * Do we need to kill the entire memory cgroup? | 966 | * Do we need to kill the entire memory cgroup? |
@@ -1011,14 +969,15 @@ static void oom_kill_process(struct oom_control *oc, const char *message) | |||
1011 | */ | 969 | */ |
1012 | oom_group = mem_cgroup_get_oom_group(victim, oc->memcg); | 970 | oom_group = mem_cgroup_get_oom_group(victim, oc->memcg); |
1013 | 971 | ||
1014 | __oom_kill_process(victim); | 972 | __oom_kill_process(victim, message); |
1015 | 973 | ||
1016 | /* | 974 | /* |
1017 | * If necessary, kill all tasks in the selected memory cgroup. | 975 | * If necessary, kill all tasks in the selected memory cgroup. |
1018 | */ | 976 | */ |
1019 | if (oom_group) { | 977 | if (oom_group) { |
1020 | mem_cgroup_print_oom_group(oom_group); | 978 | mem_cgroup_print_oom_group(oom_group); |
1021 | mem_cgroup_scan_tasks(oom_group, oom_kill_memcg_member, NULL); | 979 | mem_cgroup_scan_tasks(oom_group, oom_kill_memcg_member, |
980 | (void*)message); | ||
1022 | mem_cgroup_put(oom_group); | 981 | mem_cgroup_put(oom_group); |
1023 | } | 982 | } |
1024 | } | 983 | } |