Skip to content

Commit ab6c036

Browse files
committed
ARC: show_regs: lockdep: avoid page allocator...
and use smaller/on-stack buffer instead The motivation for this change was lockdep splat like below. | potentially unexpected fatal signal 11. | BUG: sleeping function called from invalid context at ../mm/page_alloc.c:4317 | in_atomic(): 1, irqs_disabled(): 0, pid: 57, name: segv | no locks held by segv/57. | Preemption disabled at: | [<8182f17e>] get_signal+0x4a6/0x7c4 | CPU: 0 PID: 57 Comm: segv Not tainted 4.17.0+ #23 | | Stack Trace: | arc_unwind_core.constprop.1+0xd0/0xf4 | __might_sleep+0x1f6/0x234 | __get_free_pages+0x174/0xca0 | show_regs+0x22/0x330 | get_signal+0x4ac/0x7c4 # print_fatal_signals() -> preempt_disable() | do_signal+0x30/0x224 | resume_user_mode_begin+0x90/0xd8 So signal handling core calls show_regs() with preemption disabled but an ensuing GFP_KERNEL page allocator call is flagged by lockdep. We could have switched to GFP_NOWAIT, but turns out that is not enough anways and eliding page allocator call leads to less code and instruction traces to sift thru when debugging pesky crashes. FWIW, this patch doesn't cure the lockdep splat (which next patch does). Reviewed-by: William Kucharski <[email protected]> Signed-off-by: Vineet Gupta <[email protected]>
1 parent 2913326 commit ab6c036

File tree

1 file changed

+12
-14
lines changed

1 file changed

+12
-14
lines changed

arch/arc/kernel/troubleshoot.c

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include <asm/arcregs.h>
1919
#include <asm/irqflags.h>
2020

21+
#define ARC_PATH_MAX 256
22+
2123
/*
2224
* Common routine to print scratch regs (r0-r12) or callee regs (r13-r25)
2325
* -Prints 3 regs per line and a CR.
@@ -58,11 +60,12 @@ static void show_callee_regs(struct callee_regs *cregs)
5860
print_reg_file(&(cregs->r13), 13);
5961
}
6062

61-
static void print_task_path_n_nm(struct task_struct *tsk, char *buf)
63+
static void print_task_path_n_nm(struct task_struct *tsk)
6264
{
6365
char *path_nm = NULL;
6466
struct mm_struct *mm;
6567
struct file *exe_file;
68+
char buf[ARC_PATH_MAX];
6669

6770
mm = get_task_mm(tsk);
6871
if (!mm)
@@ -72,18 +75,17 @@ static void print_task_path_n_nm(struct task_struct *tsk, char *buf)
7275
mmput(mm);
7376

7477
if (exe_file) {
75-
path_nm = file_path(exe_file, buf, 255);
78+
path_nm = file_path(exe_file, buf, ARC_PATH_MAX-1);
7679
fput(exe_file);
7780
}
7881

7982
done:
8083
pr_info("Path: %s\n", !IS_ERR(path_nm) ? path_nm : "?");
8184
}
8285

83-
static void show_faulting_vma(unsigned long address, char *buf)
86+
static void show_faulting_vma(unsigned long address)
8487
{
8588
struct vm_area_struct *vma;
86-
char *nm = buf;
8789
struct mm_struct *active_mm = current->active_mm;
8890

8991
/* can't use print_vma_addr() yet as it doesn't check for
@@ -96,8 +98,11 @@ static void show_faulting_vma(unsigned long address, char *buf)
9698
* if the container VMA is not found
9799
*/
98100
if (vma && (vma->vm_start <= address)) {
101+
char buf[ARC_PATH_MAX];
102+
char *nm = "?";
103+
99104
if (vma->vm_file) {
100-
nm = file_path(vma->vm_file, buf, PAGE_SIZE - 1);
105+
nm = file_path(vma->vm_file, buf, ARC_PATH_MAX-1);
101106
if (IS_ERR(nm))
102107
nm = "?";
103108
}
@@ -173,13 +178,8 @@ void show_regs(struct pt_regs *regs)
173178
{
174179
struct task_struct *tsk = current;
175180
struct callee_regs *cregs;
176-
char *buf;
177181

178-
buf = (char *)__get_free_page(GFP_KERNEL);
179-
if (!buf)
180-
return;
181-
182-
print_task_path_n_nm(tsk, buf);
182+
print_task_path_n_nm(tsk);
183183
show_regs_print_info(KERN_INFO);
184184

185185
show_ecr_verbose(regs);
@@ -189,7 +189,7 @@ void show_regs(struct pt_regs *regs)
189189
(void *)regs->blink, (void *)regs->ret);
190190

191191
if (user_mode(regs))
192-
show_faulting_vma(regs->ret, buf); /* faulting code, not data */
192+
show_faulting_vma(regs->ret); /* faulting code, not data */
193193

194194
pr_info("[STAT32]: 0x%08lx", regs->status32);
195195

@@ -221,8 +221,6 @@ void show_regs(struct pt_regs *regs)
221221
cregs = (struct callee_regs *)current->thread.callee_reg;
222222
if (cregs)
223223
show_callee_regs(cregs);
224-
225-
free_page((unsigned long)buf);
226224
}
227225

228226
void show_kernel_fault_diag(const char *str, struct pt_regs *regs,

0 commit comments

Comments
 (0)