temp
This commit is contained in:
@@ -1,5 +1,14 @@
|
||||
#include "monitor_kernel.h"
|
||||
|
||||
#include <linux/sched.h>
|
||||
#include <linux/sched/task.h>
|
||||
#include <linux/sched/mm.h>
|
||||
|
||||
#define __task_contributes_to_load(task) \
|
||||
((READ_ONCE(task->__state) & TASK_UNINTERRUPTIBLE) != 0 && \
|
||||
(task->flags & PF_FROZEN) == 0 && \
|
||||
(READ_ONCE(task->__state) & TASK_NOLOAD) == 0)
|
||||
|
||||
/**
|
||||
* @brief watch_arg to kernel_watch_arg
|
||||
*
|
||||
@@ -8,13 +17,14 @@
|
||||
* @param k_watch_arg: kernel_watch_arg
|
||||
* @return unsigned char
|
||||
*/
|
||||
static unsigned char w_arg2k_w_arg(void *ptr, watch_arg warg,
|
||||
static unsigned char w_arg2k_w_arg(void *kptr, watch_arg warg,
|
||||
kernel_watch_arg *k_watch_arg) {
|
||||
// k_watch_arg init
|
||||
k_watch_arg->task_id = warg.task_id;
|
||||
strncpy(k_watch_arg->name, warg.name, MAX_NAME_LEN + 1); // name
|
||||
k_watch_arg->name[MAX_NAME_LEN + 1] = '\0'; // just in case
|
||||
k_watch_arg->kptr = ptr;
|
||||
k_watch_arg->ptr = warg.ptr;
|
||||
k_watch_arg->kptr = kptr;
|
||||
k_watch_arg->length_byte = warg.length_byte;
|
||||
k_watch_arg->threshold = warg.threshold;
|
||||
k_watch_arg->unsigned_flag = warg.unsigned_flag;
|
||||
@@ -22,6 +32,15 @@ static unsigned char w_arg2k_w_arg(void *ptr, watch_arg warg,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void k_w_arg2threshold(kernel_watch_arg *k_watch_arg,
|
||||
threshold *threshold) {
|
||||
threshold->task_id = k_watch_arg->task_id;
|
||||
strncpy(threshold->name, k_watch_arg->name, MAX_NAME_LEN + 1);
|
||||
threshold->name[MAX_NAME_LEN + 1] = '\0';
|
||||
threshold->ptr = k_watch_arg->ptr;
|
||||
threshold->threshold = k_watch_arg->threshold;
|
||||
}
|
||||
|
||||
static void init_mm_tree(mm_tree *mm_tree) {
|
||||
INIT_RADIX_TREE(&mm_tree->mm_tree, GFP_ATOMIC);
|
||||
spin_lock_init(&mm_tree->mm_tree_lock);
|
||||
@@ -67,13 +86,14 @@ int monitor_init(void) {
|
||||
* @brief monitor exit: clear all watch and free buffer
|
||||
*
|
||||
*/
|
||||
void monitor_exit() {
|
||||
void monitor_exit(void) {
|
||||
// clear all watch
|
||||
clear_all_watch();
|
||||
// free buffer
|
||||
destroy_diag_variant_buffer(&load_monitor_variant_buffer);
|
||||
printk(KERN_INFO "clear all buffer\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief start watch variable
|
||||
*
|
||||
@@ -140,36 +160,61 @@ enum hrtimer_restart check_variable_cb(struct hrtimer *timer) {
|
||||
container_of(timer, kernel_watch_timer, hr_timer);
|
||||
int i = 0, j = 0;
|
||||
int buffer[TIMER_MAX_WATCH_NUM]; // Buffer to store the messages
|
||||
kernel_watch_arg *kwarg;
|
||||
|
||||
// // check all watched kernel_watch_arg
|
||||
// for (i = 0; i < k_watch_timer->sentinel; i++) {
|
||||
// if (read_and_compare(&k_watch_timer->k_watch_args[i])) {
|
||||
// // snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), "
|
||||
// // name: %s, threshold: %lld, pid: %d\n",
|
||||
// // k_watch_timer->k_watch_args[i].name,
|
||||
// // k_watch_timer->k_watch_args[i].threshold,
|
||||
// // k_watch_timer->k_watch_args[i].task_id);
|
||||
// buffer[j] = i;
|
||||
// j++;
|
||||
|
||||
// // printk(KERN_INFO "j: name %s, threshold: %lld\n",
|
||||
// // k_watch_timer->k_watch_args[i].name,
|
||||
// // k_watch_timer->k_watch_args[i].threshold);
|
||||
// // printk(KERN_INFO "j: %d\n", j);
|
||||
// }
|
||||
// }
|
||||
// check all watched kernel_watch_arg
|
||||
for (i = 0; i < k_watch_timer->sentinel; i++) {
|
||||
kwarg = &k_watch_timer->k_watch_args[i];
|
||||
if (read_and_compare(kwarg->kptr, kwarg->length_byte, kwarg->greater_flag,
|
||||
kwarg->unsigned_flag, kwarg->threshold)) {
|
||||
buffer[j] = i;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
if (j > 0) // if any threshold reached
|
||||
{
|
||||
printk("-------------------------------------\n");
|
||||
printk("-------------watch monitor-----------\n");
|
||||
printk("Threshold reached:\n");
|
||||
struct task_struct *g, *p; // g: task group; p: task
|
||||
unsigned long flags;
|
||||
variable_monitor_task tsk_info;
|
||||
unsigned long event_id = get_cycles();
|
||||
variable_monitor_record vm_record = {.id = event_id,
|
||||
.et_type = 1, //! todo event type
|
||||
.tv = ktime_get_real(),
|
||||
.threshold_record = {0}};
|
||||
|
||||
// printk("-------------------------------------\n");
|
||||
// printk("-------------watch monitor-----------\n");
|
||||
// printk("Threshold reached:\n");
|
||||
for (i = 0; i < j; i++) {
|
||||
printk(" name: %s, threshold: %lld, pid: %d\n",
|
||||
k_watch_timer->k_watch_args[buffer[i]].name, //! todo
|
||||
k_watch_timer->k_watch_args[buffer[i]].threshold,
|
||||
k_watch_timer->k_watch_args[buffer[i]].task_id);
|
||||
kwarg = &k_watch_timer->k_watch_args[buffer[i]];
|
||||
k_w_arg2threshold(kwarg, &vm_record.threshold_record[i]);
|
||||
}
|
||||
rcu_read_lock();
|
||||
diag_variant_buffer_spin_lock(&load_monitor_variant_buffer, flags);
|
||||
diag_variant_buffer_reserve(&load_monitor_variant_buffer,
|
||||
sizeof(variable_monitor_record));
|
||||
diag_variant_buffer_write_nolock(&load_monitor_variant_buffer, &vm_record,
|
||||
sizeof(variable_monitor_record));
|
||||
diag_variant_buffer_seal(&load_monitor_variant_buffer);
|
||||
diag_variant_buffer_spin_unlock(&load_monitor_variant_buffer, flags);
|
||||
|
||||
// do_each_thread(g, p) {
|
||||
// if (p->__state == TASK_RUNNING || __task_contributes_to_load(p) ||
|
||||
// p->__state == TASK_IDLE) {
|
||||
// tsk_info.et_type = 2; //! todo event type
|
||||
// tsk_info.id = event_id;
|
||||
// tsk_info.tv = vm_record.tv;
|
||||
|
||||
// diag_task_brief(p, &tsk_info.task); // task 相关信息
|
||||
// diag_task_user_stack(tsk, &tsk_info.user_stack);
|
||||
// diag_task_kern_stack(p, &tsk_info.kern_stack); // 内核栈相关信息
|
||||
// dump_proc_chains_argv(load_monitor_settings.style, &mm_tree, p,
|
||||
// &tsk_info.proc_chains); // 进程链相关信息
|
||||
// }
|
||||
// } while_each_thread(g, p);
|
||||
|
||||
rcu_read_unlock();
|
||||
|
||||
// print_task_stack();
|
||||
// restart timer after 1s
|
||||
hrtimer_forward(timer, timer->base->get_time(), ktime_set(1, 0)); //! todo
|
||||
@@ -179,4 +224,26 @@ enum hrtimer_restart check_variable_cb(struct hrtimer *timer) {
|
||||
hrtimer_forward(timer, timer->base->get_time(), k_watch_timer->kt);
|
||||
}
|
||||
return HRTIMER_RESTART; // restart timer
|
||||
}
|
||||
}
|
||||
|
||||
// static void print_task_stack(void) {
|
||||
// struct task_struct *g, *p; // g: task group; p: task
|
||||
// unsigned long backtrace[BACKTRACE_DEPTH]; // save stack
|
||||
// unsigned int nr_bt; // stack depth
|
||||
// unsigned long long current_time; // last time
|
||||
// current_time = ktime_get_real();
|
||||
// printk("Timestamp (ns): %lld\n", current_time);
|
||||
// rcu_read_lock(); // lock run queue
|
||||
// // printk("Running task\n");
|
||||
// do_each_thread(g, p) {
|
||||
// if (p->__state == TASK_RUNNING || __task_contributes_to_load(p) ||
|
||||
// p->__state == TASK_IDLE) {
|
||||
// printk("task: %s, pid %d, state %d\n", p->comm, p->pid,
|
||||
// p->__state); //! todo
|
||||
// nr_bt = orig_stack_trace_save_tsk(p, backtrace, BACKTRACE_DEPTH, 0);
|
||||
// stack_trace_print(backtrace, nr_bt, 0); // print
|
||||
// }
|
||||
// }
|
||||
// while_each_thread(g, p);
|
||||
// rcu_read_unlock(); // unlock run queue
|
||||
// }
|
||||
@@ -18,6 +18,7 @@ typedef struct {
|
||||
typedef struct {
|
||||
pid_t task_id; // current process id
|
||||
char name[MAX_NAME_LEN + 2]; // name, last char automatically add '\0'
|
||||
void *ptr; // user space virtual address
|
||||
void *kptr; // kernel address + offset
|
||||
int length_byte; // byte
|
||||
long long threshold; // threshold value
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <linux/kernfs.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
#include "../buffer/variant_buffer.h"
|
||||
|
||||
#define CGROUP_NAME_LEN 32 // max length of cgroup name
|
||||
@@ -10,6 +11,23 @@
|
||||
#define PROCESS_CHAINS_COUNT 10 // max count of process chains
|
||||
#define PROCESS_ARGV_LEN 128 // max length of process argv
|
||||
|
||||
#define MAX_NAME_LEN (15) // max name length
|
||||
#define TIMER_MAX_WATCH_NUM (32) // A timer max watch number at once time
|
||||
|
||||
typedef struct {
|
||||
pid_t task_id; // current process id
|
||||
char name[MAX_NAME_LEN + 1]; // name
|
||||
void *ptr; // virtual address
|
||||
long long threshold; // threshold value
|
||||
} threshold;
|
||||
|
||||
typedef struct {
|
||||
int et_type;
|
||||
unsigned long id;
|
||||
unsigned long long tv;
|
||||
threshold threshold_record[TIMER_MAX_WATCH_NUM];
|
||||
} variable_monitor_record;
|
||||
|
||||
// from
|
||||
// https://github.com/alibaba/diagnose-tools/blob/8cd905a1c17f2201e460a2d607413a1303757a32/SOURCE/uapi/ali_diagnose.h
|
||||
|
||||
@@ -84,9 +102,10 @@ void dump_proc_chains_argv(
|
||||
// orig_X
|
||||
extern struct sched_class *orig_idle_sched_class;
|
||||
extern int (*orig_get_task_type)(struct sched_entity *se);
|
||||
extern int (*orig_kernfs_name)(struct kernfs_node *kn, char *buf, size_t buflen);
|
||||
extern int (*orig_kernfs_name)(struct kernfs_node *kn, char *buf,
|
||||
size_t buflen);
|
||||
extern int (*orig_access_remote_vm)(struct mm_struct *mm, unsigned long addr,
|
||||
void *buf, int len, unsigned int gup_flags);
|
||||
void *buf, int len, unsigned int gup_flags);
|
||||
extern unsigned int (*orig_stack_trace_save_tsk)(struct task_struct *task,
|
||||
unsigned long *store,
|
||||
unsigned int size,
|
||||
|
||||
Reference in New Issue
Block a user