summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mboxd.c20
-rw-r--r--mboxd.h6
-rw-r--r--protocol.c109
3 files changed, 133 insertions, 2 deletions
diff --git a/mboxd.c b/mboxd.c
index 2026023..637f416 100644
--- a/mboxd.c
+++ b/mboxd.c
@@ -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;
diff --git a/mboxd.h b/mboxd.h
index 96235d7..6b14a24 100644
--- a/mboxd.h
+++ b/mboxd.h
@@ -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 */
diff --git a/protocol.c b/protocol.c
index 7158bfc..ab1c332 100644
--- a/protocol.c
+++ b/protocol.c
@@ -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;
OpenPOWER on IntegriCloud