xref: /spdk/lib/trace_parser/trace.cpp (revision 55f64c36c6b612e046b209d672d61b7cd66fc352)
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 
38 #include <exception>
39 #include <new>
40 
41 struct spdk_trace_parser {
42 	spdk_trace_parser(const spdk_trace_parser_opts *opts);
43 	~spdk_trace_parser();
44 	spdk_trace_parser(const spdk_trace_parser &) = delete;
45 	spdk_trace_parser &operator=(const spdk_trace_parser &) = delete;
46 private:
47 	bool init(const spdk_trace_parser_opts *opts);
48 	void cleanup();
49 
50 	spdk_trace_histories	*_histories;
51 	size_t			_map_size;
52 	int			_fd;
53 };
54 
55 bool
56 spdk_trace_parser::init(const spdk_trace_parser_opts *opts)
57 {
58 	struct stat st;
59 	int rc;
60 
61 	switch (opts->mode) {
62 	case SPDK_TRACE_PARSER_MODE_FILE:
63 		_fd = open(opts->filename, O_RDONLY);
64 		break;
65 	case SPDK_TRACE_PARSER_MODE_SHM:
66 		_fd = shm_open(opts->filename, O_RDONLY, 0600);
67 		break;
68 	default:
69 		SPDK_ERRLOG("Invalid mode: %d\n", opts->mode);
70 		return false;
71 	}
72 
73 	if (_fd < 0) {
74 		SPDK_ERRLOG("Could not open trace file: %s (%d)\n", opts->filename, errno);
75 		return false;
76 	}
77 
78 	rc = fstat(_fd, &st);
79 	if (rc < 0) {
80 		SPDK_ERRLOG("Could not get size of trace file: %s\n", opts->filename);
81 		return false;
82 	}
83 
84 	if ((size_t)st.st_size < sizeof(*_histories)) {
85 		SPDK_ERRLOG("Invalid trace file: %s\n", opts->filename);
86 		return false;
87 	}
88 
89 	/* Map the header of trace file */
90 	_map_size = sizeof(*_histories);
91 	_histories = static_cast<spdk_trace_histories *>(mmap(NULL, _map_size, PROT_READ,
92 			MAP_SHARED, _fd, 0));
93 	if (_histories == MAP_FAILED) {
94 		SPDK_ERRLOG("Could not mmap trace file: %s\n", opts->filename);
95 		_histories = NULL;
96 		return false;
97 	}
98 
99 	/* Remap the entire trace file */
100 	_map_size = spdk_get_trace_histories_size(_histories);
101 	munmap(_histories, sizeof(*_histories));
102 	if ((size_t)st.st_size < _map_size) {
103 		SPDK_ERRLOG("Trace file %s is not valid\n", opts->filename);
104 		_histories = NULL;
105 		return false;
106 	}
107 	_histories = static_cast<spdk_trace_histories *>(mmap(NULL, _map_size, PROT_READ,
108 			MAP_SHARED, _fd, 0));
109 	if (_histories == MAP_FAILED) {
110 		SPDK_ERRLOG("Could not mmap trace file: %s\n", opts->filename);
111 		_histories = NULL;
112 		return false;
113 	}
114 
115 	return true;
116 }
117 
118 void
119 spdk_trace_parser::cleanup()
120 {
121 	if (_histories != NULL) {
122 		munmap(_histories, _map_size);
123 	}
124 
125 	if (_fd > 0) {
126 		close(_fd);
127 	}
128 }
129 
130 spdk_trace_parser::spdk_trace_parser(const spdk_trace_parser_opts *opts) :
131 	_histories(NULL),
132 	_map_size(0),
133 	_fd(-1)
134 {
135 	if (!init(opts)) {
136 		cleanup();
137 		throw std::exception();
138 	}
139 }
140 
141 spdk_trace_parser::~spdk_trace_parser()
142 {
143 	cleanup();
144 }
145 
146 struct spdk_trace_parser *
147 spdk_trace_parser_init(const struct spdk_trace_parser_opts *opts)
148 {
149 	try {
150 		return new spdk_trace_parser(opts);
151 	} catch (...) {
152 		return NULL;
153 	}
154 }
155 
156 void
157 spdk_trace_parser_cleanup(struct spdk_trace_parser *parser)
158 {
159 	delete parser;
160 }
161