mtdoops and non pre-emptible kernel

Matthew Lear matt at bubblegen.co.uk
Wed Aug 26 13:41:35 EDT 2009


Hello,

I'm trying to use the mtd oops feature on a non pre-emptible m68k
coldfire Linux kernel. Problem is, there is nothing being written to
flash upon a kernel panic. I'm passing the correct syntax on the command
line and I can see the kernel messages indicating that everything is ok, ie:

/ # dmesg | grep -i mtd
[    0.000000] Kernel command line: console=ttyS0,115200 ip=dhcp
root=/dev/nfs nfsroot=192.168.0.2:/home/matt/nfs/evb/rootfs/ rw
mtdparts=physmap-flash.0:4M at 0x80000(kernel)ro,5M at 0x480000(r
amdisk),- at 0x980000(writeable) console=ttyMTD2
[    0.336920] console [ttyMTD2] enabled
[    0.933655] 3 cmdlinepart partitions found on MTD device physmap-flash.0
[    0.940745] Creating 3 MTD partitions on "physmap-flash.0":
[    0.951893] mtd: Giving out device 0 to kernel
[    0.965760] mtd: Giving out device 1 to ramdisk
[    0.979124] mtd: Giving out device 2 to writeable
[    0.993942] mtdoops: Ready 8, 9 (no erase)
[    0.993979] mtdoops: Attached to MTD device 2

The issue appears to be that the call to schedule_work() in
mtdoops_console_sync() does not result in mtdoops_workfunc_write() being
invoked to perform the flash write.

I understand that there is only a very small window in which to actually
flush the buffer to flash (involving a spinlock and testing
oops_in_progress). However, from what I can tell, on a non pre-emptible
kernel, after panic() does it's business of calling bust_spinlocks(),
which calls console_unblank(), which calls mtdoops_console_sync(), which
calls schedule_work(), there is no way [certainly that I can see] that
the system can context switch to the worker thread in order to invoke
the routine that actually writes to flash.

The only way I have been able to get the flash to be written to upon
panic is to make the following change:

diff --git a/drivers/mtd/mtdoops.c b/drivers/mtd/mtdoops.c
index 1a6b3be..2d734e2 100644
--- a/drivers/mtd/mtdoops.c
+++ b/drivers/mtd/mtdoops.c
@@ -335,7 +335,7 @@ static void mtdoops_console_sync(void)
                /* Interrupt context, we're going to panic so try and log */
                mtdoops_write(cxt, 1);
        else
-               schedule_work(&cxt->work_write);
+               mtdoops_write(cxt, 0);
 }

 static void

I can pull out the logs just fine in user space using oopslog, courtesy
of Mr Purdie.

I can replicate the same situation (worker thread not executing the
registered scheduled work routine) on my system with a simple kernel
module (attached). Without the call to schedule, the system does not
panic. In the case of the attached example, this is not surprising since
there is nothing to force a context switch. The kernel sits in the loop
forever and will warn about a soft lock up (if this feature is enabled).

I have tried invoking schedule() immediately after schedule_work() in
mtdoops_console_sync(). However this still results in flash not being
written to when there is a panic. I realise that now there are of course
other factors at play which could explain why the flash never gets
written to, (specifically related to scheduling, eg thread time slices,
quantums etc), but I wanted to point out that there certainly appears to
be a couple of cases in mtdoops.c where there should be calls to
schedule() after calls to schedule_work() - only there aren't.

I don't mean to criticise the code :-) I'm an avid user of open source,
but I'd be interested if the mtd oops feature works reliably on other
non pre-emptive kernels.

Thoughts? Any feedback much appreciated.

Best regards,
--  Matt
-------------- next part --------------
A non-text attachment was scrubbed...
Name: work.c
Type: text/x-csrc
Size: 757 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20090826/220130e8/attachment.bin>


More information about the linux-mtd mailing list