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 OBJECT_FTL_IO 0x50 43 #define OBJECT_RWB_IO 0x51 44 45 #define TRACE_GROUP_FTL 0x6 46 47 #define FTL_TPOINT_ID(type, source, tpoint) SPDK_TPOINT_ID(TRACE_GROUP_FTL, ((source * 16) + (type * 8) + tpoint)) 48 49 #define FTL_TRACE_TYPE_BAND_DEFRAG FTL_TPOINT_ID(FTL_TRACE_TYPE_OTHER, FTL_TRACE_SOURCE_INTERNAL, 0x0) 50 #define FTL_TRACE_TYPE_BAND_WRITE FTL_TPOINT_ID(FTL_TRACE_TYPE_OTHER, FTL_TRACE_SOURCE_INTERNAL, 0x1) 51 #define FTL_TRACE_TYPE_APPLIED_LIMITS FTL_TPOINT_ID(FTL_TRACE_TYPE_OTHER, FTL_TRACE_SOURCE_INTERNAL, 0x2) 52 #define FTL_TRACE_POINT_RWB_POP FTL_TPOINT_ID(FTL_TRACE_TYPE_OTHER, FTL_TRACE_SOURCE_INTERNAL, 0x3) 53 54 SPDK_TRACE_REGISTER_FN(ftl_trace_func, "ftl", TRACE_GROUP_FTL) 55 { 56 enum ftl_trace_type type; 57 enum ftl_trace_source source; 58 59 spdk_trace_register_owner(FTL_TRACE_SOURCE_INTERNAL, 'i'); 60 spdk_trace_register_owner(FTL_TRACE_SOURCE_USER, 'u'); 61 spdk_trace_register_object(OBJECT_FTL_IO, 'f'); 62 63 spdk_trace_register_description("FTL_TRACE_TYPE_BAND_DEFRAG", "", FTL_TRACE_TYPE_BAND_DEFRAG, 64 FTL_TRACE_SOURCE_INTERNAL, OBJECT_FTL_IO, 0, 0, "band: "); 65 spdk_trace_register_description("FTL_TRACE_TYPE_BAND_WRITE", "", FTL_TRACE_TYPE_BAND_WRITE, 66 FTL_TRACE_SOURCE_INTERNAL, OBJECT_FTL_IO, 0, 0, "band: "); 67 spdk_trace_register_description("FTL_TRACE_TYPE_APPLIED_LIMITS", "", FTL_TRACE_TYPE_APPLIED_LIMITS, 68 FTL_TRACE_SOURCE_INTERNAL, OBJECT_FTL_IO, 0, 0, "limits: "); 69 spdk_trace_register_description("FTL_TRACE_POINT_RWB_POP", "", FTL_TRACE_POINT_RWB_POP, 70 FTL_TRACE_SOURCE_INTERNAL, OBJECT_RWB_IO, 0, 0, "lba: "); 71 72 for (source = FTL_TRACE_SOURCE_INTERNAL; source <= FTL_TRACE_SOURCE_INTERNAL; source++) { 73 for (type = FTL_TRACE_TYPE_READ; type < FTL_TRACE_TYPE_OTHER; type++) { 74 /* TODO: Figure out better way to describe each of the traces */ 75 spdk_trace_register_description("FTL_TRACE_POINT_SCHEDULED", "", 76 FTL_TPOINT_ID(type, source, FTL_TRACE_POINT_SCHEDULED), 77 source, OBJECT_FTL_IO, 0, 0, "lba: "); 78 spdk_trace_register_description("FTL_TRACE_POINT_RWB_FILL", "", 79 FTL_TPOINT_ID(type, source, FTL_TRACE_POINT_RWB_FILL), 80 source, OBJECT_FTL_IO, 0, 0, "lba: "); 81 spdk_trace_register_description("FTL_TRACE_POINT_SUBMISSION", "", 82 FTL_TPOINT_ID(type, source, FTL_TRACE_POINT_SUBMISSION), 83 source, OBJECT_FTL_IO, 0, 0, "ppa: "); 84 spdk_trace_register_description("FTL_TRACE_COMPLETION_INVALID", "", 85 FTL_TPOINT_ID(type, source, FTL_TRACE_COMPLETION_INVALID), 86 source, OBJECT_FTL_IO, 0, 0, "lba: "); 87 spdk_trace_register_description("FTL_TRACE_COMPLETION_CACHE", "", 88 FTL_TPOINT_ID(type, source, FTL_TRACE_COMPLETION_CACHE), 89 source, OBJECT_FTL_IO, 0, 0, "lba: "); 90 spdk_trace_register_description("FTL_TRACE_COMPLETION_DISK", "", 91 FTL_TPOINT_ID(type, source, FTL_TRACE_COMPLETION_DISK), 92 source, OBJECT_FTL_IO, 0, 0, "lba: "); 93 } 94 } 95 } 96 97 static uint64_t 98 ftl_trace_next_id(struct ftl_trace *trace) 99 { 100 assert(trace->id != FTL_TRACE_INVALID_ID); 101 return __atomic_fetch_add(&trace->id, 1, __ATOMIC_SEQ_CST); 102 } 103 104 static uint8_t 105 ftl_io2trace_source(const struct ftl_io *io) 106 { 107 if (io->flags & FTL_IO_INTERNAL) { 108 return FTL_TRACE_SOURCE_INTERNAL; 109 } else { 110 return FTL_TRACE_SOURCE_USER; 111 } 112 } 113 114 static uint64_t 115 ftl_io2trace_type(const struct ftl_io *io, enum ftl_trace_point point) 116 { 117 uint8_t md_type = 0; 118 static const enum ftl_trace_type type[][2] = { 119 [FTL_IO_READ][0] = FTL_TRACE_TYPE_READ, 120 [FTL_IO_READ][1] = FTL_TRACE_TYPE_MD_READ, 121 [FTL_IO_WRITE][0] = FTL_TRACE_TYPE_WRITE, 122 [FTL_IO_WRITE][1] = FTL_TRACE_TYPE_MD_WRITE, 123 [FTL_IO_ERASE][0] = FTL_TRACE_TYPE_ERASE, 124 [FTL_IO_ERASE][1] = FTL_TRACE_TYPE_ERASE, 125 }; 126 127 if (io->flags & FTL_IO_MD) { 128 md_type = 1; 129 } 130 131 return FTL_TPOINT_ID(type[io->type][md_type], ftl_io2trace_source(io), point); 132 } 133 134 void 135 ftl_trace_defrag_band(struct spdk_ftl_dev *dev, const struct ftl_band *band) 136 { 137 struct ftl_trace *trace = &dev->stats.trace; 138 139 spdk_trace_record(FTL_TRACE_TYPE_BAND_DEFRAG, ftl_trace_next_id(trace), 0, band->id, 140 band->md.num_vld); 141 } 142 143 void 144 ftl_trace_write_band(struct spdk_ftl_dev *dev, const struct ftl_band *band) 145 { 146 struct ftl_trace *trace = &dev->stats.trace; 147 148 spdk_trace_record(FTL_TRACE_TYPE_BAND_WRITE, ftl_trace_next_id(trace), 0, band->id, 0); 149 } 150 151 void 152 ftl_trace_lba_io_init(struct spdk_ftl_dev *dev, const struct ftl_io *io) 153 { 154 uint64_t type; 155 156 assert(io->trace != FTL_TRACE_INVALID_ID); 157 type = ftl_io2trace_type(io, FTL_TRACE_POINT_SCHEDULED); 158 159 spdk_trace_record(type, io->trace, io->lbk_cnt, io->lba, 0); 160 } 161 162 void 163 ftl_trace_rwb_fill(struct spdk_ftl_dev *dev, const struct ftl_io *io) 164 { 165 uint64_t type; 166 167 assert(io->trace != FTL_TRACE_INVALID_ID); 168 type = ftl_io2trace_type(io, FTL_TRACE_POINT_RWB_FILL); 169 170 spdk_trace_record(type, io->trace, 0, io->lba, 0); 171 } 172 173 void ftl_trace_rwb_pop(struct spdk_ftl_dev *dev, const struct ftl_rwb_entry *entry) 174 { 175 assert(entry->trace != FTL_TRACE_INVALID_ID); 176 177 spdk_trace_record(FTL_TRACE_POINT_RWB_POP, entry->trace, 0, 178 entry->lba, (uint64_t)entry->ppa.ppa); 179 } 180 181 void 182 ftl_trace_completion(struct spdk_ftl_dev *dev, const struct ftl_io *io, 183 enum ftl_trace_completion completion) 184 { 185 uint64_t type; 186 187 assert(io->trace != FTL_TRACE_INVALID_ID); 188 type = ftl_io2trace_type(io, (enum ftl_trace_point)completion); 189 190 spdk_trace_record(type, io->trace, 0, io->lba, 0); 191 } 192 193 void 194 ftl_trace_submission(struct spdk_ftl_dev *dev, const struct ftl_io *io, struct ftl_ppa ppa, 195 size_t ppa_cnt) 196 { 197 uint64_t type; 198 199 assert(io->trace != FTL_TRACE_INVALID_ID); 200 type = ftl_io2trace_type(io, FTL_TRACE_POINT_SUBMISSION); 201 202 spdk_trace_record(type, io->trace, ppa_cnt, ppa.ppa, 0); 203 } 204 205 void 206 ftl_trace_limits(struct spdk_ftl_dev *dev, const size_t *limits, size_t num_free) 207 { 208 struct ftl_trace *trace = &dev->stats.trace; 209 210 spdk_trace_record(FTL_TRACE_TYPE_APPLIED_LIMITS, ftl_trace_next_id(trace), num_free, 211 limits[FTL_RWB_TYPE_USER], limits[FTL_RWB_TYPE_INTERNAL]); 212 } 213 214 uint64_t 215 ftl_trace_alloc_id(struct spdk_ftl_dev *dev) 216 { 217 struct ftl_trace *trace = &dev->stats.trace; 218 219 return ftl_trace_next_id(trace); 220 } 221