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