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