xref: /spdk/lib/trace_parser/trace.cpp (revision 41ba2b30e79b7f7069fcc14e5409b8c42cee6df3)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk/stdinc.h"
35 #include "spdk/log.h"
36 #include "spdk/trace_parser.h"
37 #include "spdk/util.h"
38 
39 #include <exception>
40 #include <new>
41 
42 struct spdk_trace_parser {
43 	spdk_trace_parser(const spdk_trace_parser_opts *opts);
44 	~spdk_trace_parser();
45 	spdk_trace_parser(const spdk_trace_parser &) = delete;
46 	spdk_trace_parser &operator=(const spdk_trace_parser &) = delete;
47 	const spdk_trace_flags *flags() const { return &_histories->flags; }
48 private:
49 	bool init(const spdk_trace_parser_opts *opts);
50 	void cleanup();
51 
52 	spdk_trace_histories	*_histories;
53 	size_t			_map_size;
54 	int			_fd;
55 };
56 
57 bool
58 spdk_trace_parser::init(const spdk_trace_parser_opts *opts)
59 {
60 	struct stat st;
61 	int rc;
62 
63 	switch (opts->mode) {
64 	case SPDK_TRACE_PARSER_MODE_FILE:
65 		_fd = open(opts->filename, O_RDONLY);
66 		break;
67 	case SPDK_TRACE_PARSER_MODE_SHM:
68 		_fd = shm_open(opts->filename, O_RDONLY, 0600);
69 		break;
70 	default:
71 		SPDK_ERRLOG("Invalid mode: %d\n", opts->mode);
72 		return false;
73 	}
74 
75 	if (_fd < 0) {
76 		SPDK_ERRLOG("Could not open trace file: %s (%d)\n", opts->filename, errno);
77 		return false;
78 	}
79 
80 	rc = fstat(_fd, &st);
81 	if (rc < 0) {
82 		SPDK_ERRLOG("Could not get size of trace file: %s\n", opts->filename);
83 		return false;
84 	}
85 
86 	if ((size_t)st.st_size < sizeof(*_histories)) {
87 		SPDK_ERRLOG("Invalid trace file: %s\n", opts->filename);
88 		return false;
89 	}
90 
91 	/* Map the header of trace file */
92 	_map_size = sizeof(*_histories);
93 	_histories = static_cast<spdk_trace_histories *>(mmap(NULL, _map_size, PROT_READ,
94 			MAP_SHARED, _fd, 0));
95 	if (_histories == MAP_FAILED) {
96 		SPDK_ERRLOG("Could not mmap trace file: %s\n", opts->filename);
97 		_histories = NULL;
98 		return false;
99 	}
100 
101 	/* Remap the entire trace file */
102 	_map_size = spdk_get_trace_histories_size(_histories);
103 	munmap(_histories, sizeof(*_histories));
104 	if ((size_t)st.st_size < _map_size) {
105 		SPDK_ERRLOG("Trace file %s is not valid\n", opts->filename);
106 		_histories = NULL;
107 		return false;
108 	}
109 	_histories = static_cast<spdk_trace_histories *>(mmap(NULL, _map_size, PROT_READ,
110 			MAP_SHARED, _fd, 0));
111 	if (_histories == MAP_FAILED) {
112 		SPDK_ERRLOG("Could not mmap trace file: %s\n", opts->filename);
113 		_histories = NULL;
114 		return false;
115 	}
116 
117 	return true;
118 }
119 
120 void
121 spdk_trace_parser::cleanup()
122 {
123 	if (_histories != NULL) {
124 		munmap(_histories, _map_size);
125 	}
126 
127 	if (_fd > 0) {
128 		close(_fd);
129 	}
130 }
131 
132 spdk_trace_parser::spdk_trace_parser(const spdk_trace_parser_opts *opts) :
133 	_histories(NULL),
134 	_map_size(0),
135 	_fd(-1)
136 {
137 	if (!init(opts)) {
138 		cleanup();
139 		throw std::exception();
140 	}
141 }
142 
143 spdk_trace_parser::~spdk_trace_parser()
144 {
145 	cleanup();
146 }
147 
148 struct spdk_trace_parser *
149 spdk_trace_parser_init(const struct spdk_trace_parser_opts *opts)
150 {
151 	try {
152 		return new spdk_trace_parser(opts);
153 	} catch (...) {
154 		return NULL;
155 	}
156 }
157 
158 void
159 spdk_trace_parser_cleanup(struct spdk_trace_parser *parser)
160 {
161 	delete parser;
162 }
163 
164 const struct spdk_trace_flags *
165 spdk_trace_parser_get_flags(const struct spdk_trace_parser *parser)
166 {
167 	return parser->flags();
168 }
169