xref: /spdk/lib/ftl/ftl_trace.c (revision 94a84ae98590bea46939eb1dcd7a9876bd393b54)
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/trace.h"
35 
36 #include "ftl_core.h"
37 #include "ftl_trace.h"
38 #include "ftl_io.h"
39 #include "ftl_band.h"
40 
41 #define OWNER_FTL	0x20
42 #define TRACE_GROUP_FTL	0x6
43 
44 enum ftl_trace_source {
45 	FTL_TRACE_SOURCE_INTERNAL,
46 	FTL_TRACE_SOURCE_USER,
47 	FTL_TRACE_SOURCE_MAX,
48 };
49 
50 #define FTL_TPOINT_ID(id, src) SPDK_TPOINT_ID(TRACE_GROUP_FTL, (((id) << 1) | (!!(src))))
51 
52 #define FTL_TRACE_BAND_DEFRAG(src)		FTL_TPOINT_ID(0, src)
53 #define FTL_TRACE_BAND_WRITE(src)		FTL_TPOINT_ID(1, src)
54 #define FTL_TRACE_LIMITS(src)			FTL_TPOINT_ID(2, src)
55 #define FTL_TRACE_WBUF_POP(src)			FTL_TPOINT_ID(3, src)
56 
57 #define FTL_TRACE_READ_SCHEDULE(src)		FTL_TPOINT_ID(4, src)
58 #define FTL_TRACE_READ_SUBMISSION(src)		FTL_TPOINT_ID(5, src)
59 #define FTL_TRACE_READ_COMPLETION_INVALID(src)	FTL_TPOINT_ID(6, src)
60 #define FTL_TRACE_READ_COMPLETION_CACHE(src)	FTL_TPOINT_ID(7, src)
61 #define FTL_TRACE_READ_COMPLETION_DISK(src)	FTL_TPOINT_ID(8, src)
62 
63 #define FTL_TRACE_MD_READ_SCHEDULE(src)		FTL_TPOINT_ID(9,  src)
64 #define FTL_TRACE_MD_READ_SUBMISSION(src)	FTL_TPOINT_ID(10, src)
65 #define FTL_TRACE_MD_READ_COMPLETION(src)	FTL_TPOINT_ID(11, src)
66 
67 #define FTL_TRACE_WRITE_SCHEDULE(src)		FTL_TPOINT_ID(12, src)
68 #define FTL_TRACE_WRITE_WBUF_FILL(src)		FTL_TPOINT_ID(13, src)
69 #define FTL_TRACE_WRITE_SUBMISSION(src)		FTL_TPOINT_ID(14, src)
70 #define FTL_TRACE_WRITE_COMPLETION(src)		FTL_TPOINT_ID(15, src)
71 
72 #define FTL_TRACE_MD_WRITE_SCHEDULE(src)	FTL_TPOINT_ID(16, src)
73 #define FTL_TRACE_MD_WRITE_SUBMISSION(src)	FTL_TPOINT_ID(17, src)
74 #define FTL_TRACE_MD_WRITE_COMPLETION(src)	FTL_TPOINT_ID(18, src)
75 
76 #define FTL_TRACE_ERASE_SUBMISSION(src)		FTL_TPOINT_ID(19, src)
77 #define FTL_TRACE_ERASE_COMPLETION(src)		FTL_TPOINT_ID(20, src)
78 
79 SPDK_TRACE_REGISTER_FN(ftl_trace_func, "ftl", TRACE_GROUP_FTL)
80 {
81 	const char source[] = { 'i', 'u' };
82 	char descbuf[128];
83 	int i;
84 
85 	spdk_trace_register_owner(OWNER_FTL, 'f');
86 
87 	for (i = 0; i < FTL_TRACE_SOURCE_MAX; ++i) {
88 		snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "band_defrag");
89 		spdk_trace_register_description(descbuf, FTL_TRACE_BAND_DEFRAG(i),
90 						OWNER_FTL, OBJECT_NONE, 0, 0, "band: ");
91 		snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "band_write");
92 		spdk_trace_register_description(descbuf, FTL_TRACE_BAND_WRITE(i),
93 						OWNER_FTL, OBJECT_NONE, 0, 0, "band: ");
94 		snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "limits");
95 		spdk_trace_register_description(descbuf, FTL_TRACE_LIMITS(i),
96 						OWNER_FTL, OBJECT_NONE, 0, 0, "limits: ");
97 		snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "rwb_pop");
98 		spdk_trace_register_description(descbuf, FTL_TRACE_WBUF_POP(i),
99 						OWNER_FTL, OBJECT_NONE, 0, 0, "lba: ");
100 
101 		snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "md_read_sched");
102 		spdk_trace_register_description(descbuf, FTL_TRACE_MD_READ_SCHEDULE(i),
103 						OWNER_FTL, OBJECT_NONE, 0, 0, "addr: ");
104 		snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "md_read_submit");
105 		spdk_trace_register_description(descbuf, FTL_TRACE_MD_READ_SUBMISSION(i),
106 						OWNER_FTL, OBJECT_NONE, 0, 0, "addr: ");
107 		snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "md_read_cmpl");
108 		spdk_trace_register_description(descbuf, FTL_TRACE_MD_READ_COMPLETION(i),
109 						OWNER_FTL, OBJECT_NONE, 0, 0, "lba: ");
110 
111 		snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "md_write_sched");
112 		spdk_trace_register_description(descbuf, FTL_TRACE_MD_WRITE_SCHEDULE(i),
113 						OWNER_FTL, OBJECT_NONE, 0, 0, "addr: ");
114 		snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "md_write_submit");
115 		spdk_trace_register_description(descbuf, FTL_TRACE_MD_WRITE_SUBMISSION(i),
116 						OWNER_FTL, OBJECT_NONE, 0, 0, "addr: ");
117 		snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "md_write_cmpl");
118 		spdk_trace_register_description(descbuf, FTL_TRACE_MD_WRITE_COMPLETION(i),
119 						OWNER_FTL, OBJECT_NONE, 0, 0, "lba: ");
120 
121 		snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "read_sched");
122 		spdk_trace_register_description(descbuf, FTL_TRACE_READ_SCHEDULE(i),
123 						OWNER_FTL, OBJECT_NONE, 0, 0, "lba: ");
124 		snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "read_submit");
125 		spdk_trace_register_description(descbuf, FTL_TRACE_READ_SUBMISSION(i),
126 						OWNER_FTL, OBJECT_NONE, 0, 0, "addr: ");
127 		snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "read_cmpl_invld");
128 		spdk_trace_register_description(descbuf, FTL_TRACE_READ_COMPLETION_INVALID(i),
129 						OWNER_FTL, OBJECT_NONE, 0, 0, "lba: ");
130 		snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "read_cmpl_cache");
131 		spdk_trace_register_description(descbuf, FTL_TRACE_READ_COMPLETION_CACHE(i),
132 						OWNER_FTL, OBJECT_NONE, 0, 0, "lba: ");
133 		snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "read_cmpl_ssd");
134 		spdk_trace_register_description(descbuf, FTL_TRACE_READ_COMPLETION_DISK(i),
135 						OWNER_FTL, OBJECT_NONE, 0, 0, "lba: ");
136 
137 		snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "write_sched");
138 		spdk_trace_register_description(descbuf, FTL_TRACE_WRITE_SCHEDULE(i),
139 						OWNER_FTL, OBJECT_NONE, 0, 0, "lba: ");
140 		snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "rwb_fill");
141 		spdk_trace_register_description(descbuf, FTL_TRACE_WRITE_WBUF_FILL(i),
142 						OWNER_FTL, OBJECT_NONE, 0, 0, "lba: ");
143 		snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "write_submit");
144 		spdk_trace_register_description(descbuf, FTL_TRACE_WRITE_SUBMISSION(i),
145 						OWNER_FTL, OBJECT_NONE, 0, 0, "addr: ");
146 		snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "write_cmpl");
147 		spdk_trace_register_description(descbuf, FTL_TRACE_WRITE_COMPLETION(i),
148 						OWNER_FTL, OBJECT_NONE, 0, 0, "lba: ");
149 
150 		snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "erase_submit");
151 		spdk_trace_register_description(descbuf, FTL_TRACE_ERASE_SUBMISSION(i),
152 						OWNER_FTL, OBJECT_NONE, 0, 0, "addr: ");
153 		snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "erase_cmpl");
154 		spdk_trace_register_description(descbuf, FTL_TRACE_ERASE_COMPLETION(i),
155 						OWNER_FTL, OBJECT_NONE, 0, 0, "addr: ");
156 	}
157 }
158 
159 static uint16_t
160 ftl_trace_io_source(const struct ftl_io *io)
161 {
162 	if (io->flags & FTL_IO_INTERNAL) {
163 		return FTL_TRACE_SOURCE_INTERNAL;
164 	} else {
165 		return FTL_TRACE_SOURCE_USER;
166 	}
167 }
168 
169 static uint64_t
170 ftl_trace_next_id(struct ftl_trace *trace)
171 {
172 	assert(trace->id != FTL_TRACE_INVALID_ID);
173 	return __atomic_fetch_add(&trace->id, 1, __ATOMIC_SEQ_CST);
174 }
175 
176 void
177 ftl_trace_defrag_band(struct spdk_ftl_dev *dev, const struct ftl_band *band)
178 {
179 	struct ftl_trace *trace = &dev->stats.trace;
180 
181 	spdk_trace_record(FTL_TRACE_BAND_DEFRAG(FTL_TRACE_SOURCE_INTERNAL),
182 			  ftl_trace_next_id(trace), 0, band->lba_map.num_vld, band->id);
183 }
184 
185 void
186 ftl_trace_write_band(struct spdk_ftl_dev *dev, const struct ftl_band *band)
187 {
188 	struct ftl_trace *trace = &dev->stats.trace;
189 
190 	spdk_trace_record(FTL_TRACE_BAND_WRITE(FTL_TRACE_SOURCE_INTERNAL),
191 			  ftl_trace_next_id(trace), 0, 0, band->id);
192 }
193 
194 void
195 ftl_trace_lba_io_init(struct spdk_ftl_dev *dev, const struct ftl_io *io)
196 {
197 	uint16_t tpoint_id = 0, source;
198 
199 	assert(io->trace != FTL_TRACE_INVALID_ID);
200 	source = ftl_trace_io_source(io);
201 
202 	if (io->flags & FTL_IO_MD) {
203 		switch (io->type) {
204 		case FTL_IO_READ:
205 			tpoint_id = FTL_TRACE_MD_READ_SCHEDULE(source);
206 			break;
207 		case FTL_IO_WRITE:
208 			tpoint_id = FTL_TRACE_MD_WRITE_SCHEDULE(source);
209 			break;
210 		default:
211 			assert(0);
212 		}
213 	} else {
214 		switch (io->type) {
215 		case FTL_IO_READ:
216 			tpoint_id = FTL_TRACE_READ_SCHEDULE(source);
217 			break;
218 		case FTL_IO_WRITE:
219 			tpoint_id = FTL_TRACE_WRITE_SCHEDULE(source);
220 			break;
221 		default:
222 			assert(0);
223 		}
224 	}
225 
226 	spdk_trace_record(tpoint_id, io->trace, io->num_blocks, 0, ftl_io_get_lba(io, 0));
227 }
228 
229 void
230 ftl_trace_wbuf_fill(struct spdk_ftl_dev *dev, const struct ftl_io *io)
231 {
232 	assert(io->trace != FTL_TRACE_INVALID_ID);
233 
234 	spdk_trace_record(FTL_TRACE_WRITE_WBUF_FILL(ftl_trace_io_source(io)), io->trace,
235 			  0, 0, ftl_io_current_lba(io));
236 }
237 
238 void
239 ftl_trace_wbuf_pop(struct spdk_ftl_dev *dev, const struct ftl_wbuf_entry *entry)
240 {
241 	uint16_t tpoint_id;
242 
243 	assert(entry->trace != FTL_TRACE_INVALID_ID);
244 
245 	if (entry->io_flags & FTL_IO_INTERNAL) {
246 		tpoint_id = FTL_TRACE_WBUF_POP(FTL_TRACE_SOURCE_INTERNAL);
247 	} else {
248 		tpoint_id = FTL_TRACE_WBUF_POP(FTL_TRACE_SOURCE_USER);
249 	}
250 
251 	spdk_trace_record(tpoint_id, entry->trace, 0, entry->addr.offset, entry->lba);
252 }
253 
254 void
255 ftl_trace_completion(struct spdk_ftl_dev *dev, const struct ftl_io *io,
256 		     enum ftl_trace_completion completion)
257 {
258 	uint16_t tpoint_id = 0, source;
259 
260 	assert(io->trace != FTL_TRACE_INVALID_ID);
261 	source = ftl_trace_io_source(io);
262 
263 	if (io->flags & FTL_IO_MD) {
264 		switch (io->type) {
265 		case FTL_IO_READ:
266 			tpoint_id = FTL_TRACE_MD_READ_COMPLETION(source);
267 			break;
268 		case FTL_IO_WRITE:
269 			tpoint_id = FTL_TRACE_MD_WRITE_COMPLETION(source);
270 			break;
271 		default:
272 			assert(0);
273 		}
274 	} else {
275 		switch (io->type) {
276 		case FTL_IO_READ:
277 			switch (completion) {
278 			case FTL_TRACE_COMPLETION_INVALID:
279 				tpoint_id = FTL_TRACE_READ_COMPLETION_INVALID(source);
280 				break;
281 			case FTL_TRACE_COMPLETION_CACHE:
282 				tpoint_id = FTL_TRACE_READ_COMPLETION_CACHE(source);
283 				break;
284 			case FTL_TRACE_COMPLETION_DISK:
285 				tpoint_id = FTL_TRACE_READ_COMPLETION_DISK(source);
286 				break;
287 			}
288 			break;
289 		case FTL_IO_WRITE:
290 			tpoint_id = FTL_TRACE_WRITE_COMPLETION(source);
291 			break;
292 		case FTL_IO_ERASE:
293 			tpoint_id = FTL_TRACE_ERASE_COMPLETION(source);
294 			break;
295 		default:
296 			assert(0);
297 		}
298 	}
299 
300 	spdk_trace_record(tpoint_id, io->trace, 0, 0, ftl_io_get_lba(io, io->pos - 1));
301 }
302 
303 void
304 ftl_trace_submission(struct spdk_ftl_dev *dev, const struct ftl_io *io, struct ftl_addr addr,
305 		     size_t addr_cnt)
306 {
307 	uint16_t tpoint_id = 0, source;
308 
309 	assert(io->trace != FTL_TRACE_INVALID_ID);
310 	source = ftl_trace_io_source(io);
311 
312 	if (io->flags & FTL_IO_MD) {
313 		switch (io->type) {
314 		case FTL_IO_READ:
315 			tpoint_id = FTL_TRACE_MD_READ_SUBMISSION(source);
316 			break;
317 		case FTL_IO_WRITE:
318 			tpoint_id = FTL_TRACE_MD_WRITE_SUBMISSION(source);
319 			break;
320 		default:
321 			assert(0);
322 		}
323 	} else {
324 		switch (io->type) {
325 		case FTL_IO_READ:
326 			tpoint_id = FTL_TRACE_READ_SUBMISSION(source);
327 			break;
328 		case FTL_IO_WRITE:
329 			tpoint_id = FTL_TRACE_WRITE_SUBMISSION(source);
330 			break;
331 		case FTL_IO_ERASE:
332 			tpoint_id = FTL_TRACE_ERASE_SUBMISSION(source);
333 			break;
334 		default:
335 			assert(0);
336 		}
337 	}
338 
339 	spdk_trace_record(tpoint_id, io->trace, addr_cnt, 0, addr.offset);
340 }
341 
342 void
343 ftl_trace_limits(struct spdk_ftl_dev *dev, int limit, size_t num_free)
344 {
345 	struct ftl_trace *trace = &dev->stats.trace;
346 
347 	spdk_trace_record(FTL_TRACE_LIMITS(FTL_TRACE_SOURCE_INTERNAL), ftl_trace_next_id(trace),
348 			  num_free, limit, 0);
349 }
350 
351 uint64_t
352 ftl_trace_alloc_id(struct spdk_ftl_dev *dev)
353 {
354 	struct ftl_trace *trace = &dev->stats.trace;
355 
356 	return ftl_trace_next_id(trace);
357 }
358