Merge branch 'master' of ssh://axboe@router.home.kernel.dk/data/git/blktrace
[blktrace.git] / blkparse.c
index 517dde5841ab6f2c26edfa0890615bbd65edec6c..ef556974b0d321625d23d5ea20a5abb892562f25 100644 (file)
@@ -36,7 +36,7 @@
 #include "rbtree.h"
 #include "jhash.h"
 
-static char blkparse_version[] = "0.99.3";
+static char blkparse_version[] = "1.0.0";
 
 struct skip_info {
        unsigned long start, end;
@@ -104,7 +104,6 @@ static struct per_process_info *ppi_hash_table[PPI_HASH_SIZE];
 static struct per_process_info *ppi_list;
 static int ppi_list_entries;
 
-#define S_OPTS  "a:A:b:D:d:f:F:hi:o:Oqstw:vV"
 static struct option l_opts[] = {
        {
                .name = "act-mask",
@@ -160,6 +159,12 @@ static struct option l_opts[] = {
                .flag = NULL,
                .val = 'i'
        },
+       {
+               .name = "no-msgs",
+               .has_arg = no_argument,
+               .flag = NULL,
+               .val = 'M'
+       },
        {
                .name = "output",
                .has_arg = required_argument,
@@ -270,6 +275,7 @@ static int ppi_hash_by_pid = 1;
 static int verbose;
 static unsigned int act_mask = -1U;
 static int stats_printed;
+static int bin_output_msgs = 1;
 int data_is_native = -1;
 
 static FILE *dump_fp;
@@ -292,6 +298,8 @@ static volatile int done;
 struct timespec                abs_start_time;
 static unsigned long long start_timestamp;
 
+static int have_drv_data = 0;
+
 #define JHASH_RANDOM   (0x3af5f2ee)
 
 #define CPUS_PER_LONG  (8 * sizeof(unsigned long))
@@ -590,6 +598,22 @@ static void handle_notify(struct blk_io_trace *bit)
 
                break;
 
+       case BLK_TN_MESSAGE:
+               if (bit->pdu_len > 0) {
+                       char msg[bit->pdu_len+1];
+
+                       memcpy(msg, (char *)payload, bit->pdu_len);
+                       msg[bit->pdu_len] = '\0';
+
+                       fprintf(ofp,
+                               "%3d,%-3d %2d %8s %5d.%09lu %5u %2s %3s %s\n",
+                               MAJOR(bit->device), MINOR(bit->device),
+                               bit->cpu, "0", (int) SECONDS(bit->time),
+                               (unsigned long) NANO_SECONDS(bit->time),
+                               0, "m", "N", msg);
+               }
+               break;
+
        default:
                /* Ignore unknown notify events */
                ;
@@ -1567,6 +1591,10 @@ static void dump_trace_fs(struct blk_io_trace *t, struct per_dev_info *pdi,
                case __BLK_TA_REMAP:
                        log_generic(pci, t, "A");
                        break;
+               case __BLK_TA_DRV_DATA:
+                       have_drv_data = 1;
+                       /* dump to binary file only */
+                       break;
                default:
                        fprintf(stderr, "Bad fs action %x\n", t->action);
                        break;
@@ -1577,7 +1605,9 @@ static void dump_trace(struct blk_io_trace *t, struct per_cpu_info *pci,
                       struct per_dev_info *pdi)
 {
        if (text_output) {
-               if (t->action & BLK_TC_ACT(BLK_TC_PC))
+               if (t->action == BLK_TN_MESSAGE)
+                       handle_notify(t);
+               else if (t->action & BLK_TC_ACT(BLK_TC_PC))
                        dump_trace_pc(t, pdi, pci);
                else
                        dump_trace_fs(t, pdi, pci);
@@ -1588,7 +1618,10 @@ static void dump_trace(struct blk_io_trace *t, struct per_cpu_info *pci,
 
        pdi->events++;
 
-       output_binary(t, sizeof(*t) + t->pdu_len);
+       if (bin_output_msgs ||
+                           !(t->action & BLK_TC_ACT(BLK_TC_NOTIFY) &&
+                             t->action == BLK_TN_MESSAGE))
+               output_binary(t, sizeof(*t) + t->pdu_len);
 }
 
 /*
@@ -2176,7 +2209,7 @@ static int read_events(int fd, int always_block, int *fdblock)
                /*
                 * not a real trace, so grab and handle it here
                 */
-               if (bit->action & BLK_TC_ACT(BLK_TC_NOTIFY)) {
+               if (bit->action & BLK_TC_ACT(BLK_TC_NOTIFY) && bit->action != BLK_TN_MESSAGE) {
                        handle_notify(bit);
                        output_binary(bit, sizeof(*bit) + bit->pdu_len);
                        continue;
@@ -2319,7 +2352,7 @@ static int ms_prime(struct ms_stream *msp)
                if (verify_trace(bit))
                        goto err;
 
-               if (bit->action & BLK_TC_ACT(BLK_TC_NOTIFY)) {
+               if (bit->action & BLK_TC_ACT(BLK_TC_NOTIFY) && bit->action != BLK_TN_MESSAGE) {
                        handle_notify(bit);
                        output_binary(bit, sizeof(*bit) + bit->pdu_len);
                        bit_free(bit);
@@ -2621,7 +2654,7 @@ static int is_pipe(const char *str)
        return 0;
 }
 
-#define S_OPTS  "a:A:b:D:d:f:F:hi:o:Oqstw:vV"
+#define S_OPTS  "a:A:b:D:d:f:F:hi:o:Oqstw:vVM"
 static char usage_str[] =    "\n\n" \
        "-i <file>           | --input=<file>\n" \
        "[ -a <action field> | --act-mask=<action field> ]\n" \
@@ -2638,6 +2671,7 @@ static char usage_str[] =    "\n\n" \
        "[ -s                | --per-program-stats ]\n" \
        "[ -t                | --track-ios ]\n" \
        "[ -w <time>         | --stopwatch=<time> ]\n" \
+       "[ -M                | --no-msgs\n" \
        "[ -v                | --verbose ]\n" \
        "[ -V                | --version ]\n\n" \
        "\t-b stdin read batching\n" \
@@ -2656,6 +2690,7 @@ static char usage_str[] =    "\n\n" \
        "\t   to get queued, to get dispatched, and to get completed\n" \
        "\t-w Only parse data between the given time interval in seconds.\n" \
        "\t   If 'start' isn't given, blkparse defaults the start time to 0\n" \
+       "\t-M Do not output messages to binary file\n" \
        "\t-v More verbose for marginal errors\n" \
        "\t-V Print program version info\n\n";
 
@@ -2746,6 +2781,9 @@ int main(int argc, char *argv[])
                case 'd':
                        dump_binary = optarg;
                        break;
+               case 'M':
+                       bin_output_msgs = 0;
+                       break;
                default:
                        usage(argv[0]);
                        return 1;
@@ -2823,6 +2861,10 @@ int main(int argc, char *argv[])
        if (!ret)
                show_stats();
 
+       if (have_drv_data && !dump_binary)
+               printf("\ndiscarded traces containing low-level device driver "
+                      "specific data (only available in binary output)\n");
+
        if (ofp_buffer) {
                fflush(ofp);
                free(ofp_buffer);