linux
linux copied to clipboard
Update printk.c
Adding new function , int type_printk(int type, const char *fmt, ...) , it will print an output and adding type , 1 : [error] . 2 [log] 3 [action] . TODO : other types
Does we need a 'break' statement at the end of 'case 0' block?
yes it's been added . others types will be added
Why does in case 1 sprintf() need to be called before local_irq_save()? Since there is no 'undefined type' for which we don't do anything, local_irq_save() and some other routines are going to be used anyway, why not leave repeated statements out of the switch?
int printk_type(int type, const char *fmt, ...) { unsigned long flags; va_list args; char *buf; int r;
local_irq_save(flags);
buf = __get_cpu_var(printk_sched_buf);
switch(type){
case 0:
va_start(args, fmt);
r = vsnprintf(buf, PRINTK_BUF_SIZE, fmt, args);
break;
case 1:
const char *all_fmt;
sprintf(all_fmt, "[Error] : %s", fmt);
va_start(args, all_fmt)
r = vsnprintf(buf, PRINTK_BUF_SIZE, all_fmt, args);
break;
}
va_end(args);
__this_cpu_or(printk_pending, PRINTK_PENDING_SCHED);
irq_work_queue(&__get_cpu_var(wake_up_klogd_work));
local_irq_restore(flags);
return r;
}
Yes it's been added to , and also the default case .
Also, if you want the function to be visible inside the kernel API (as printk() is) you should add this underneath the closing brace of the function:
EXPORT_SYMBOL(type_printk);
This is exactly why Linus doesn't support pull requests via GitHub. Your willingness to contribute to an open source project is appreciated, but you can't just send pull requests to a major project with broken, untested code. Read the docs, go through the proper vetting process, and THEN submit your pull requests (but not here).
OP's current code doesn't work. I made a working version, for educational purposes. Applying this commit (https://github.com/kjenova/linux/commit/26eb273d60d91a0979468e094ea0718348599d65) to the latest kernel (3.15.0-rc7), building the kernel, running it, compiling this module against the kernel and running this module:
#include "/where_your_3.15rc-7_kernel_source_is/linux/module.h" #include "/where_your_3.15rc-7_kernel_source_is/linux/kernel.h"
int init_module() { printk(KERN_INFO "using printk() with KERN_INFO macro."); printk(KERN_WARNING "using printk() with KERN_WARNING macro."); printk(KERN_ERR "using printk() with KERN_ERR macro.");
printk(KERN_INFO "switching to type_printk().");
type_printk(0, "using type_printk() with normal type.");
type_printk(1, "using type_printk() with error type.");
type_printk(2. "using type_printk() with action type.");
type_printk(-1, "using type_printk() with unsupported type.");
return 0;
}
void exit_module(void) {
}
produces this output on the /usr/var/kern.log of my machine (my .config is http://pastebin.com/BcZCkp8i):
/begin
May 31 17:07:28 kje-desktop kernel: [ 177.015377] test_type_printk: module license 'unspecified' taints kernel. May 31 17:07:28 kje-desktop kernel: [ 177.015382] Disabling lock debugging due to kernel taint May 31 17:07:28 kje-desktop kernel: [ 177.015461] using printk() with KERN_INFO macro. May 31 17:07:28 kje-desktop kernel: [ 177.015463] using printk() with KERN_WARNING macro.using printk() with KERN_ERR macro. May 31 17:07:56 kje-desktop kernel: [ 177.015472] switching to type_printk().using type_printk() with normal type.[Error] : using type_printk() with error type.[Action] : using type_printk() with action type.using type_printk() with unsupported type. May 31 17:07:56 kje-desktop kernel: [ 205.352376] general protection fault: 0000 [#1] SMP May 31 17:07:56 kje-desktop kernel: [ 205.352385] Modules linked in: test_type_printk(PO)
/end
I don't see a reason, why to add this change to the kernel. If there is a reason, go with it through the above mentioned process.
Well, the reason your code didn't work is, that you should've put it under the declaration of wake_up_klogd() (as printk_sched(), on which your code is based on, is).
thank you guys for you comments , i have updated the code
Don't forget to add this line to include/linux/printk.h
/begin
asmlinkage __printf(2, 3) __cold int type_printk(int type, char *fmt, ...);
/end
The macro __printf(2, 3) tells us, that the second (we don't start counting at zero here, zero means argument not supplied) argument will be the format string and the third the va_list. __cold is a compiler hint, it tells us to optimise (but not so "agressively", it's "cold" because of that) this functions and place it near other "cold" functions (from: http://axon.cs.byu.edu/~adam/gatheredinfo/tips/tips_gcc.php).
On a side note: your original function also compiles and works (you should put that func at the very end, however), if you add kmalloc(). You can also use the printk_sched() function (I used it in type_printk_using_printk_sched() function).
The full code:
/include/linux/printk.h
add this:
asmlinkage __printf(2, 3) __cold int type_printk(int type, char *fmt, ...);
asmlinkage __printf(2, 3) __cold int type_printk_using_printk_sched(int type, char *fmt, ...);
/kernel/printk.c
add this:
asmlinkage __visible int type_printk(int type, char *fmt, ...) { va_list args; char *buf; char *all_fmt; int r; unsigned long flags;
local_irq_save(flags);
buf = __get_cpu_var(printk_sched_buf);
switch(type) {
default:
va_start(args, fmt);
r = vsnprintf(buf, PRINTK_BUF_SIZE, fmt, args);
break;
case 1:
all_fmt = kmalloc(sizeof(fmt)+11*sizeof(char), GFP_KERNEL);
sprintf(all_fmt, "[Error] : %s", fmt);
va_start(args, all_fmt);
r = vsnprintf(buf, PRINTK_BUF_SIZE, all_fmt, args);
kfree(all_fmt);
break;
case 2:
all_fmt = kmalloc(sizeof(fmt)+12*sizeof(char), GFP_KERNEL);
sprintf(all_fmt, "[Action] : %s", fmt);
va_start(args, all_fmt);
r = vsnprintf(buf, PRINTK_BUF_SIZE, all_fmt, args);
kfree(all_fmt);
break;
}
va_end(args);
__this_cpu_or(printk_pending, PRINTK_PENDING_SCHED);
irq_work_queue(&__get_cpu_var(wake_up_klogd_work));
local_irq_restore(flags);
return r;
} EXPORT_SYMBOL(type_printk);
asmlinkage __visible int type_printk_using_printk_sched(int type, char *fmt, ...) { va_list args; char *all_fmt; int r;
switch(type) {
default:
va_start(args, fmt);
r = printk_sched(fmt, args);
case 1:
all_fmt = kmalloc(sizeof(fmt)+11*sizeof(char), GFP_KERNEL);
sprintf(all_fmt, "[Error] : %s\n", fmt);
va_start(args, all_fmt);
r = printk_sched(all_fmt, args);
kfree(all_fmt);
break;
case 2:
all_fmt = kmalloc(sizeof(fmt)+12*sizeof(char), GFP_KERNEL);
sprintf(all_fmt, "[Action] : %s\n", fmt);
va_start(args, all_fmt);
r = printk_sched(all_fmt, args);
kfree(all_fmt);
break;
}
return r;
} EXPORT_SYMBOL(type_printk_using_printk_sched);
/begin
Jun 1 20:20:15 kje-desktop kernel: [ 67.877502] test_type_printk: module license 'unspecified' taints kernel. Jun 1 20:20:15 kje-desktop kernel: [ 67.877506] Disabling lock debugging due to kernel taint Jun 1 20:20:15 kje-desktop kernel: [ 67.877569] using printk() with KERN_INFO macro. Jun 1 20:20:15 kje-desktop kernel: [ 67.877570] using printk() with KERN_WARNING macro.using printk() with KERN_ERR macro. Jun 1 20:20:15 kje-desktop kernel: [ 67.877572] switching to type_printk().switching to type_printk_using_printk_sched(). Jun 1 20:20:15 kje-desktop kernel: [ 67.877765] [sched_delayed] [Error] : using type_printk_using_printk_sched() with unsupported type.
/end
Important: as seen, only one of the outputs of those functions is seen, due to scheduling. So you're better off with the current version!
ok I corrected the code