source: branches/backfire/target/linux/generic-2.6/patches-2.6.30/930-kmsg_dump_backport.patch @ 29023

Last change on this file since 29023 was 29023, checked in by florian, 4 years ago

refresh 2.6.30 patches

File size: 5.2 KB
  • new file include/linux/kmsg_dump.h

    - +  
     1/* 
     2 * linux/include/kmsg_dump.h 
     3 * 
     4 * Copyright (C) 2009 Net Insight AB 
     5 * 
     6 * Author: Simon Kagstrom <simon.kagstrom@netinsight.net> 
     7 * 
     8 * This file is subject to the terms and conditions of the GNU General Public 
     9 * License.  See the file COPYING in the main directory of this archive 
     10 * for more details. 
     11 */ 
     12#ifndef _LINUX_KMSG_DUMP_H 
     13#define _LINUX_KMSG_DUMP_H 
     14 
     15#include <linux/list.h> 
     16 
     17enum kmsg_dump_reason { 
     18        KMSG_DUMP_OOPS, 
     19        KMSG_DUMP_PANIC, 
     20}; 
     21 
     22/** 
     23 * struct kmsg_dumper - kernel crash message dumper structure 
     24 * @dump:       The callback which gets called on crashes. The buffer is passed 
     25 *              as two sections, where s1 (length l1) contains the older 
     26 *              messages and s2 (length l2) contains the newer. 
     27 * @list:       Entry in the dumper list (private) 
     28 * @registered: Flag that specifies if this is already registered 
     29 */ 
     30struct kmsg_dumper { 
     31        void (*dump)(struct kmsg_dumper *dumper, enum kmsg_dump_reason reason, 
     32                        const char *s1, unsigned long l1, 
     33                        const char *s2, unsigned long l2); 
     34        struct list_head list; 
     35        int registered; 
     36}; 
     37 
     38void kmsg_dump(enum kmsg_dump_reason reason); 
     39 
     40int kmsg_dump_register(struct kmsg_dumper *dumper); 
     41 
     42int kmsg_dump_unregister(struct kmsg_dumper *dumper); 
     43 
     44#endif /* _LINUX_KMSG_DUMP_H */ 
  • kernel/panic.c

    a b  
    1010 */ 
    1111#include <linux/debug_locks.h> 
    1212#include <linux/interrupt.h> 
     13#include <linux/kmsg_dump.h> 
    1314#include <linux/kallsyms.h> 
    1415#include <linux/notifier.h> 
    1516#include <linux/module.h> 
    NORET_TYPE void panic(const char * fmt, 
    7475        dump_stack(); 
    7576#endif 
    7677 
     78        kmsg_dump(KMSG_DUMP_PANIC); 
    7779        /* 
    7880         * If we have crashed and we have a crash kernel loaded let it handle 
    7981         * everything else. 
    void oops_exit(void) 
    337339{ 
    338340        do_oops_enter_exit(); 
    339341        print_oops_end_marker(); 
     342        kmsg_dump(KMSG_DUMP_OOPS); 
    340343} 
    341344 
    342345#ifdef WANT_WARN_ON_SLOWPATH 
  • kernel/printk.c

    a b  
    3333#include <linux/bootmem.h> 
    3434#include <linux/syscalls.h> 
    3535#include <linux/kexec.h> 
     36#include <linux/kmsg_dump.h> 
    3637 
    3738#include <asm/uaccess.h> 
    3839 
    bool printk_timed_ratelimit(unsigned lon 
    13221323} 
    13231324EXPORT_SYMBOL(printk_timed_ratelimit); 
    13241325#endif 
     1326 
     1327static DEFINE_SPINLOCK(dump_list_lock); 
     1328static LIST_HEAD(dump_list); 
     1329 
     1330/** 
     1331 * kmsg_dump_register - register a kernel log dumper. 
     1332 * @dump: pointer to the kmsg_dumper structure 
     1333 * 
     1334 * Adds a kernel log dumper to the system. The dump callback in the 
     1335 * structure will be called when the kernel oopses or panics and must be 
     1336 * set. Returns zero on success and %-EINVAL or %-EBUSY otherwise. 
     1337 */ 
     1338int kmsg_dump_register(struct kmsg_dumper *dumper) 
     1339{ 
     1340        unsigned long flags; 
     1341        int err = -EBUSY; 
     1342 
     1343        /* The dump callback needs to be set */ 
     1344        if (!dumper->dump) 
     1345                return -EINVAL; 
     1346 
     1347        spin_lock_irqsave(&dump_list_lock, flags); 
     1348        /* Don't allow registering multiple times */ 
     1349        if (!dumper->registered) { 
     1350                dumper->registered = 1; 
     1351                list_add_tail(&dumper->list, &dump_list); 
     1352                err = 0; 
     1353        } 
     1354        spin_unlock_irqrestore(&dump_list_lock, flags); 
     1355 
     1356        return err; 
     1357} 
     1358EXPORT_SYMBOL_GPL(kmsg_dump_register); 
     1359 
     1360/** 
     1361 * kmsg_dump_unregister - unregister a kmsg dumper. 
     1362 * @dump: pointer to the kmsg_dumper structure 
     1363 * 
     1364 * Removes a dump device from the system. Returns zero on success and 
     1365 * %-EINVAL otherwise. 
     1366 */ 
     1367int kmsg_dump_unregister(struct kmsg_dumper *dumper) 
     1368{ 
     1369        unsigned long flags; 
     1370        int err = -EINVAL; 
     1371 
     1372        spin_lock_irqsave(&dump_list_lock, flags); 
     1373        if (dumper->registered) { 
     1374                dumper->registered = 0; 
     1375                list_del(&dumper->list); 
     1376                err = 0; 
     1377        } 
     1378        spin_unlock_irqrestore(&dump_list_lock, flags); 
     1379 
     1380        return err; 
     1381} 
     1382EXPORT_SYMBOL_GPL(kmsg_dump_unregister); 
     1383 
     1384static const char const *kmsg_reasons[] = { 
     1385        [KMSG_DUMP_OOPS]        = "oops", 
     1386        [KMSG_DUMP_PANIC]       = "panic", 
     1387}; 
     1388 
     1389static const char *kmsg_to_str(enum kmsg_dump_reason reason) 
     1390{ 
     1391        if (reason >= ARRAY_SIZE(kmsg_reasons) || reason < 0) 
     1392                return "unknown"; 
     1393 
     1394        return kmsg_reasons[reason]; 
     1395} 
     1396 
     1397/** 
     1398 * kmsg_dump - dump kernel log to kernel message dumpers. 
     1399 * @reason: the reason (oops, panic etc) for dumping 
     1400 * 
     1401 * Iterate through each of the dump devices and call the oops/panic 
     1402 * callbacks with the log buffer. 
     1403 */ 
     1404void kmsg_dump(enum kmsg_dump_reason reason) 
     1405{ 
     1406        unsigned long end; 
     1407        unsigned chars; 
     1408        struct kmsg_dumper *dumper; 
     1409        const char *s1, *s2; 
     1410        unsigned long l1, l2; 
     1411        unsigned long flags; 
     1412 
     1413        /* Theoretically, the log could move on after we do this, but 
     1414           there's not a lot we can do about that. The new messages 
     1415           will overwrite the start of what we dump. */ 
     1416        spin_lock_irqsave(&logbuf_lock, flags); 
     1417        end = log_end & LOG_BUF_MASK; 
     1418        chars = logged_chars; 
     1419        spin_unlock_irqrestore(&logbuf_lock, flags); 
     1420 
     1421        if (logged_chars > end) { 
     1422                s1 = log_buf + log_buf_len - logged_chars + end; 
     1423                l1 = logged_chars - end; 
     1424 
     1425                s2 = log_buf; 
     1426                l2 = end; 
     1427        } else { 
     1428                s1 = ""; 
     1429                l1 = 0; 
     1430 
     1431                s2 = log_buf + end - logged_chars; 
     1432                l2 = logged_chars; 
     1433        } 
     1434 
     1435        if (!spin_trylock_irqsave(&dump_list_lock, flags)) { 
     1436                printk(KERN_ERR "dump_kmsg: dump list lock is held during %s, skipping dump\n", 
     1437                                kmsg_to_str(reason)); 
     1438                return; 
     1439        } 
     1440        list_for_each_entry(dumper, &dump_list, list) 
     1441                dumper->dump(dumper, reason, s1, l1, s2, l2); 
     1442        spin_unlock_irqrestore(&dump_list_lock, flags); 
     1443} 
Note: See TracBrowser for help on using the repository browser.