[Crash-utility] [PATCH] extension: get socket receive queue into a file

Dave Anderson anderson at redhat.com
Tue Apr 22 15:26:03 UTC 2014



Thanks Qiao -- I've posted the module in the extensions page:
  
 http://people.redhat.com/anderson/extensions.html#SOCKQ

Dave

----- Original Message -----
> 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 at cn.fujitsu.com>
> ---
>  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 at cn.fujitsu.com>
> + *
> + * 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 at redhat.com
> https://www.redhat.com/mailman/listinfo/crash-utility
> 




More information about the Crash-utility mailing list