huawei-mrd-kernel/fs/proc/process_reclaim_info.c

184 lines
4.4 KiB
C

/*
* process_reclaim_info.c : Process reclaim information
*
* Copyright (c) 2016 Huawei.
*
* Authors:
* Wanglai Yao <yaowanglai@huawei.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/of_fdt.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include "internal.h"
static struct kmem_cache *process_reclaim_result_cache;
static int __init process_reclaim_result_cache_create(void)
{
process_reclaim_result_cache = KMEM_CACHE(reclaim_result, 0);
return process_reclaim_result_cache == NULL;
}
struct reclaim_result *process_reclaim_result_cache_alloc(gfp_t gfp)
{
struct reclaim_result *result = NULL;
if (process_reclaim_result_cache)
result = kmem_cache_alloc(process_reclaim_result_cache, gfp);
return result;
}
void process_reclaim_result_cache_free(struct reclaim_result *result)
{
if (process_reclaim_result_cache)
kmem_cache_free(process_reclaim_result_cache, result);
}
int process_reclaim_result_read(struct seq_file *m, struct pid_namespace *ns,
struct pid *pid, struct task_struct *tsk)
{
struct reclaim_result *result;
unsigned nr_reclaimed = 0;
unsigned nr_writedblock = 0;
s64 elapsed_centisecs64 = 0;
if (tsk) {
task_lock(tsk);
result = tsk->proc_reclaimed_result;
if (result) {
nr_reclaimed = result->nr_reclaimed;
nr_writedblock = result->nr_writedblock;
elapsed_centisecs64 = result->elapsed_centisecs64;
tsk->proc_reclaimed_result = NULL;
task_unlock(tsk);
process_reclaim_result_cache_free(result);
} else {
task_unlock(tsk);
}
}
#if KERNEL_VERSION(4, 3, 0) <= LINUX_VERSION_CODE
seq_printf(m,
"nr_reclaimed=%u, nr_writedblock=%u, elapsed=%lld\n",
nr_reclaimed, nr_writedblock, elapsed_centisecs64);
return 0;
#else
return seq_printf(m,
"nr_reclaimed=%u, nr_writedblock=%u, elapsed=%lld\n",
nr_reclaimed, nr_writedblock, elapsed_centisecs64);
#endif
}
void exit_proc_reclaim(struct task_struct *tsk)
{
if (tsk) {
task_lock(tsk);
if (tsk->proc_reclaimed_result) {
struct reclaim_result *result =
tsk->proc_reclaimed_result;
tsk->proc_reclaimed_result = NULL;
task_unlock(tsk);
process_reclaim_result_cache_free
(result);
} else {
task_unlock(tsk);
}
}
}
void process_reclaim_result_write(struct task_struct *task,
unsigned nr_reclaimed, unsigned nr_writedblock,
s64 elapsed_centisecs64)
{
struct reclaim_result *result = NULL;
task_lock(task);
if (!task->proc_reclaimed_result) {
task_unlock(task);
#if KERNEL_VERSION(4, 3, 0) <= LINUX_VERSION_CODE
result =
process_reclaim_result_cache_alloc(__GFP_NOWARN
| __GFP_NORETRY
| __GFP_KSWAPD_RECLAIM);
#else
result =
process_reclaim_result_cache_alloc(__GFP_NOWARN
| __GFP_NORETRY);
#endif
task_lock(task);
if (!task->proc_reclaimed_result) {
task->proc_reclaimed_result = result;
result = NULL;
}
}
if (task->proc_reclaimed_result) {
/*ns->>us*/
task->proc_reclaimed_result->elapsed_centisecs64 =
div_s64(elapsed_centisecs64, 1000);
task->proc_reclaimed_result->nr_writedblock = nr_writedblock;
task->proc_reclaimed_result->nr_reclaimed = nr_reclaimed;
}
task_unlock(task);
if (result)
process_reclaim_result_cache_free(result);
}
bool process_reclaim_need_abort(struct mm_walk *walk)
{
struct mm_struct *mm;
#if KERNEL_VERSION(4, 9, 0) <= LINUX_VERSION_CODE
if (!walk || !walk->private) {
return false;
} else {
struct reclaim_param *rp = walk->private;
if (!rp->hiber)
return false;
}
#else
if (!walk || !walk->hiber)
return false;
#endif
if (reclaim_sigusr_pending(current)) {
pr_info("Reclaim abort!case is signal.\n");
return true;
}
mm = walk->mm;
if (mm && !list_empty(&mm->mmap_sem.wait_list)) {
pr_info("Reclaim abort!case is lock race.\n");
return true;
}
return false;
}
static int __init process_reclaim_info_init(void)
{
int ret = 0;
ret = process_reclaim_result_cache_create();
if (ret)
pr_err("Process reclaim information module init failed!\n");
return ret;
}
late_initcall(process_reclaim_info_init);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Wanglai Yao <yaowanglai@huawei.com>");
MODULE_DESCRIPTION("Process reclaim information");