1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2018 Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/ftl.h" 7 #include "ftl_debug.h" 8 #include "ftl_band.h" 9 10 /* TODO: Switch to INFOLOG instead, we can control the printing via spdk_log_get_flag */ 11 #if defined(DEBUG) 12 13 static const char *ftl_band_state_str[] = { 14 "free", 15 "prep", 16 "opening", 17 "open", 18 "full", 19 "closing", 20 "closed", 21 "max" 22 }; 23 24 struct ftl_band_validate_ctx { 25 struct ftl_band *band; 26 ftl_band_validate_md_cb cb; 27 int remaining; 28 uint64_t pin_cnt; 29 uint64_t current_offset; 30 struct ftl_l2p_pin_ctx l2p_pin_ctx[]; 31 }; 32 33 static void ftl_band_validate_md_l2p_pin_cb(struct spdk_ftl_dev *dev, int status, 34 struct ftl_l2p_pin_ctx *pin_ctx); 35 36 #define FTL_MD_VALIDATE_LBA_PER_ITERATION 128 37 38 static void 39 ftl_band_validate_md_pin(struct ftl_band_validate_ctx *ctx) 40 { 41 struct ftl_band *band = ctx->band; 42 struct spdk_ftl_dev *dev = band->dev; 43 struct ftl_p2l_map *p2l_map = &band->p2l_map; 44 size_t i, size; 45 struct ftl_l2p_pin_ctx tmp_pin_ctx = { 46 .cb_ctx = ctx 47 }; 48 49 /* Since the first L2P page may already be pinned, the ftl_band_validate_md_l2p_pin_cb could be prematurely 50 * triggered. Initializing to 1 and then triggering the callback again manually prevents the issue. 51 */ 52 ctx->remaining = 1; 53 size = spdk_min(FTL_MD_VALIDATE_LBA_PER_ITERATION, 54 ftl_get_num_blocks_in_band(dev) - ctx->current_offset); 55 56 for (i = ctx->current_offset; i < ctx->current_offset + size; ++i) { 57 if (!ftl_bitmap_get(p2l_map->valid, i)) { 58 ctx->l2p_pin_ctx[i].lba = FTL_LBA_INVALID; 59 continue; 60 } 61 62 assert(p2l_map->band_map[i].lba != FTL_LBA_INVALID); 63 ctx->remaining++; 64 ctx->pin_cnt++; 65 ftl_l2p_pin(dev, p2l_map->band_map[i].lba, 1, ftl_band_validate_md_l2p_pin_cb, ctx, 66 &ctx->l2p_pin_ctx[i]); 67 } 68 69 ftl_band_validate_md_l2p_pin_cb(dev, 0, &tmp_pin_ctx); 70 } 71 72 static void 73 _ftl_band_validate_md(void *_ctx) 74 { 75 struct ftl_band_validate_ctx *ctx = _ctx; 76 struct ftl_band *band = ctx->band; 77 struct spdk_ftl_dev *dev = band->dev; 78 ftl_addr addr_l2p; 79 size_t i, size; 80 bool valid = true; 81 uint64_t lba; 82 83 size = spdk_min(FTL_MD_VALIDATE_LBA_PER_ITERATION, 84 ftl_get_num_blocks_in_band(dev) - ctx->current_offset); 85 86 for (i = ctx->current_offset; i < ctx->current_offset + size; ++i) { 87 lba = ctx->l2p_pin_ctx[i].lba; 88 if (lba == FTL_LBA_INVALID) { 89 continue; 90 } 91 92 if (ftl_bitmap_get(band->p2l_map.valid, i)) { 93 addr_l2p = ftl_l2p_get(dev, lba); 94 95 if (addr_l2p != FTL_ADDR_INVALID && !ftl_addr_in_nvc(dev, addr_l2p) && 96 addr_l2p != ftl_band_addr_from_block_offset(band, i)) { 97 valid = false; 98 } 99 } 100 101 ctx->pin_cnt--; 102 ftl_l2p_unpin(dev, lba, 1); 103 } 104 assert(ctx->pin_cnt == 0); 105 106 ctx->current_offset += size; 107 108 if (ctx->current_offset == ftl_get_num_blocks_in_band(dev)) { 109 ctx->cb(band, valid); 110 free(ctx); 111 return; 112 } 113 114 ftl_band_validate_md_pin(ctx); 115 } 116 117 static void 118 ftl_band_validate_md_l2p_pin_cb(struct spdk_ftl_dev *dev, int status, 119 struct ftl_l2p_pin_ctx *pin_ctx) 120 { 121 struct ftl_band_validate_ctx *ctx = pin_ctx->cb_ctx; 122 123 assert(status == 0); 124 125 if (--ctx->remaining == 0) { 126 spdk_thread_send_msg(dev->core_thread, _ftl_band_validate_md, ctx); 127 } 128 } 129 130 void 131 ftl_band_validate_md(struct ftl_band *band, ftl_band_validate_md_cb cb) 132 { 133 struct ftl_band_validate_ctx *ctx; 134 size_t size; 135 136 assert(cb); 137 138 size = ftl_get_num_blocks_in_band(band->dev); 139 140 ctx = malloc(sizeof(*ctx) + size * sizeof(*ctx->l2p_pin_ctx)); 141 142 if (!ctx) { 143 FTL_ERRLOG(band->dev, "Failed to allocate memory for band validate context"); 144 cb(band, false); 145 return; 146 } 147 148 ctx->band = band; 149 ctx->cb = cb; 150 ctx->pin_cnt = 0; 151 ctx->current_offset = 0; 152 153 ftl_band_validate_md_pin(ctx); 154 } 155 156 void 157 ftl_dev_dump_bands(struct spdk_ftl_dev *dev) 158 { 159 uint64_t i; 160 161 if (!dev->bands) { 162 return; 163 } 164 165 FTL_NOTICELOG(dev, "Bands validity:\n"); 166 for (i = 0; i < ftl_get_num_bands(dev); ++i) { 167 FTL_NOTICELOG(dev, " Band %3zu: %8zu / %zu \twr_cnt: %"PRIu64 168 "\tstate: %s\n", 169 i + 1, dev->bands[i].p2l_map.num_valid, 170 ftl_band_user_blocks(&dev->bands[i]), 171 dev->bands[i].md->wr_cnt, 172 ftl_band_state_str[dev->bands[i].md->state]); 173 } 174 } 175 176 #endif /* defined(DEBUG) */ 177 178 void 179 ftl_dev_dump_stats(const struct spdk_ftl_dev *dev) 180 { 181 uint64_t i, total = 0; 182 char uuid[SPDK_UUID_STRING_LEN]; 183 double waf; 184 uint64_t write_user, write_total; 185 const char *limits[] = { 186 [SPDK_FTL_LIMIT_CRIT] = "crit", 187 [SPDK_FTL_LIMIT_HIGH] = "high", 188 [SPDK_FTL_LIMIT_LOW] = "low", 189 [SPDK_FTL_LIMIT_START] = "start" 190 }; 191 192 (void)limits; 193 194 if (!dev->bands) { 195 return; 196 } 197 198 /* Count the number of valid LBAs */ 199 for (i = 0; i < ftl_get_num_bands(dev); ++i) { 200 total += dev->bands[i].p2l_map.num_valid; 201 } 202 203 write_user = dev->stats.entries[FTL_STATS_TYPE_CMP].write.blocks; 204 write_total = write_user + 205 dev->stats.entries[FTL_STATS_TYPE_GC].write.blocks + 206 dev->stats.entries[FTL_STATS_TYPE_MD_BASE].write.blocks; 207 208 waf = (double)write_total / (double)write_user; 209 210 spdk_uuid_fmt_lower(uuid, sizeof(uuid), &dev->conf.uuid); 211 FTL_NOTICELOG(dev, "\n"); 212 FTL_NOTICELOG(dev, "device UUID: %s\n", uuid); 213 FTL_NOTICELOG(dev, "total valid LBAs: %zu\n", total); 214 FTL_NOTICELOG(dev, "total writes: %"PRIu64"\n", write_total); 215 FTL_NOTICELOG(dev, "user writes: %"PRIu64"\n", write_user); 216 FTL_NOTICELOG(dev, "WAF: %.4lf\n", waf); 217 #ifdef DEBUG 218 FTL_NOTICELOG(dev, "limits:\n"); 219 for (i = 0; i < SPDK_FTL_LIMIT_MAX; ++i) { 220 FTL_NOTICELOG(dev, " %5s: %"PRIu64"\n", limits[i], dev->stats.limits[i]); 221 } 222 #endif 223 } 224