diff options
-rw-r--r-- | mboxd.c | 20 | ||||
-rw-r--r-- | mboxd.h | 6 | ||||
-rw-r--r-- | protocol.c | 109 |
3 files changed, 133 insertions, 2 deletions
@@ -54,7 +54,8 @@ const char* USAGE = "\t\t\t\t(default: fill the reserved memory region)\n" "\t-w | --window-size\tThe window size (power of 2) in MB\n" "\t\t\t\t(default: 1MB)\n" - "\t-f | --flash\t\tSize of flash in [K|M] bytes\n\n"; + "\t-f | --flash\t\tSize of flash in [K|M] bytes\n\n" + "\t-t | --trace\t\tFile to write trace data to (in blktrace format)\n\n"; static int dbus_init(struct mbox_context *context, const struct transport_ops **ops) @@ -236,6 +237,7 @@ static bool parse_cmdline(int argc, char **argv, { "window-num", optional_argument, 0, 'n' }, { "verbose", no_argument, 0, 'v' }, { "syslog", no_argument, 0, 's' }, + { "trace", optional_argument, 0, 't' }, { "version", no_argument, 0, 'V' }, { "help", no_argument, 0, 'h' }, { 0, 0, 0, 0 } @@ -246,7 +248,7 @@ static bool parse_cmdline(int argc, char **argv, context->current = NULL; /* No current window */ - while ((opt = getopt_long(argc, argv, "f:b:w::n::vsVh", long_options, NULL)) + while ((opt = getopt_long(argc, argv, "f:b:w::n::vst::Vh", long_options, NULL)) != -1) { switch (opt) { case 0: @@ -309,6 +311,17 @@ static bool parse_cmdline(int argc, char **argv, case 'V': printf("%s V%s\n", THIS_NAME, PACKAGE_VERSION); exit(0); + case 't': + context->blktracefd = open(argv[optind], + O_CREAT|O_TRUNC|O_WRONLY, + 0666); + printf("Recording blktrace output to %s\n", + argv[optind]); + if (context->blktracefd == -1) { + perror("Couldn't open blktrace file for writing"); + exit(2); + } + break; case 'h': return false; /* This will print the usage message */ default: @@ -480,6 +493,9 @@ cleanup_protocol: cleanup_backend: backend_free(&context->backend); cleanup_context: + if (context->blktracefd) + close(context->blktracefd); + free(context); return rc; @@ -5,6 +5,7 @@ #define MBOX_H #include <assert.h> +#include <linux/blktrace_api.h> #include <mtd/mtd-abi.h> #include <systemd/sd-bus.h> #include <poll.h> @@ -101,6 +102,11 @@ struct mbox_context { uint32_t mem_size; /* LPC Bus Base Address (bytes) */ uint32_t lpc_base; + + /* Tracing */ + int blktracefd; + struct blk_io_trace trace; + int64_t blktrace_start; }; #endif /* MBOX_H */ @@ -5,6 +5,7 @@ #include <errno.h> #include <stdint.h> #include <stdio.h> +#include <unistd.h> #include "backend.h" #include "common.h" @@ -13,6 +14,7 @@ #include "protocol.h" #include "windows.h" + #define BLOCK_SIZE_SHIFT_V1 12 /* 4K */ static inline uint8_t protocol_get_bmc_event_mask(struct mbox_context *context) @@ -155,6 +157,109 @@ static inline uint16_t get_lpc_addr_shifted(struct mbox_context *context) return lpc_addr >> context->backend.block_size_shift; } +static inline int64_t blktrace_gettime(void) +{ + struct timespec ts; + int64_t n; + + clock_gettime(CLOCK_REALTIME, &ts); + n = (int64_t)(ts.tv_sec) * (int64_t)1000000000 + (int64_t)(ts.tv_nsec); + + return n; +} + +static void blktrace_flush_start(struct mbox_context *context) +{ + struct blk_io_trace *trace = &context->trace; + struct timespec now; + + if (!context->blktracefd) + return; + + if (!context->blktrace_start) { + clock_gettime(CLOCK_REALTIME, &now); + context->blktrace_start = blktrace_gettime(); + } + + trace->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION; + trace->sequence++; + trace->time = blktrace_gettime() - context->blktrace_start; + trace->sector = context->current->flash_offset / 512; + trace->bytes = context->current->size; + if (context->current_is_write) + trace->action = BLK_TA_QUEUE | BLK_TC_ACT(BLK_TC_WRITE); + else + trace->action = BLK_TA_QUEUE | BLK_TC_ACT(BLK_TC_READ); + trace->pid = 0; + trace->device = 0; + trace->cpu = 0; + trace->error = 0; + trace->pdu_len = 0; + write(context->blktracefd, trace, sizeof(*trace)); + trace->sequence++; + trace->time = blktrace_gettime() - context->blktrace_start; + trace->action &= ~BLK_TA_QUEUE; + trace->action |= BLK_TA_ISSUE; + write(context->blktracefd, trace, sizeof(*trace)); +} + +static void blktrace_flush_done(struct mbox_context *context) +{ + struct blk_io_trace *trace = &context->trace; + + if (!context->blktracefd) + return; + + trace->sequence++; + trace->time = blktrace_gettime() - context->blktrace_start; + trace->action &= ~BLK_TA_ISSUE; + trace->action |= BLK_TA_COMPLETE; + write(context->blktracefd, trace, sizeof(*trace)); +} + +static void blktrace_window_start(struct mbox_context *context) +{ + struct blk_io_trace *trace = &context->trace; + + if (!context->blktracefd) + return; + + if (!context->blktrace_start) + context->blktrace_start = blktrace_gettime(); + + trace->magic = BLK_IO_TRACE_MAGIC | BLK_IO_TRACE_VERSION; + trace->sequence++; + trace->time = blktrace_gettime() - context->blktrace_start; + trace->action = BLK_TA_QUEUE | BLK_TC_ACT(BLK_TC_READ); + trace->pid = 0; + trace->device = 0; + trace->cpu = 0; + trace->error = 0; + trace->pdu_len = 0; +} + +static void blktrace_window_done(struct mbox_context *context) +{ + struct blk_io_trace *trace = &context->trace; + + if (!context->blktracefd) + return; + + trace->sector = context->current->flash_offset / 512; + trace->bytes = context->current->size; + write(context->blktracefd, trace, sizeof(*trace)); + trace->sequence++; + trace->action &= ~BLK_TA_QUEUE; + trace->action |= BLK_TA_ISSUE; + write(context->blktracefd, trace, sizeof(*trace)); + + trace->sequence++; + trace->time = blktrace_gettime() - context->blktrace_start; + trace->action &= ~BLK_TA_ISSUE; + trace->action |= BLK_TA_COMPLETE; + write(context->blktracefd, trace, sizeof(*trace)); +} + static int protocol_v1_create_window(struct mbox_context *context, struct protocol_create_window *io) { @@ -180,7 +285,9 @@ static int protocol_v1_create_window(struct mbox_context *context, * write_flush() to make sure we pick the right one. */ if (context->current_is_write) { + blktrace_flush_start(context); rc = context->protocol->flush(context, NULL); + blktrace_flush_done(context); if (rc < 0) { MSG_ERR("Couldn't Flush Write Window\n"); return rc; @@ -192,6 +299,7 @@ static int protocol_v1_create_window(struct mbox_context *context, /* Offset the host has requested */ MSG_INFO("Host requested flash @ 0x%.8x\n", offset); /* Check if we have an existing window */ + blktrace_window_start(context); context->current = windows_search(context, offset, context->version == API_VERSION_1); @@ -206,6 +314,7 @@ static int protocol_v1_create_window(struct mbox_context *context, return rc; } } + blktrace_window_done(context); context->current_is_write = !io->req.ro; |