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 #include "spdk_internal/trace_defs.h" 42 43 #if defined(DEBUG) 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_WBUF_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_WBUF_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, 92 SPDK_TRACE_ARG_TYPE_INT, "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, 96 SPDK_TRACE_ARG_TYPE_INT, "band"); 97 snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "limits"); 98 spdk_trace_register_description(descbuf, FTL_TRACE_LIMITS(i), 99 OWNER_FTL, OBJECT_NONE, 0, 100 SPDK_TRACE_ARG_TYPE_INT, "limits"); 101 snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "rwb_pop"); 102 spdk_trace_register_description(descbuf, FTL_TRACE_WBUF_POP(i), 103 OWNER_FTL, OBJECT_NONE, 0, 104 SPDK_TRACE_ARG_TYPE_INT, "lba"); 105 106 snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "md_read_sched"); 107 spdk_trace_register_description(descbuf, FTL_TRACE_MD_READ_SCHEDULE(i), 108 OWNER_FTL, OBJECT_NONE, 0, 109 SPDK_TRACE_ARG_TYPE_INT, "addr"); 110 snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "md_read_submit"); 111 spdk_trace_register_description(descbuf, FTL_TRACE_MD_READ_SUBMISSION(i), 112 OWNER_FTL, OBJECT_NONE, 0, 113 SPDK_TRACE_ARG_TYPE_INT, "addr"); 114 snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "md_read_cmpl"); 115 spdk_trace_register_description(descbuf, FTL_TRACE_MD_READ_COMPLETION(i), 116 OWNER_FTL, OBJECT_NONE, 0, 117 SPDK_TRACE_ARG_TYPE_INT, "lba"); 118 119 snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "md_write_sched"); 120 spdk_trace_register_description(descbuf, FTL_TRACE_MD_WRITE_SCHEDULE(i), 121 OWNER_FTL, OBJECT_NONE, 0, 122 SPDK_TRACE_ARG_TYPE_INT, "addr"); 123 snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "md_write_submit"); 124 spdk_trace_register_description(descbuf, FTL_TRACE_MD_WRITE_SUBMISSION(i), 125 OWNER_FTL, OBJECT_NONE, 0, 126 SPDK_TRACE_ARG_TYPE_INT, "addr"); 127 snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "md_write_cmpl"); 128 spdk_trace_register_description(descbuf, FTL_TRACE_MD_WRITE_COMPLETION(i), 129 OWNER_FTL, OBJECT_NONE, 0, 130 SPDK_TRACE_ARG_TYPE_INT, "lba"); 131 132 snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "read_sched"); 133 spdk_trace_register_description(descbuf, FTL_TRACE_READ_SCHEDULE(i), 134 OWNER_FTL, OBJECT_NONE, 0, 135 SPDK_TRACE_ARG_TYPE_INT, "lba"); 136 snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "read_submit"); 137 spdk_trace_register_description(descbuf, FTL_TRACE_READ_SUBMISSION(i), 138 OWNER_FTL, OBJECT_NONE, 0, 139 SPDK_TRACE_ARG_TYPE_INT, "addr"); 140 snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "read_cmpl_invld"); 141 spdk_trace_register_description(descbuf, FTL_TRACE_READ_COMPLETION_INVALID(i), 142 OWNER_FTL, OBJECT_NONE, 0, 143 SPDK_TRACE_ARG_TYPE_INT, "lba"); 144 snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "read_cmpl_cache"); 145 spdk_trace_register_description(descbuf, FTL_TRACE_READ_COMPLETION_CACHE(i), 146 OWNER_FTL, OBJECT_NONE, 0, 147 SPDK_TRACE_ARG_TYPE_INT, "lba"); 148 snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "read_cmpl_ssd"); 149 spdk_trace_register_description(descbuf, FTL_TRACE_READ_COMPLETION_DISK(i), 150 OWNER_FTL, OBJECT_NONE, 0, 151 SPDK_TRACE_ARG_TYPE_INT, "lba"); 152 153 snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "write_sched"); 154 spdk_trace_register_description(descbuf, FTL_TRACE_WRITE_SCHEDULE(i), 155 OWNER_FTL, OBJECT_NONE, 0, 156 SPDK_TRACE_ARG_TYPE_INT, "lba"); 157 snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "rwb_fill"); 158 spdk_trace_register_description(descbuf, FTL_TRACE_WRITE_WBUF_FILL(i), 159 OWNER_FTL, OBJECT_NONE, 0, 160 SPDK_TRACE_ARG_TYPE_INT, "lba"); 161 snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "write_submit"); 162 spdk_trace_register_description(descbuf, FTL_TRACE_WRITE_SUBMISSION(i), 163 OWNER_FTL, OBJECT_NONE, 0, 164 SPDK_TRACE_ARG_TYPE_INT, "addr"); 165 snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "write_cmpl"); 166 spdk_trace_register_description(descbuf, FTL_TRACE_WRITE_COMPLETION(i), 167 OWNER_FTL, OBJECT_NONE, 0, 168 SPDK_TRACE_ARG_TYPE_INT, "lba"); 169 170 snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "erase_submit"); 171 spdk_trace_register_description(descbuf, FTL_TRACE_ERASE_SUBMISSION(i), 172 OWNER_FTL, OBJECT_NONE, 0, 173 SPDK_TRACE_ARG_TYPE_INT, "addr"); 174 snprintf(descbuf, sizeof(descbuf), "%c %s", source[i], "erase_cmpl"); 175 spdk_trace_register_description(descbuf, FTL_TRACE_ERASE_COMPLETION(i), 176 OWNER_FTL, OBJECT_NONE, 0, 177 SPDK_TRACE_ARG_TYPE_INT, "addr"); 178 } 179 } 180 181 static uint16_t 182 ftl_trace_io_source(const struct ftl_io *io) 183 { 184 if (io->flags & FTL_IO_INTERNAL) { 185 return FTL_TRACE_SOURCE_INTERNAL; 186 } else { 187 return FTL_TRACE_SOURCE_USER; 188 } 189 } 190 191 static uint64_t 192 ftl_trace_next_id(struct ftl_trace *trace) 193 { 194 assert(trace->id != FTL_TRACE_INVALID_ID); 195 return __atomic_fetch_add(&trace->id, 1, __ATOMIC_SEQ_CST); 196 } 197 198 void 199 ftl_trace_defrag_band(struct spdk_ftl_dev *dev, const struct ftl_band *band) 200 { 201 struct ftl_trace *trace = &dev->stats.trace; 202 203 spdk_trace_record(FTL_TRACE_BAND_DEFRAG(FTL_TRACE_SOURCE_INTERNAL), 204 ftl_trace_next_id(trace), 0, band->lba_map.num_vld, band->id); 205 } 206 207 void 208 ftl_trace_write_band(struct spdk_ftl_dev *dev, const struct ftl_band *band) 209 { 210 struct ftl_trace *trace = &dev->stats.trace; 211 212 spdk_trace_record(FTL_TRACE_BAND_WRITE(FTL_TRACE_SOURCE_INTERNAL), 213 ftl_trace_next_id(trace), 0, 0, band->id); 214 } 215 216 void 217 ftl_trace_lba_io_init(struct spdk_ftl_dev *dev, const struct ftl_io *io) 218 { 219 uint16_t tpoint_id = 0, source; 220 221 assert(io->trace != FTL_TRACE_INVALID_ID); 222 source = ftl_trace_io_source(io); 223 224 if (io->flags & FTL_IO_MD) { 225 switch (io->type) { 226 case FTL_IO_READ: 227 tpoint_id = FTL_TRACE_MD_READ_SCHEDULE(source); 228 break; 229 case FTL_IO_WRITE: 230 tpoint_id = FTL_TRACE_MD_WRITE_SCHEDULE(source); 231 break; 232 default: 233 assert(0); 234 } 235 } else { 236 switch (io->type) { 237 case FTL_IO_READ: 238 tpoint_id = FTL_TRACE_READ_SCHEDULE(source); 239 break; 240 case FTL_IO_WRITE: 241 tpoint_id = FTL_TRACE_WRITE_SCHEDULE(source); 242 break; 243 default: 244 assert(0); 245 } 246 } 247 248 spdk_trace_record(tpoint_id, io->trace, io->num_blocks, 0, ftl_io_get_lba(io, 0)); 249 } 250 251 void 252 ftl_trace_wbuf_fill(struct spdk_ftl_dev *dev, const struct ftl_io *io) 253 { 254 assert(io->trace != FTL_TRACE_INVALID_ID); 255 256 spdk_trace_record(FTL_TRACE_WRITE_WBUF_FILL(ftl_trace_io_source(io)), io->trace, 257 0, 0, ftl_io_current_lba(io)); 258 } 259 260 void 261 ftl_trace_wbuf_pop(struct spdk_ftl_dev *dev, const struct ftl_wbuf_entry *entry) 262 { 263 uint16_t tpoint_id; 264 265 assert(entry->trace != FTL_TRACE_INVALID_ID); 266 267 if (entry->io_flags & FTL_IO_INTERNAL) { 268 tpoint_id = FTL_TRACE_WBUF_POP(FTL_TRACE_SOURCE_INTERNAL); 269 } else { 270 tpoint_id = FTL_TRACE_WBUF_POP(FTL_TRACE_SOURCE_USER); 271 } 272 273 spdk_trace_record(tpoint_id, entry->trace, 0, entry->addr.offset, entry->lba); 274 } 275 276 void 277 ftl_trace_completion(struct spdk_ftl_dev *dev, const struct ftl_io *io, 278 enum ftl_trace_completion completion) 279 { 280 uint16_t tpoint_id = 0, source; 281 282 assert(io->trace != FTL_TRACE_INVALID_ID); 283 source = ftl_trace_io_source(io); 284 285 if (io->flags & FTL_IO_MD) { 286 switch (io->type) { 287 case FTL_IO_READ: 288 tpoint_id = FTL_TRACE_MD_READ_COMPLETION(source); 289 break; 290 case FTL_IO_WRITE: 291 tpoint_id = FTL_TRACE_MD_WRITE_COMPLETION(source); 292 break; 293 default: 294 assert(0); 295 } 296 } else { 297 switch (io->type) { 298 case FTL_IO_READ: 299 switch (completion) { 300 case FTL_TRACE_COMPLETION_INVALID: 301 tpoint_id = FTL_TRACE_READ_COMPLETION_INVALID(source); 302 break; 303 case FTL_TRACE_COMPLETION_CACHE: 304 tpoint_id = FTL_TRACE_READ_COMPLETION_CACHE(source); 305 break; 306 case FTL_TRACE_COMPLETION_DISK: 307 tpoint_id = FTL_TRACE_READ_COMPLETION_DISK(source); 308 break; 309 } 310 break; 311 case FTL_IO_WRITE: 312 tpoint_id = FTL_TRACE_WRITE_COMPLETION(source); 313 break; 314 case FTL_IO_ERASE: 315 tpoint_id = FTL_TRACE_ERASE_COMPLETION(source); 316 break; 317 default: 318 assert(0); 319 } 320 } 321 322 spdk_trace_record(tpoint_id, io->trace, 0, 0, ftl_io_get_lba(io, io->pos - 1)); 323 } 324 325 void 326 ftl_trace_submission(struct spdk_ftl_dev *dev, const struct ftl_io *io, struct ftl_addr addr, 327 size_t addr_cnt) 328 { 329 uint16_t tpoint_id = 0, source; 330 331 assert(io->trace != FTL_TRACE_INVALID_ID); 332 source = ftl_trace_io_source(io); 333 334 if (io->flags & FTL_IO_MD) { 335 switch (io->type) { 336 case FTL_IO_READ: 337 tpoint_id = FTL_TRACE_MD_READ_SUBMISSION(source); 338 break; 339 case FTL_IO_WRITE: 340 tpoint_id = FTL_TRACE_MD_WRITE_SUBMISSION(source); 341 break; 342 default: 343 assert(0); 344 } 345 } else { 346 switch (io->type) { 347 case FTL_IO_READ: 348 tpoint_id = FTL_TRACE_READ_SUBMISSION(source); 349 break; 350 case FTL_IO_WRITE: 351 tpoint_id = FTL_TRACE_WRITE_SUBMISSION(source); 352 break; 353 case FTL_IO_ERASE: 354 tpoint_id = FTL_TRACE_ERASE_SUBMISSION(source); 355 break; 356 default: 357 assert(0); 358 } 359 } 360 361 spdk_trace_record(tpoint_id, io->trace, addr_cnt, 0, addr.offset); 362 } 363 364 void 365 ftl_trace_limits(struct spdk_ftl_dev *dev, int limit, size_t num_free) 366 { 367 struct ftl_trace *trace = &dev->stats.trace; 368 369 spdk_trace_record(FTL_TRACE_LIMITS(FTL_TRACE_SOURCE_INTERNAL), ftl_trace_next_id(trace), 370 num_free, limit, 0); 371 } 372 373 uint64_t 374 ftl_trace_alloc_id(struct spdk_ftl_dev *dev) 375 { 376 struct ftl_trace *trace = &dev->stats.trace; 377 378 return ftl_trace_next_id(trace); 379 } 380 381 #endif /* defined(DEBUG) */ 382