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