Messages in this thread Patch in this message | | | Subject | Re: [PATCH] x86: Avoid pr_cont() in show_opcodes() | From | Rasmus Villemoes <> | Date | Tue, 17 Jul 2018 11:01:14 +0200 |
| |
On 2018-07-07 15:54, Tetsuo Handa wrote: > On 2018/07/07 20:12, Ingo Molnar wrote: >> >> * Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> wrote: >> >>> From: Tetsuo Handa <penguin-kernel@I-love.SKAURA.ne.jp> >>> >>> Since syzbot is confused by concurrent printk() messages [1], >>> this patch changes show_opcodes() to use snprintf(). >>> >>> When we start adding prefix to each line of printk() output, >>> we will be able to handle concurrent printk() messages. >>> >>> [1] https://syzkaller.appspot.com/text?tag=CrashReport&x=139d342c400000 >> >> Does this change the output? >> >> - If yes, could you show the before/after output in the changelog, >> >> - If not (i.e. if only the number of printk calls is changed, the output is the >> same), could you say so in the changelog? > > This patch will not change the output unless multiple threads concurrently > call printk(). The purpose of this patch is to help parsing kernel messages > when multiple threads are concurrently calling printk() for multiple times > (e.g. backtrace) by reducing pr_cont()/KERN_CONT usage. > >> >> Also, 3*OPCODE_BUFSIZE+2+1 is 195 bytes - isn't that a bit too much on-stack >> footprint? > > Then, we can reduce it by OPCODE_BUFSIZE bytes by unionizing opcodes[] and buf[].
Why not this instead? Less stack use, less code, no intermediary snprintfs, no pr_cont...
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index 666a284116ac..c881e8a757d9 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c @@ -93,26 +93,16 @@ static void printk_stack_address(unsigned long address, int reliable, */ void show_opcodes(u8 *rip, const char *loglvl) { - unsigned int code_prologue = OPCODE_BUFSIZE * 2 / 3; + unsigned int prologue = OPCODE_BUFSIZE * 2 / 3; u8 opcodes[OPCODE_BUFSIZE]; - u8 *ip; - int i;
- printk("%sCode: ", loglvl); - - ip = (u8 *)rip - code_prologue; - if (probe_kernel_read(opcodes, ip, OPCODE_BUFSIZE)) { - pr_cont("Bad RIP value.\n"); + if (probe_kernel_read(opcodes, rip - prologue, OPCODE_BUFSIZE)) { + printk("%sCode: Bad RIP value.\n", loglvl); return; } - - for (i = 0; i < OPCODE_BUFSIZE; i++, ip++) { - if (ip == rip) - pr_cont("<%02x> ", opcodes[i]); - else - pr_cont("%02x ", opcodes[i]); - } - pr_cont("\n"); + printk("%sCode: %*ph <%02x> %*ph\n", loglvl, + prologue, &opcodes[0], opcodes[prologue], + OPCODE_BUFSIZE - prologue - 1, &opcodes[prologue + 1]); }
void show_ip(struct pt_regs *regs, const char *loglvl) Not compile-tested, probably whitespace-damaged, but you get the idea.
Rasmus
| |