diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-16 13:23:43 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-16 13:23:43 -0500 |
| commit | 60d9aa758c00f20ade0cb1951f6a934f628dd2d7 (patch) | |
| tree | e3bdfa4ec0d3f9a29a822810b8b9188c7d613cbd /kernel | |
| parent | b2adf0cbec4cf0934c63f48f893e0cebde380d0c (diff) | |
| parent | 2e16cfca6e17ae37ae21feca080a6f2eca9087dc (diff) | |
Merge git://git.infradead.org/mtd-2.6
* git://git.infradead.org/mtd-2.6: (90 commits)
jffs2: Fix long-standing bug with symlink garbage collection.
mtd: OneNAND: Fix test of unsigned in onenand_otp_walk()
mtd: cfi_cmdset_0002, fix lock imbalance
Revert "mtd: move mxcnd_remove to .exit.text"
mtd: m25p80: add support for Macronix MX25L4005A
kmsg_dump: fix build for CONFIG_PRINTK=n
mtd: nandsim: add support for 4KiB pages
mtd: mtdoops: refactor as a kmsg_dumper
mtd: mtdoops: make record size configurable
mtd: mtdoops: limit the maximum mtd partition size
mtd: mtdoops: keep track of used/unused pages in an array
mtd: mtdoops: several minor cleanups
core: Add kernel message dumper to call on oopses and panics
mtd: add ARM pismo support
mtd: pxa3xx_nand: Fix PIO data transfer
mtd: nand: fix multi-chip suspend problem
mtd: add support for switching old SST chips into QRY mode
mtd: fix M29W800D dev_id and uaddr
mtd: don't use PF_MEMALLOC
mtd: Add bad block table overrides to Davinci NAND driver
...
Fixed up conflicts (mostly trivial) in
drivers/mtd/devices/m25p80.c
drivers/mtd/maps/pcmciamtd.c
drivers/mtd/nand/pxa3xx_nand.c
kernel/printk.c
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/panic.c | 3 | ||||
| -rw-r--r-- | kernel/printk.c | 119 |
2 files changed, 122 insertions, 0 deletions
diff --git a/kernel/panic.c b/kernel/panic.c index 96b45d0b4ba5..5827f7b97254 100644 --- a/kernel/panic.c +++ b/kernel/panic.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | */ | 10 | */ |
| 11 | #include <linux/debug_locks.h> | 11 | #include <linux/debug_locks.h> |
| 12 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> |
| 13 | #include <linux/kmsg_dump.h> | ||
| 13 | #include <linux/kallsyms.h> | 14 | #include <linux/kallsyms.h> |
| 14 | #include <linux/notifier.h> | 15 | #include <linux/notifier.h> |
| 15 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| @@ -74,6 +75,7 @@ NORET_TYPE void panic(const char * fmt, ...) | |||
| 74 | dump_stack(); | 75 | dump_stack(); |
| 75 | #endif | 76 | #endif |
| 76 | 77 | ||
| 78 | kmsg_dump(KMSG_DUMP_PANIC); | ||
| 77 | /* | 79 | /* |
| 78 | * If we have crashed and we have a crash kernel loaded let it handle | 80 | * If we have crashed and we have a crash kernel loaded let it handle |
| 79 | * everything else. | 81 | * everything else. |
| @@ -339,6 +341,7 @@ void oops_exit(void) | |||
| 339 | { | 341 | { |
| 340 | do_oops_enter_exit(); | 342 | do_oops_enter_exit(); |
| 341 | print_oops_end_marker(); | 343 | print_oops_end_marker(); |
| 344 | kmsg_dump(KMSG_DUMP_OOPS); | ||
| 342 | } | 345 | } |
| 343 | 346 | ||
| 344 | #ifdef WANT_WARN_ON_SLOWPATH | 347 | #ifdef WANT_WARN_ON_SLOWPATH |
diff --git a/kernel/printk.c b/kernel/printk.c index b5ac4d99c667..1ded8e7dd19b 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include <linux/syscalls.h> | 34 | #include <linux/syscalls.h> |
| 35 | #include <linux/kexec.h> | 35 | #include <linux/kexec.h> |
| 36 | #include <linux/ratelimit.h> | 36 | #include <linux/ratelimit.h> |
| 37 | #include <linux/kmsg_dump.h> | ||
| 37 | 38 | ||
| 38 | #include <asm/uaccess.h> | 39 | #include <asm/uaccess.h> |
| 39 | 40 | ||
| @@ -1405,4 +1406,122 @@ bool printk_timed_ratelimit(unsigned long *caller_jiffies, | |||
| 1405 | return false; | 1406 | return false; |
| 1406 | } | 1407 | } |
| 1407 | EXPORT_SYMBOL(printk_timed_ratelimit); | 1408 | EXPORT_SYMBOL(printk_timed_ratelimit); |
| 1409 | |||
| 1410 | static DEFINE_SPINLOCK(dump_list_lock); | ||
| 1411 | static LIST_HEAD(dump_list); | ||
| 1412 | |||
| 1413 | /** | ||
| 1414 | * kmsg_dump_register - register a kernel log dumper. | ||
| 1415 | * @dump: pointer to the kmsg_dumper structure | ||
| 1416 | * | ||
| 1417 | * Adds a kernel log dumper to the system. The dump callback in the | ||
| 1418 | * structure will be called when the kernel oopses or panics and must be | ||
| 1419 | * set. Returns zero on success and %-EINVAL or %-EBUSY otherwise. | ||
| 1420 | */ | ||
| 1421 | int kmsg_dump_register(struct kmsg_dumper *dumper) | ||
| 1422 | { | ||
| 1423 | unsigned long flags; | ||
| 1424 | int err = -EBUSY; | ||
| 1425 | |||
| 1426 | /* The dump callback needs to be set */ | ||
| 1427 | if (!dumper->dump) | ||
| 1428 | return -EINVAL; | ||
| 1429 | |||
| 1430 | spin_lock_irqsave(&dump_list_lock, flags); | ||
| 1431 | /* Don't allow registering multiple times */ | ||
| 1432 | if (!dumper->registered) { | ||
| 1433 | dumper->registered = 1; | ||
| 1434 | list_add_tail(&dumper->list, &dump_list); | ||
| 1435 | err = 0; | ||
| 1436 | } | ||
| 1437 | spin_unlock_irqrestore(&dump_list_lock, flags); | ||
| 1438 | |||
| 1439 | return err; | ||
| 1440 | } | ||
| 1441 | EXPORT_SYMBOL_GPL(kmsg_dump_register); | ||
| 1442 | |||
| 1443 | /** | ||
| 1444 | * kmsg_dump_unregister - unregister a kmsg dumper. | ||
| 1445 | * @dump: pointer to the kmsg_dumper structure | ||
| 1446 | * | ||
| 1447 | * Removes a dump device from the system. Returns zero on success and | ||
| 1448 | * %-EINVAL otherwise. | ||
| 1449 | */ | ||
| 1450 | int kmsg_dump_unregister(struct kmsg_dumper *dumper) | ||
| 1451 | { | ||
| 1452 | unsigned long flags; | ||
| 1453 | int err = -EINVAL; | ||
| 1454 | |||
| 1455 | spin_lock_irqsave(&dump_list_lock, flags); | ||
| 1456 | if (dumper->registered) { | ||
| 1457 | dumper->registered = 0; | ||
| 1458 | list_del(&dumper->list); | ||
| 1459 | err = 0; | ||
| 1460 | } | ||
| 1461 | spin_unlock_irqrestore(&dump_list_lock, flags); | ||
| 1462 | |||
| 1463 | return err; | ||
| 1464 | } | ||
| 1465 | EXPORT_SYMBOL_GPL(kmsg_dump_unregister); | ||
| 1466 | |||
| 1467 | static const char const *kmsg_reasons[] = { | ||
| 1468 | [KMSG_DUMP_OOPS] = "oops", | ||
| 1469 | [KMSG_DUMP_PANIC] = "panic", | ||
| 1470 | }; | ||
| 1471 | |||
| 1472 | static const char *kmsg_to_str(enum kmsg_dump_reason reason) | ||
| 1473 | { | ||
| 1474 | if (reason >= ARRAY_SIZE(kmsg_reasons) || reason < 0) | ||
| 1475 | return "unknown"; | ||
| 1476 | |||
| 1477 | return kmsg_reasons[reason]; | ||
| 1478 | } | ||
| 1479 | |||
| 1480 | /** | ||
| 1481 | * kmsg_dump - dump kernel log to kernel message dumpers. | ||
| 1482 | * @reason: the reason (oops, panic etc) for dumping | ||
| 1483 | * | ||
| 1484 | * Iterate through each of the dump devices and call the oops/panic | ||
| 1485 | * callbacks with the log buffer. | ||
| 1486 | */ | ||
| 1487 | void kmsg_dump(enum kmsg_dump_reason reason) | ||
| 1488 | { | ||
| 1489 | unsigned long end; | ||
| 1490 | unsigned chars; | ||
| 1491 | struct kmsg_dumper *dumper; | ||
| 1492 | const char *s1, *s2; | ||
| 1493 | unsigned long l1, l2; | ||
| 1494 | unsigned long flags; | ||
| 1495 | |||
| 1496 | /* Theoretically, the log could move on after we do this, but | ||
| 1497 | there's not a lot we can do about that. The new messages | ||
| 1498 | will overwrite the start of what we dump. */ | ||
| 1499 | spin_lock_irqsave(&logbuf_lock, flags); | ||
| 1500 | end = log_end & LOG_BUF_MASK; | ||
| 1501 | chars = logged_chars; | ||
| 1502 | spin_unlock_irqrestore(&logbuf_lock, flags); | ||
| 1503 | |||
| 1504 | if (logged_chars > end) { | ||
| 1505 | s1 = log_buf + log_buf_len - logged_chars + end; | ||
| 1506 | l1 = logged_chars - end; | ||
| 1507 | |||
| 1508 | s2 = log_buf; | ||
| 1509 | l2 = end; | ||
| 1510 | } else { | ||
| 1511 | s1 = ""; | ||
| 1512 | l1 = 0; | ||
| 1513 | |||
| 1514 | s2 = log_buf + end - logged_chars; | ||
| 1515 | l2 = logged_chars; | ||
| 1516 | } | ||
| 1517 | |||
| 1518 | if (!spin_trylock_irqsave(&dump_list_lock, flags)) { | ||
| 1519 | printk(KERN_ERR "dump_kmsg: dump list lock is held during %s, skipping dump\n", | ||
| 1520 | kmsg_to_str(reason)); | ||
| 1521 | return; | ||
| 1522 | } | ||
| 1523 | list_for_each_entry(dumper, &dump_list, list) | ||
| 1524 | dumper->dump(dumper, reason, s1, l1, s2, l2); | ||
| 1525 | spin_unlock_irqrestore(&dump_list_lock, flags); | ||
| 1526 | } | ||
| 1408 | #endif | 1527 | #endif |
