diff --git a/lib/trace_parser/trace.cpp b/lib/trace_parser/trace.cpp index 839444844..8874b4770 100644 --- a/lib/trace_parser/trace.cpp +++ b/lib/trace_parser/trace.cpp @@ -32,14 +32,129 @@ */ #include "spdk/stdinc.h" +#include "spdk/log.h" #include "spdk/trace_parser.h" +#include +#include + +struct spdk_trace_parser { + spdk_trace_parser(const spdk_trace_parser_opts *opts); + ~spdk_trace_parser(); + spdk_trace_parser(const spdk_trace_parser &) = delete; + spdk_trace_parser &operator=(const spdk_trace_parser &) = delete; +private: + bool init(const spdk_trace_parser_opts *opts); + void cleanup(); + + spdk_trace_histories *_histories; + size_t _map_size; + int _fd; +}; + +bool +spdk_trace_parser::init(const spdk_trace_parser_opts *opts) +{ + struct stat st; + int rc; + + switch (opts->mode) { + case SPDK_TRACE_PARSER_MODE_FILE: + _fd = open(opts->filename, O_RDONLY); + break; + case SPDK_TRACE_PARSER_MODE_SHM: + _fd = shm_open(opts->filename, O_RDONLY, 0600); + break; + default: + SPDK_ERRLOG("Invalid mode: %d\n", opts->mode); + return false; + } + + if (_fd < 0) { + SPDK_ERRLOG("Could not open trace file: %s (%d)\n", opts->filename, errno); + return false; + } + + rc = fstat(_fd, &st); + if (rc < 0) { + SPDK_ERRLOG("Could not get size of trace file: %s\n", opts->filename); + return false; + } + + if ((size_t)st.st_size < sizeof(*_histories)) { + SPDK_ERRLOG("Invalid trace file: %s\n", opts->filename); + return false; + } + + /* Map the header of trace file */ + _map_size = sizeof(*_histories); + _histories = static_cast(mmap(NULL, _map_size, PROT_READ, + MAP_SHARED, _fd, 0)); + if (_histories == MAP_FAILED) { + SPDK_ERRLOG("Could not mmap trace file: %s\n", opts->filename); + _histories = NULL; + return false; + } + + /* Remap the entire trace file */ + _map_size = spdk_get_trace_histories_size(_histories); + munmap(_histories, sizeof(*_histories)); + if ((size_t)st.st_size < _map_size) { + SPDK_ERRLOG("Trace file %s is not valid\n", opts->filename); + _histories = NULL; + return false; + } + _histories = static_cast(mmap(NULL, _map_size, PROT_READ, + MAP_SHARED, _fd, 0)); + if (_histories == MAP_FAILED) { + SPDK_ERRLOG("Could not mmap trace file: %s\n", opts->filename); + _histories = NULL; + return false; + } + + return true; +} + +void +spdk_trace_parser::cleanup() +{ + if (_histories != NULL) { + munmap(_histories, _map_size); + } + + if (_fd > 0) { + close(_fd); + } +} + +spdk_trace_parser::spdk_trace_parser(const spdk_trace_parser_opts *opts) : + _histories(NULL), + _map_size(0), + _fd(-1) +{ + if (!init(opts)) { + cleanup(); + throw std::exception(); + } +} + +spdk_trace_parser::~spdk_trace_parser() +{ + cleanup(); +} + struct spdk_trace_parser * spdk_trace_parser_init(const struct spdk_trace_parser_opts *opts) { - return NULL; + try { + return new spdk_trace_parser(opts); + } catch (...) { + return NULL; + } } void spdk_trace_parser_cleanup(struct spdk_trace_parser *parser) -{} +{ + delete parser; +} diff --git a/mk/spdk.lib_deps.mk b/mk/spdk.lib_deps.mk index 68fd1a97a..fb5d81455 100644 --- a/mk/spdk.lib_deps.mk +++ b/mk/spdk.lib_deps.mk @@ -52,6 +52,7 @@ DEPDIRS-sock := log $(JSON_LIBS) DEPDIRS-util := log DEPDIRS-vmd := log DEPDIRS-dma := log +DEPDIRS-trace_parser := log ifeq ($(CONFIG_VFIO_USER),y) DEPDIRS-vfio_user := log endif