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