You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
138 lines
3.8 KiB
138 lines
3.8 KiB
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* sec_mm/
|
|
*
|
|
* Copyright (C) 2020 Samsung Electronics
|
|
*
|
|
*/
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/memcontrol.h>
|
|
#include <linux/swap.h>
|
|
#include <linux/oom.h>
|
|
#include "sec_mm.h"
|
|
|
|
void mm_debug_show_free_areas(void)
|
|
{
|
|
printk("mm_debug(KB) totalram:%lu"
|
|
" active_anon:%lu inactive_anon:%lu isolated_anon:%lu"
|
|
" active_file:%lu inactive_file:%lu isolated_file:%lu"
|
|
" unevictable:%lu dirty:%lu writeback:%lu unstable:%lu"
|
|
" slab_reclaimable:%lu slab_unreclaimable:%lu"
|
|
" mapped:%lu shmem:%lu pagetables:%lu bounce:%lu"
|
|
" free:%lu free_cma:%lu"
|
|
#if IS_ENABLED(CONFIG_ZSMALLOC)
|
|
" zspages:%lu"
|
|
#endif
|
|
" swapfree:%lu\n",
|
|
K(totalram_pages),
|
|
K(global_node_page_state(NR_ACTIVE_ANON)),
|
|
K(global_node_page_state(NR_INACTIVE_ANON)),
|
|
K(global_node_page_state(NR_ISOLATED_ANON)),
|
|
K(global_node_page_state(NR_ACTIVE_FILE)),
|
|
K(global_node_page_state(NR_INACTIVE_FILE)),
|
|
K(global_node_page_state(NR_ISOLATED_FILE)),
|
|
K(global_node_page_state(NR_UNEVICTABLE)),
|
|
K(global_node_page_state(NR_FILE_DIRTY)),
|
|
K(global_node_page_state(NR_WRITEBACK)),
|
|
K(global_node_page_state(NR_UNSTABLE_NFS)),
|
|
K(global_node_page_state(NR_SLAB_RECLAIMABLE)),
|
|
K(global_node_page_state(NR_SLAB_UNRECLAIMABLE)),
|
|
K(global_node_page_state(NR_FILE_MAPPED)),
|
|
K(global_node_page_state(NR_SHMEM)),
|
|
K(global_zone_page_state(NR_PAGETABLE)),
|
|
K(global_zone_page_state(NR_BOUNCE)),
|
|
K(global_zone_page_state(NR_FREE_PAGES)),
|
|
K(global_zone_page_state(NR_FREE_CMA_PAGES)),
|
|
#if IS_ENABLED(CONFIG_ZSMALLOC)
|
|
K(global_zone_page_state(NR_ZSPAGES)),
|
|
#endif
|
|
K(get_nr_swap_pages()));
|
|
}
|
|
|
|
/* return true if the task is not adequate as candidate victim task. */
|
|
static bool oom_unkillable_task(struct task_struct *p)
|
|
{
|
|
if (is_global_init(p))
|
|
return true;
|
|
if (p->flags & PF_KTHREAD)
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
* The process p may have detached its own ->mm while exiting or through
|
|
* use_mm(), but one or more of its subthreads may still have a valid
|
|
* pointer. Return p, or any of its subthreads with a valid ->mm, with
|
|
* task_lock() held.
|
|
*/
|
|
static struct task_struct *mm_debug_find_lock_task_mm(struct task_struct *p)
|
|
{
|
|
struct task_struct *t;
|
|
|
|
rcu_read_lock();
|
|
|
|
for_each_thread(p, t) {
|
|
task_lock(t);
|
|
if (likely(t->mm))
|
|
goto found;
|
|
task_unlock(t);
|
|
}
|
|
t = NULL;
|
|
found:
|
|
rcu_read_unlock();
|
|
|
|
return t;
|
|
}
|
|
|
|
void mm_debug_dump_tasks(void)
|
|
{
|
|
struct task_struct *p;
|
|
struct task_struct *task;
|
|
unsigned long cur_rss_sum;
|
|
unsigned long heaviest_rss_sum = 0;
|
|
char heaviest_comm[TASK_COMM_LEN];
|
|
pid_t heaviest_pid;
|
|
|
|
pr_info("mm_debug dump tasks\n");
|
|
pr_info("[ pid ] uid tgid total_vm rss nr_ptes nr_pmds swapents oom_score_adj name\n");
|
|
rcu_read_lock();
|
|
for_each_process(p) {
|
|
if (oom_unkillable_task(p))
|
|
continue;
|
|
|
|
task = mm_debug_find_lock_task_mm(p);
|
|
if (!task) {
|
|
/*
|
|
* This is a kthread or all of p's threads have already
|
|
* detached their mm's. There's no need to report
|
|
* them; they can't be oom killed anyway.
|
|
*/
|
|
continue;
|
|
}
|
|
|
|
pr_info("[%5d] %5d %5d %8lu %8lu %7ld %7ld %8lu %5hd %s\n",
|
|
task->pid, from_kuid(&init_user_ns, task_uid(task)),
|
|
task->tgid, task->mm->total_vm, get_mm_rss(task->mm),
|
|
atomic_long_read(&task->mm->nr_ptes),
|
|
mm_nr_pmds(task->mm),
|
|
get_mm_counter(task->mm, MM_SWAPENTS),
|
|
task->signal->oom_score_adj, task->comm);
|
|
cur_rss_sum = get_mm_rss(task->mm) +
|
|
get_mm_counter(task->mm, MM_SWAPENTS);
|
|
if (cur_rss_sum > heaviest_rss_sum) {
|
|
heaviest_rss_sum = cur_rss_sum;
|
|
strncpy(heaviest_comm, task->comm, TASK_COMM_LEN);
|
|
heaviest_pid = task->pid;
|
|
}
|
|
task_unlock(task);
|
|
}
|
|
rcu_read_unlock();
|
|
if (heaviest_rss_sum)
|
|
pr_info("heaviest_task_rss:%s(%d) size:%luKB, totalram_pages:%luKB\n",
|
|
heaviest_comm, heaviest_pid, K(heaviest_rss_sum),
|
|
K(totalram_pages));
|
|
}
|
|
|
|
MODULE_LICENSE("GPL");
|
|
|