syslog() can be used to send messages to the system logger, and a socket is used to do the deliverying. So such a situation may be existed that the message is sent to the socket, but not received by syslogd yet. This module is used to dump the messages left in the socket. This module has been tested on RHEL5/6 x86/x64. The following program is used to generate a kdump core that got log messages left in socket. 1. compile the following c program to a.out <cut> int main(int argc, char **argv) { char buf[256]; int i = 0; for (i = 0; i < 1; i++) { openlog("syslog", LOG_CONS , 0); sprintf(buf, "[TEST] a very long test message is appropriate, but I do " "not know such a message (No.%d)\n", i); syslog(LOG_INFO, buf); closelog(); } return 0; } <cut> 2. run the following bash code to panic and generate a kdump core <cut> i=0 while [[ $i -lt 1000 ]];do ./a.out & echo $i i=$((i+1)) done echo c > /proc/sysrq-trigger i=0 while [[ $i -lt 1000 ]];do ./a.out & echo $i i=$((i+1)) done <cut> 3. run crash with the vmcore generated in step 2 and load sockq module. Then run command like below to get left log message <cut> crash> ps | grep syslog 1121 1 0 ffff880037ac2080 IN 0.2 249080 1740 rsyslogd 1123 1 1 ffff880037a00040 RU 0.2 249080 1740 rsyslogd 1124 1 1 ffff8800375f9540 IN 0.2 249080 1740 rsyslogd crash> files 1121 PID: 1121 TASK: ffff880037ac2080 CPU: 0 COMMAND: "rsyslogd" ROOT: / CWD: / FD FILE DENTRY INODE TYPE PATH 0 ffff88003e0d0b40 ffff88003ef29a80 ffff88003ef8c688 SOCK 1 ffff88003d8f1140 ffff88003efc3800 ffff88003d3d44c0 REG /var/log/messages 2 ffff88003d859180 ffff88003efadb40 ffff88003d3d40c0 REG /var/log/secure 3 ffff88003d8590c0 ffff88003ef29b40 ffff88003ef917f8 REG /proc/kmsg 4 ffff88003dfd1b40 ffff88003d1a7500 ffff88003d004cc0 REG /var/log/maillog 5 ffff88003dee7180 ffff88003d0b6980 ffff88003d0048c0 REG /var/log/cron crash> sockq ffff88003e0d0b40 out crash> cat out <14>Apr 17 16:32:56 syslog: [TEST] a very long test message is appropriate, but I do not know such a message (No.48) <14>Apr 17 16:32:56 syslog: [TEST] a very long test message is appropriate, but I do not know such a message (No.44) <14>Apr 17 16:32:56 syslog: [TEST] a very long test message is appropriate, but I do not know such a message (No.12) <14>Apr 17 16:32:56 syslog: [TEST] a very long test message is appropriate, but I do not know such a message (No.13) <14>Apr 17 16:32:56 syslog: [TEST] a very long test message is appropriate, but I do not know such a message (No.21) <14>Apr 17 16:32:56 syslog: [TEST] a very long test message is appropriate, but I do not know such a message (No.21) <14>Apr 17 16:32:56 syslog: [TEST] a very long test message is appropriate, but I do not know such a message (No.18) <14>Apr 17 16:32:56 syslog: [TEST] a very long test message is appropriate, but I do not know such a message (No.1) <14>Apr 17 16:32:56 syslog: [TEST] a very long test message is appropriate, but I do not know such a message (No.18) <14>Apr 17 16:32:56 syslog: [TEST] a very long test message is appropriate, but I do not know such a message (No.18) <14>Apr 17 16:32:56 syslog: [TEST] a very long test message is appropriate, but I do not know such a message (No.2) crash> <cut> Signed-off-by: Qiao Nuohan <qiaonuohan@xxxxxxxxxxxxxx> --- extensions/sockq.c | 203 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100644 extensions/sockq.c diff --git a/extensions/sockq.c b/extensions/sockq.c new file mode 100644 index 0000000..3784413 --- /dev/null +++ b/extensions/sockq.c @@ -0,0 +1,203 @@ +/* sockq.c - sockq extension module for crash + * + * Copyright (C) 2014 FUJITSU LIMITED + * Author: Qiao Nuohan <qiaonuohan@xxxxxxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include "defs.h" /* From the crash source top-level directory */ + +void sockq_init(void); /* constructor function */ +void sockq_fini(void); /* destructor function (optional) */ + +void cmd_sockq(void); /* Declare the commands and their help data. */ +char *help_sockq[]; + +static struct command_table_entry command_table[] = { + { "sockq", cmd_sockq, help_sockq, 0}, /* One or more commands, */ + { NULL }, /* terminated by NULL, */ +}; + +char *help_sockq[] = { +"sockq", /* command name */ +"get socket receive queue into a file", /* short description */ +"file_address outfile", /* argument synopsis */ + +" This command gets the data from the socket receive queue.", +" ", +" file_address A hexadecimal value of socket's file structure address.", +" outfile A name of output file. If the file already exists,", +" it is overwritten.", +NULL +}; + +void __attribute__((constructor)) +sockq_init(void) /* Register the command set. */ +{ + register_extension(command_table); +} + +/* + * This function is called if the shared object is unloaded. + * If desired, perform any cleanups here. + */ +void __attribute__((destructor)) +sockq_fini(void) { } + +static int +get_member_data(ulonglong addr, char *name, char *member, void* buf) +{ + ulong member_offset; + + member_offset = MEMBER_OFFSET(name, member); + + if (!readmem(addr + member_offset, KVADDR, buf, + MEMBER_SIZE(name, member), name, FAULT_ON_ERROR)) + return FALSE; + + return TRUE; +} + +/* + * write receive data in the specified file + */ +static int +write_data(int fd, char *buf, ulong addr, ulong size) +{ + ulong wsize; + + while (size > 0) { + /* size of the buffer is pagesize */ + wsize = (size > PAGESIZE()) ? PAGESIZE() : size; + + if (!readmem(addr, KVADDR, buf, wsize, "vaddr", FAULT_ON_ERROR)) { + fprintf(fp, "cannot read data from packet buffer\n"); + return 1; + } + + if (write(fd, buf, wsize) < 0) { + fprintf(fp, "cannot write data in a file\n"); + return 1; + } + + addr += wsize; + size -= wsize; + } + + return 0; +} + +int +do_sockq(ulong file_addr, char *output_file, int fd) +{ + int rc = 1; + ulong pd, sk; + uint qlen; + char *buf = NULL; + ulong next, head; + unsigned int len; + ulong wnext; + + if (!get_member_data(file_addr, "file", "private_data", &pd)) { + fprintf(fp, "cannot get private_datad of file structure\n"); + goto cleanup; + } + + if (!get_member_data(pd, "socket", "sk", &sk)) { + fprintf(fp, "cannot get sk of socket structure\n"); + goto cleanup; + } + + if (!get_member_data(sk + MEMBER_OFFSET("sock", "sk_receive_queue"), + "sk_buff_head", "next", &next)) { + fprintf(fp, "cannot get the first queue of sock structure\n"); + goto cleanup; + } + + if (!get_member_data(sk + MEMBER_OFFSET("sock", "sk_receive_queue"), + "sk_buff_head", "qlen", &qlen)) { + fprintf(fp, "cannot get the number of queue list\n"); + goto cleanup; + } + + /* create a output file */ + if (output_file != NULL && + (fd = open(output_file, + O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR)) < 0) { + fprintf(fp, "cannot create %s\n", output_file); + goto cleanup; + } + + if (qlen == 0) { + /* receive queue is empty */ + rc = 0; + goto cleanup; + } + + /* get work area */ + buf = GETBUF(PAGESIZE()); + + while (qlen-- > 0) { + /* get packet buffer are info */ + if (!get_member_data(next, "sk_buff", "head", &head)) { + fprintf(fp, "cannot head of sk_buff structure\n"); + goto cleanup; + } + + if (!get_member_data(next, "sk_buff", "len", &len)) { + fprintf(fp, "cannot tail of sk_buff structure\n"); + goto cleanup; + } + + /* write data in the output file */ + if (write_data(fd, buf, head, len)) + goto cleanup; + + /* next receive queue */ + wnext = next; + if (!get_member_data(wnext, "sk_buff", "next", &next)) { + fprintf(fp, "cannot get next of sk_buff structure\n"); + goto cleanup; + } + } + + /* all process normally ends */ + rc = 0; + +cleanup: + if (output_file != NULL) + close(fd); + if (buf) + FREEBUF(buf); + + return rc; +} + +void +cmd_sockq(void) +{ + ulong file_addr; + + if (argcnt != 3) + cmd_usage(pc->curcmd, SYNOPSIS); + + optind++; + file_addr = htol(args[optind], FAULT_ON_ERROR, NULL); + + optind++; + if (strlen(args[optind]) > PATH_MAX) { + fprintf(fp, "cannot create specified output file\n"); + return; + } + + do_sockq(file_addr, args[optind], -1); +} -- 1.8.5.3 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility