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