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