1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
| diff --git a/include/linux/printk.h b/include/linux/printk.h index e8aae29..2c1ec29 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -10,6 +10,9 @@ extern const char linux_banner[]; extern const char linux_proc_banner[]; +typedef int *printk_hook_t(char *text,size_t textlen); +extern void printk_hook_register(printk_hook_t *hook); +extern void printk_hook_unregister(void); static inline int printk_get_level(const char *buffer) { if (buffer[0] == KERN_SOH_ASCII && buffer[1]) { diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 82e293a..eb45e81 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -62,6 +62,19 @@ int console_printk[4] = { CONSOLE_LOGLEVEL_DEFAULT, /* default_console_loglevel */ }; +static printk_hook_t __rcu *printk_hook __read_mostly; +void printk_hook_register(printk_hook_t *hook) +{ + rcu_assign_pointer(printk_hook, hook); +} +EXPORT_SYMBOL(printk_hook_register); +void printk_hook_unregister(void) +{ + RCU_INIT_POINTER(printk_hook, NULL); + synchronize_rcu(); +} +EXPORT_SYMBOL(printk_hook_unregister); + /* * Low level drivers may need that to know if they can schedule in * their unblank() callback or not. So let's export it. @@ -1673,6 +1686,15 @@ asmlinkage int vprintk_emit(int facility, int level, /* cpu currently holding logbuf_lock in this function */ static unsigned int logbuf_cpu = UINT_MAX; + printk_hook_t *pr_hook = rcu_dereference(printk_hook); + static bool first_time_pr_hook = true; + u64 hook_seq,pre_next_seq; + u32 hook_idx,pre_next_idx; + struct printk_log *hook_msg; + //static char textbuf[LOG_LINE_MAX]; + size_t len; + + if (level == LOGLEVEL_SCHED) { level = LOGLEVEL_DEFAULT; in_sched = true; @@ -1707,6 +1729,9 @@ asmlinkage int vprintk_emit(int facility, int level, lockdep_off(); raw_spin_lock(&logbuf_lock); logbuf_cpu = this_cpu; + + pre_next_idx = log_next_idx; + pre_next_seq = log_next_seq; if (unlikely(recursion_bug)) { static const char recursion_msg[] = @@ -1800,6 +1825,28 @@ asmlinkage int vprintk_emit(int facility, int level, printed_len += log_store(facility, level, lflags, 0, dict, dictlen, text, text_len); } + + if(pr_hook){ + if(first_time_pr_hook || (level == LOGLEVEL_EMERG)){ + cont_flush(LOG_NEWLINE); + } + if(first_time_pr_hook){ + hook_idx = log_first_idx; + hook_seq = log_first_seq; + first_time_pr_hook = false; + }else{ + hook_idx = pre_next_idx; + hook_seq = pre_next_seq; + } + + for(; hook_seq != log_next_seq;hook_seq ++){ + hook_msg = log_from_idx(hook_idx); + len = sizeof(textbuf); + len = msg_print_text(hook_msg,0,false,textbuf,len); + pr_hook(textbuf,len); + hook_idx = log_next(hook_idx); + } + } logbuf_cpu = UINT_MAX; raw_spin_unlock(&logbuf_lock);
|