Subject: kern/35699: root-on-md can panic with "panic: init died"
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: Simon Burge <simonb@NetBSD.org>
List: netbsd-bugs
Date: 02/19/2007 06:55:00
>Number: 35699
>Category: kern
>Synopsis: root-on-md can panic with "panic: init died"
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Mon Feb 19 06:55:00 +0000 2007
>Originator: Simon Burge
>Release: -current from mid Feb 2007
>Organization:
>Environment:
PowerPC ports, maybe others?
>Description:
I've found a problem where starting up a PPC system with root on
a md(4) memory disk gets:
Process (pid 1) got signal 6
panic: init died (signal 0, exit 1)
while trying to start up. I've tracked this down to this change
in kern_sysctl.c:
revision 1.191
date: 2006/03/15 16:12:07; author: drochner; state: Exp; lines: +10 -2
branches: 1.191.2;
Check the "oldlen" argument to sysctl(2) before passing it
to vslock(9). This prevents a local DOS.
(The checks against system and user limits for wired
memory should be centralized in UVM; for now prefer a less
invasive fix which can be pulled pulled up into releases.)
which is:
if (l != NULL && oldp != NULL && savelen) {
+ /*
+ * be lazy - memory is locked for short time only, so
+ * just do a basic check against system limit
+ */
+ if (uvmexp.wired + atop(savelen) > uvmexp.wiredmax) {
+ lockmgr(&sysctl_treelock, LK_RELEASE, NULL);
+ return (ENOMEM);
+ }
error = uvm_vslock(l->l_proc, oldp, savelen, VM_PROT_WRITE);
What's happening is that uvmexp.wiredmax is initialised by the
pagedaemon kthread, and with root-on-md the pagedaemon thread
hasn't had a chance to run. This means that sysctl_lock()
decides it can't lock down any memory so the machdep.cacheinfo
sysctl fails, and syncicache() calls abort() because it's not
happy.
Usually, this system uses root-on-NFS and while we're waiting
for the dhcp dance to finish, the pagedaemon thread runs and
sets up uvmexp.wiredmax before /sbin/init starts.
With root-on-md there's no delays before /sbin/init starts
up. There are no disks or USB or any devices that would be
configured in config_interrupts() which can also introduce a
delay for the pagedaemon thread to run - another PPC system that
has a USB bus boots up fine with root-on-md, but init fails the
same way if USB is removed from the kernel config file.
>How-To-Repeat:
Make a root-on-md system that has nothing "fancy" configured
with config_interrupts().
>Fix:
The patch I'm using to work around this is:
- if (uvmexp.wired + atop(savelen) > uvmexp.wiredmax) {
+ if (uvmexp.wiredmax &&
+ uvmexp.wired + atop(savelen) > uvmexp.wiredmax) {
but this obviously isn't right.
I'm not sure if the correct fix is to call uvmpd_tune() (in
uvm_pdaemon.c) before kthreads run, or have something like
uvm_page_physload() update uvmexp.wiredmax directly? Or maybe
changes in sysctl_lock()?