diff --git a/source/module/monitor_kernel_lib.c b/source/module/monitor_kernel_lib.c index 6c42005..76cb218 100644 --- a/source/module/monitor_kernel_lib.c +++ b/source/module/monitor_kernel_lib.c @@ -1,5 +1,14 @@ #include "monitor_kernel.h" +#include +#include +#include + +#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 -} \ No newline at end of file +} + +// 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 +// } \ No newline at end of file diff --git a/source/module/monitor_timer.h b/source/module/monitor_timer.h index 0feb57c..5926142 100644 --- a/source/module/monitor_timer.h +++ b/source/module/monitor_timer.h @@ -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 diff --git a/source/module/monitor_trace.h b/source/module/monitor_trace.h index 56eb36a..f127d7b 100644 --- a/source/module/monitor_trace.h +++ b/source/module/monitor_trace.h @@ -1,5 +1,6 @@ #include #include + #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,