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

Dave Anderson anderson at redhat.com
Thu Apr 24 13:06:50 UTC 2014



----- Original Message -----
> Hi Qiao,
> 
> Can you fix a typo in one of the strings (doesn't affect the functionality of
> the extension module and isn't likely to confuse anyone):
> 
>        fprintf(fp, "cannot get private_datad of file structure\n");
> 
> This line should have private_data not private_datad in the string.
> 
> Thanks
> Shane

I went ahead and fixed the sockq.c version available from the extensions page.

Dave

> 
> -----Original Message-----
> From: crash-utility-bounces at redhat.com
> [mailto:crash-utility-bounces at redhat.com] On Behalf Of Dave Anderson
> Sent: Wednesday, April 23, 2014 1:26 AM
> To: Discussion list for crash utility usage, maintenance and development
> Subject: Re: [Crash-utility] [PATCH] extension: get socket receive queue into
> a file
> 
> 
> 
> 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
> > 
> 
> --
> Crash-utility mailing list
> Crash-utility at redhat.com
> https://www.redhat.com/mailman/listinfo/crash-utility
> 
> --
> 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