Merge branch 'master' of ssh://axboe@router.home.kernel.dk/data/git/blktrace
[blktrace.git] / blkparse.c
index a2badc6a2fa571074aaacf3582f70efaa7a6369d..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))
@@ -544,7 +552,7 @@ static struct process_pid_map *find_ppm(pid_t pid)
        return NULL;
 }
 
-static void add_ppm_hash(pid_t pid, const char *name)
+static struct process_pid_map *add_ppm_hash(pid_t pid, const char *name)
 {
        const int hash_idx = ppm_hash_pid(pid);
        struct process_pid_map *ppm;
@@ -558,6 +566,8 @@ static void add_ppm_hash(pid_t pid, const char *name)
                ppm->hash_next = ppm_hash_table[hash_idx];
                ppm_hash_table[hash_idx] = ppm;
        }
+
+       return ppm;
 }
 
 static void handle_notify(struct blk_io_trace *bit)
@@ -588,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 */
                ;
@@ -937,6 +963,8 @@ static struct io_track *find_track(struct per_dev_info *pdi, pid_t pid,
        if (!iot) {
                iot = malloc(sizeof(*iot));
                iot->ppm = find_ppm(pid);
+               if (!iot->ppm)
+                       iot->ppm = add_ppm_hash(pid, "unknown");
                iot->sector = sector;
                track_rb_insert(pdi, iot);
        }
@@ -1119,6 +1147,8 @@ static struct io_stats *find_process_io_stats(pid_t pid)
                ppi = malloc(sizeof(*ppi));
                memset(ppi, 0, sizeof(*ppi));
                ppi->ppm = find_ppm(pid);
+               if (!ppi->ppm)
+                       ppi->ppm = add_ppm_hash(pid, "unknown");
                add_ppi_to_hash(ppi);
                add_ppi_to_list(ppi);
        }
@@ -1561,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;
@@ -1571,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);
@@ -1582,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);
 }
 
 /*
@@ -2170,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;
@@ -2313,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);
@@ -2418,17 +2457,19 @@ static int handle(struct ms_stream *msp)
        struct blk_io_trace *bit;
 
        t = ms_peek(msp);
-       if (t->bit->time > stopwatch_end)
-               return 0;
 
        bit = t->bit;
        pdi = msp->pdi;
        pci = get_cpu_info(pdi, msp->cpu);
        pci->nelems++;
-
        bit->time -= genesis_time;
+
+       if (t->bit->time > stopwatch_end)
+               return 0;
+
        pdi->last_reported_time = bit->time;
-       if (bit->action & (act_mask << BLK_TC_SHIFT))
+       if ((bit->action & (act_mask << BLK_TC_SHIFT))&&
+           t->bit->time >= stopwatch_start)
                dump_trace(bit, pci, pdi);
 
        ms_deq(msp);
@@ -2613,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" \
@@ -2630,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" \
@@ -2648,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";
 
@@ -2738,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;
@@ -2815,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);