@@ -1,15 +1,16 @@
# include "monitor_trace.h"
# include <asm/processor.h>
# include <asm/ptrace.h>
# include <asm/syscall.h> // for syscall_get_nr
# include <asm/syscall.h> // for syscall_get_nr
# include <linux/irq.h>
# include <linux/sched/mm.h> // for get_task_mm
# include <linux/rcupdate.h>
# include <linux/sched/mm.h> // for get_task_mm
# include <linux/syscalls.h>
# include <linux/tracehook.h>
# include <linux/rcupdate.h>
mm_tree mm_tree_struct ;
struct diag_variant_buffer load_monitor_variant_buffer ;
struct diag_variant_buffer load_monitor_variant_buffer ;
typedef struct {
struct rcu_head rcu_head ;
@@ -31,8 +32,7 @@ struct stack_frame_user {
} ;
static inline int diag_get_task_type ( struct task_struct * tsk ) {
if ( orig_get_task_type )
return orig_get_task_type ( & tsk - > se ) ;
if ( orig_get_task_type ) return orig_get_task_type ( & tsk - > se ) ;
return 0 ;
}
@@ -47,8 +47,7 @@ static inline int orig_diag_cgroup_name(struct cgroup *cgrp, char *buf,
static inline mm_info * find_mm_info ( mm_tree * mm_tree , struct mm_struct * mm ) {
mm_info * info ;
if ( mm = = NULL )
return NULL ;
if ( mm = = NULL ) return NULL ;
info = radix_tree_lookup ( & mm_tree - > mm_tree , ( unsigned long ) mm ) ;
return info ;
}
@@ -81,8 +80,7 @@ static int copy_stack_frame(const void __user *fp,
ret = 1 ;
pagefault_disable ( ) ;
if ( __copy_from_user_inatomic ( frame , fp , sizeof ( * frame ) ) )
ret = 0 ;
if ( __copy_from_user_inatomic ( frame , fp , sizeof ( * frame ) ) ) ret = 0 ;
pagefault_enable ( ) ;
return ret ;
@@ -95,8 +93,7 @@ static int copy_stack_frame_remote(struct task_struct *tsk,
struct mm_struct * mm ;
mm = get_task_mm ( tsk ) ;
if ( ! mm )
return 0 ;
if ( ! mm ) return 0 ;
ret = orig_access_remote_vm ( mm , ( unsigned long ) fp , frame , sizeof ( * frame ) , 0 ) ;
mmput ( mm ) ;
@@ -127,24 +124,21 @@ static inline void save_stack_trace_user_remote(struct task_struct *tsk,
break ;
}
if ( ( unsigned long ) fp < regs - > sp )
break ;
if ( ( unsigned long ) fp < regs - > sp ) break ;
if ( frame . ret_addr ) {
trace - > entries [ trace - > nr_entries + + ] = frame . ret_addr ;
} else
break ;
if ( fp = = frame . next_fp )
break ;
if ( fp = = frame . next_fp ) break ;
fp = frame . next_fp ;
count + + ;
/**
* 线上环境发现这里有hardlockup, 这里强制退出
*/
if ( count > = trace - > max_entries | | count > = 100 )
break ;
if ( count > = trace - > max_entries | | count > = 100 ) break ;
}
}
@@ -161,22 +155,18 @@ static inline void __save_stack_trace_user(struct stack_trace *trace) {
frame . next_fp = NULL ;
frame . ret_addr = 0 ;
if ( ! copy_stack_frame ( fp , & frame ) )
break ;
if ( ( unsigned long ) fp < regs - > sp )
break ;
if ( ! copy_stack_frame ( fp , & frame ) ) break ;
if ( ( unsigned long ) fp < regs - > sp ) break ;
if ( frame . ret_addr ) {
trace - > entries [ trace - > nr_entries + + ] = frame . ret_addr ;
}
if ( fp = = frame . next_fp )
break ;
if ( fp = = frame . next_fp ) break ;
fp = frame . next_fp ;
count + + ;
/**
* 线上环境发现这里有hardlockup, 这里强制退出
*/
if ( count > = trace - > max_entries | | count > = 100 )
break ;
if ( count > = trace - > max_entries | | count > = 100 ) break ;
}
}
@@ -202,7 +192,7 @@ static void diagnose_save_stack_trace_user(unsigned long *backtrace) {
}
static void diagnose_save_stack_trace_user_remote ( struct task_struct * tsk ,
unsigned long * backtrace ) {
unsigned long * backtrace ) {
struct stack_trace trace ;
memset ( & trace , 0 , sizeof ( trace ) ) ;
@@ -226,52 +216,51 @@ void diag_task_brief(struct task_struct *tsk, task_detail *detail) {
struct task_struct * leader ;
struct pt_regs * irq_regs ;
if ( ! detail )
return ;
if ( ! detail ) return ;
memset ( detail , 0 , sizeof ( task_detail ) ) ;
if ( ! tsk | | tsk - > exit_state = = EXIT_ZOMBIE ) // zombie
if ( ! tsk | | tsk - > exit_state = = EXIT_ZOMBIE ) // zombie
return ;
leader = tsk - > group_leader ;
if ( ! leader | | leader - > exit_state = = EXIT_ZOMBIE ) {
return ;
}
if ( tsk ! = current ) { // not current task
if ( tsk ! = current ) { // not current task
detail - > user_mode = - 1 ;
detail - > syscallno = - 1 ;
} else if ( ! tsk - > mm ) { // current task but kernel thread
} else if ( ! tsk - > mm ) { // current task but kernel thread
detail - > user_mode = 0 ;
detail - > syscallno = - 1 ;
} else { // current task and user thread
irq_regs = get_irq_regs ( ) ; // get current irq regs
} else { // current task and user thread
irq_regs = get_irq_regs ( ) ; // get current irq regs
task_regs = task_pt_regs ( tsk ) ;
if ( ( irq_regs & & user_mode ( irq_regs ) ) | |
( task_regs & & user_mode ( task_regs ) ) ) {
detail - > user_mode = 1 ; // user mode
detail - > user_mode = 1 ; // user mode
} else {
detail - > user_mode = 0 ; // kernel mode
detail - > user_mode = 0 ; // kernel mode
}
if ( task_regs ) {
detail - > syscallno = syscall_get_nr ( tsk , task_regs ) ; // get syscall no
detail - > syscallno = syscall_get_nr ( tsk , task_regs ) ; // get syscall no
}
}
if ( tsk - > sched_class = = orig_idle_sched_class ) // idle task
if ( tsk - > sched_class = = orig_idle_sched_class ) // idle task
detail - > sys_task = 2 ;
else if ( ! tsk - > mm ) // kernel thread
else if ( ! tsk - > mm ) // kernel thread
detail - > sys_task = 1 ;
else
detail - > sys_task = 0 ;
detail - > pid = tsk - > pid ; // pid
detail - > tgid = tsk - > tgid ; // tgid
detail - > state = tsk - > __state ; // state
detail - > task_type = diag_get_task_type ( tsk ) ; // task type
ns = task_active_pid_ns ( tsk ) ; // container pid
detail - > pid = tsk - > pid ; // pid
detail - > tgid = tsk - > tgid ; // tgid
detail - > state = tsk - > __state ; // state
detail - > task_type = diag_get_task_type ( tsk ) ; // task type
ns = task_active_pid_ns ( tsk ) ; // container pid
if ( ns & & ns ! = & init_pid_ns ) {
detail - > container_pid = task_pid_nr_ns ( tsk , ns ) ;
detail - > container_tgid = task_tgid_nr_ns ( tsk , ns ) ;
@@ -280,12 +269,12 @@ void diag_task_brief(struct task_struct *tsk, task_detail *detail) {
detail - > container_tgid = tsk - > tgid ;
}
strncpy ( detail - > comm , tsk - > comm , TASK_COMM_LEN ) ;
detail - > comm [ TASK_COMM_LEN - 1 ] = 0 ; // comm name
detail - > comm [ TASK_COMM_LEN - 1 ] = 0 ; // comm name
diag_cgroup_name ( tsk , detail - > cgroup_buf , CGROUP_NAME_LEN , 0 ) ;
diag_cgroup_name ( tsk , detail - > cgroup_cpuset , CGROUP_NAME_LEN , 1 ) ;
detail - > cgroup_buf [ CGROUP_NAME_LEN - 1 ] = 0 ; // cgroup name
detail - > cgroup_cpuset [ CGROUP_NAME_LEN - 1 ] = 0 ; // cgroup cpuset name
detail - > cgroup_buf [ CGROUP_NAME_LEN - 1 ] = 0 ; // cgroup name
detail - > cgroup_cpuset [ CGROUP_NAME_LEN - 1 ] = 0 ; // cgroup cpuset name
}
void diag_task_user_stack ( struct task_struct * tsk , user_stack_detail * detail ) {
@@ -293,13 +282,13 @@ void diag_task_user_stack(struct task_struct *tsk, user_stack_detail *detail) {
unsigned long sp , ip , bp ;
struct task_struct * leader ;
if ( ! detail ) {
if ( ! detail ) {
printk ( " diag_task_user_stack 4 \n " ) ;
return ;
}
detail - > stack [ 0 ] = 0 ;
if ( ! tsk | | ! tsk - > mm ) {
if ( ! tsk | | ! tsk - > mm ) {
printk ( " diag_task_user_stack 5 \n " ) ;
return ;
}
@@ -349,15 +338,13 @@ void dump_proc_chains_argv(int style, struct task_struct *tsk, mm_tree *mm_tree,
detail - > chains [ i ] [ 0 ] = 0 ;
detail - > tgid [ i ] = 0 ;
}
if ( style = = 0 )
return ;
if ( style = = 0 ) return ;
if ( ! tsk | | ! tsk - > mm )
return ;
if ( ! tsk | | ! tsk - > mm ) return ;
leader = tsk - > group_leader ;
if ( ! leader | | ! leader - > mm | |
leader - > exit_state = = EXIT_ZOMBIE ) { // leader is zombie or no mm
leader - > exit_state = = EXIT_ZOMBIE ) { // leader is zombie or no mm
return ;
}
@@ -380,8 +367,7 @@ void dump_proc_chains_argv(int style, struct task_struct *tsk, mm_tree *mm_tree,
detail - > tgid [ cnt ] = walker - > pid ;
walker = rcu_dereference ( walker - > real_parent ) ;
cnt + + ;
if ( cnt > = PROCESS_CHAINS_COUNT )
break ;
if ( cnt > = PROCESS_CHAINS_COUNT ) break ;
}
rcu_read_unlock ( ) ;
}
@@ -411,4 +397,42 @@ void dump_proc_chains_argv(int style, struct task_struct *tsk, mm_tree *mm_tree,
// }
// while_each_thread(g, p);
// rcu_read_unlock(); // unlock run queue
// }
// }
// void diag_printf_kern_stack(kern_stack_detail *kern_stack, int reverse) {
// int i;
// symbol sym;
// printf(" 内核态堆栈:\n");
// if (reverse) {
// for (i = BACKTRACE_DEPTH - 1; i >= 0; i--) {
// if (kern_stack->stack[i] == (size_t)-1 || kern_stack->stack[i] == 0) {
// continue;
// }
// sym.reset(kern_stack->stack[i]);
// if (g_symbol_parser.find_kernel_symbol(sym)) {
// printf("#@ 0x%lx %s ([kernel.kallsyms])\n", kern_stack->stack[i],
// sym.name.c_str());
// } else {
// printf("#@ 0x%lx %s\n", kern_stack->stack[i], "UNKNOWN");
// }
// }
// } else {
// for (i = 0; i < BACKTRACE_DEPTH; i++) {
// if (kern_stack->stack[i] == (size_t)-1 || kern_stack->stack[i] == 0) {
// break;
// }
// sym.reset(kern_stack->stack[i]);
// if (g_symbol_parser.find_kernel_symbol(sym)) {
// printf("#@ 0x%lx %s ([kernel.kallsyms])\n", kern_stack->stack[i],
// sym.name.c_str());
// } else {
// printf("#@ 0x%lx %s\n", kern_stack->stack[i], "UNKNOWN");
// }
// }
// }
// }
// void diag_printf_kern_stack(struct diag_kern_stack_detail *kern_stack) {
// diag_printf_kern_stack(kern_stack, 0);
// }