clang compiled kernel panic when mounting zfs root on i386
Konstantin Belousov
kostikbel at gmail.com
Thu Nov 29 23:29:50 UTC 2012
On Tue, Nov 27, 2012 at 08:21:05AM +1100, Bruce Evans wrote:
> On Mon, 26 Nov 2012, Konstantin Belousov wrote:
>
> > On Mon, Nov 26, 2012 at 06:31:34AM -0800, sig6247 wrote:
> >>
> >> Just checked out r243529, this only happens when the kernel is compiled
> >> by clang, and only on i386, either recompiling the kernel with gcc or
> >> booting from a UFS root works fine. Is it a known problem?
> > It looks like that clang uses more stack than gcc, and zfs makes quite
> > deep call chains.
...
> It would be useful if the stack trace printed the the stack pointer
> on every function call, so that you could see how much stack each
> function used.
Please apply the patch below and obtain the backtrace of the double fault
panic again. I will commit the patch later.
diff --git a/sys/amd64/amd64/db_trace.c b/sys/amd64/amd64/db_trace.c
index cba90f2..2c81f87 100644
--- a/sys/amd64/amd64/db_trace.c
+++ b/sys/amd64/amd64/db_trace.c
@@ -186,7 +186,8 @@ db_ss(struct db_variable *vp, db_expr_t *valuep, int op)
static void db_nextframe(struct amd64_frame **, db_addr_t *, struct thread *);
static int db_numargs(struct amd64_frame *);
-static void db_print_stack_entry(const char *, int, char **, long *, db_addr_t);
+static void db_print_stack_entry(const char *, int, char **, long *, db_addr_t,
+ void *);
static void decode_syscall(int, struct thread *);
static const char * watchtype_str(int type);
@@ -230,12 +231,13 @@ db_numargs(fp)
}
static void
-db_print_stack_entry(name, narg, argnp, argp, callpc)
+db_print_stack_entry(name, narg, argnp, argp, callpc, frame)
const char *name;
int narg;
char **argnp;
long *argp;
db_addr_t callpc;
+ void *frame;
{
db_printf("%s(", name);
#if 0
@@ -250,6 +252,8 @@ db_print_stack_entry(name, narg, argnp, argp, callpc)
#endif
db_printf(") at ");
db_printsym(callpc, DB_STGY_PROC);
+ if (frame != NULL)
+ db_printf("/frame 0x%lx", (register_t)frame);
db_printf("\n");
}
@@ -341,7 +345,7 @@ db_nextframe(struct amd64_frame **fp, db_addr_t *ip, struct thread *td)
return;
}
- db_print_stack_entry(name, 0, 0, 0, rip);
+ db_print_stack_entry(name, 0, 0, 0, rip, &(*fp)->f_frame);
/*
* Point to base of trapframe which is just above the
@@ -437,7 +441,8 @@ db_backtrace(struct thread *td, struct trapframe *tf,
* Don't try to walk back on a stack for a
* process that hasn't actually been run yet.
*/
- db_print_stack_entry(name, 0, 0, 0, pc);
+ db_print_stack_entry(name, 0, 0, 0, pc,
+ actframe);
break;
}
first = FALSE;
@@ -451,7 +456,7 @@ db_backtrace(struct thread *td, struct trapframe *tf,
narg = db_numargs(frame);
}
- db_print_stack_entry(name, narg, argnp, argp, pc);
+ db_print_stack_entry(name, narg, argnp, argp, pc, actframe);
if (actframe != frame) {
/* `frame' belongs to caller. */
@@ -465,7 +470,7 @@ db_backtrace(struct thread *td, struct trapframe *tf,
if (INKERNEL((long)pc) && !INKERNEL((long)frame)) {
sym = db_search_symbol(pc, DB_STGY_ANY, &offset);
db_symbol_values(sym, &name, NULL);
- db_print_stack_entry(name, 0, 0, 0, pc);
+ db_print_stack_entry(name, 0, 0, 0, pc, frame);
break;
}
if (!INKERNEL((long) frame)) {
diff --git a/sys/i386/i386/db_trace.c b/sys/i386/i386/db_trace.c
index 445d9c5..822cc56 100644
--- a/sys/i386/i386/db_trace.c
+++ b/sys/i386/i386/db_trace.c
@@ -176,7 +176,8 @@ db_ss(struct db_variable *vp, db_expr_t *valuep, int op)
static void db_nextframe(struct i386_frame **, db_addr_t *, struct thread *);
static int db_numargs(struct i386_frame *);
-static void db_print_stack_entry(const char *, int, char **, int *, db_addr_t);
+static void db_print_stack_entry(const char *, int, char **, int *, db_addr_t,
+ void *);
static void decode_syscall(int, struct thread *);
static const char * watchtype_str(int type);
@@ -220,12 +221,13 @@ retry:
}
static void
-db_print_stack_entry(name, narg, argnp, argp, callpc)
+db_print_stack_entry(name, narg, argnp, argp, callpc, frame)
const char *name;
int narg;
char **argnp;
int *argp;
db_addr_t callpc;
+ void *frame;
{
int n = narg >= 0 ? narg : 5;
@@ -242,6 +244,8 @@ db_print_stack_entry(name, narg, argnp, argp, callpc)
db_printf(",...");
db_printf(") at ");
db_printsym(callpc, DB_STGY_PROC);
+ if (frame != NULL)
+ db_printf("/frame 0x%r", (register_t)frame);
db_printf("\n");
}
@@ -326,7 +330,7 @@ db_nextframe(struct i386_frame **fp, db_addr_t *ip, struct thread *td)
return;
}
- db_print_stack_entry(name, 0, 0, 0, eip);
+ db_print_stack_entry(name, 0, 0, 0, eip, &(*fp)->f_frame);
/*
* For a double fault, we have to snag the values from the
@@ -467,7 +471,8 @@ db_backtrace(struct thread *td, struct trapframe *tf, struct i386_frame *frame,
* Don't try to walk back on a stack for a
* process that hasn't actually been run yet.
*/
- db_print_stack_entry(name, 0, 0, 0, pc);
+ db_print_stack_entry(name, 0, 0, 0, pc,
+ actframe);
break;
}
first = FALSE;
@@ -481,7 +486,7 @@ db_backtrace(struct thread *td, struct trapframe *tf, struct i386_frame *frame,
narg = db_numargs(frame);
}
- db_print_stack_entry(name, narg, argnp, argp, pc);
+ db_print_stack_entry(name, narg, argnp, argp, pc, actframe);
if (actframe != frame) {
/* `frame' belongs to caller. */
@@ -495,7 +500,7 @@ db_backtrace(struct thread *td, struct trapframe *tf, struct i386_frame *frame,
if (INKERNEL((int)pc) && !INKERNEL((int) frame)) {
sym = db_search_symbol(pc, DB_STGY_ANY, &offset);
db_symbol_values(sym, &name, NULL);
- db_print_stack_entry(name, 0, 0, 0, pc);
+ db_print_stack_entry(name, 0, 0, 0, pc, frame);
break;
}
if (!INKERNEL((int) frame)) {
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 834 bytes
Desc: not available
URL: <http://lists.freebsd.org/pipermail/freebsd-fs/attachments/20121130/29bda775/attachment.sig>
More information about the freebsd-fs
mailing list