1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2022 Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "ftl_mngt.h" 7 #include "ftl_mngt_steps.h" 8 #include "ftl_internal.h" 9 #include "ftl_core.h" 10 #include "ftl_band.h" 11 12 struct ftl_validate_ctx { 13 struct { 14 struct ftl_bitmap *bitmap; 15 void *buffer; 16 uint64_t buffer_size; 17 uint64_t bit_count; 18 uint64_t base_valid_count; 19 uint64_t cache_valid_count; 20 } valid_map; 21 22 int status; 23 }; 24 25 static void 26 ftl_mngt_test_prepare(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 27 { 28 struct ftl_validate_ctx *cntx = ftl_mngt_get_process_ctx(mngt); 29 30 cntx->valid_map.bit_count = dev->layout.base.total_blocks + 31 dev->layout.nvc.total_blocks; 32 cntx->valid_map.buffer_size = spdk_divide_round_up(cntx->valid_map.bit_count, 8); 33 cntx->valid_map.buffer_size = SPDK_ALIGN_CEIL(cntx->valid_map.buffer_size, 34 ftl_bitmap_buffer_alignment); 35 36 cntx->valid_map.buffer = calloc(cntx->valid_map.buffer_size, 1); 37 if (!cntx->valid_map.buffer) { 38 ftl_mngt_fail_step(mngt); 39 return; 40 } 41 42 cntx->valid_map.bitmap = ftl_bitmap_create(cntx->valid_map.buffer, 43 cntx->valid_map.buffer_size); 44 if (!cntx->valid_map.bitmap) { 45 ftl_mngt_fail_step(mngt); 46 return; 47 } 48 49 ftl_mngt_next_step(mngt); 50 } 51 52 static void 53 ftl_mngt_test_cleanup(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 54 { 55 struct ftl_validate_ctx *cntx = ftl_mngt_get_process_ctx(mngt); 56 57 ftl_bitmap_destroy(cntx->valid_map.bitmap); 58 cntx->valid_map.bitmap = NULL; 59 60 free(cntx->valid_map.buffer); 61 cntx->valid_map.buffer = NULL; 62 63 ftl_mngt_next_step(mngt); 64 } 65 66 static void 67 test_valid_map_pin_cb(struct spdk_ftl_dev *dev, int status, 68 struct ftl_l2p_pin_ctx *pin_ctx) 69 { 70 struct ftl_mngt_process *mngt = pin_ctx->cb_ctx; 71 struct ftl_validate_ctx *ctx = ftl_mngt_get_process_ctx(mngt); 72 uint64_t lba, end; 73 74 if (status) { 75 FTL_ERRLOG(dev, "L2P pin ERROR when testing valid map\n"); 76 ftl_mngt_fail_step(mngt); 77 return; 78 } 79 80 lba = pin_ctx->lba; 81 end = pin_ctx->lba + pin_ctx->count; 82 83 for (; lba < end; ++lba) { 84 ftl_addr addr = ftl_l2p_get(dev, lba); 85 bool valid; 86 87 if (FTL_ADDR_INVALID == addr) { 88 continue; 89 } 90 91 if (ftl_bitmap_get(ctx->valid_map.bitmap, addr)) { 92 status = -EINVAL; 93 FTL_ERRLOG(dev, "L2P mapping ERROR, double reference, " 94 "address 0x%.16"PRIX64"\n", addr); 95 break; 96 } else { 97 ftl_bitmap_set(ctx->valid_map.bitmap, addr); 98 } 99 100 if (ftl_addr_in_nvc(dev, addr)) { 101 ctx->valid_map.cache_valid_count++; 102 } else { 103 ctx->valid_map.base_valid_count++; 104 } 105 106 valid = ftl_bitmap_get(dev->valid_map, addr); 107 if (!valid) { 108 status = -EINVAL; 109 FTL_ERRLOG(dev, "L2P and valid map mismatch" 110 ", LBA 0x%.16"PRIX64 111 ", address 0x%.16"PRIX64" unset\n", 112 lba, addr); 113 break; 114 } 115 } 116 117 ftl_l2p_unpin(dev, pin_ctx->lba, pin_ctx->count); 118 pin_ctx->lba += pin_ctx->count; 119 120 if (!status) { 121 ftl_mngt_continue_step(mngt); 122 } else { 123 ftl_mngt_fail_step(mngt); 124 } 125 } 126 127 static void 128 ftl_mngt_test_valid_map(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 129 { 130 struct ftl_l2p_pin_ctx *pin_ctx; 131 struct ftl_validate_ctx *ctx = ftl_mngt_get_process_ctx(mngt); 132 uint64_t left; 133 134 pin_ctx = ftl_mngt_get_step_ctx(mngt); 135 if (!pin_ctx) { 136 if (ftl_mngt_alloc_step_ctx(mngt, sizeof(*pin_ctx))) { 137 ftl_mngt_fail_step(mngt); 138 return; 139 } 140 pin_ctx = ftl_mngt_get_step_ctx(mngt); 141 assert(pin_ctx); 142 143 pin_ctx->lba = 0; 144 memset(ctx->valid_map.buffer, 0, ctx->valid_map.buffer_size); 145 } 146 147 left = dev->num_lbas - pin_ctx->lba; 148 pin_ctx->count = spdk_min(left, 4096); 149 150 if (pin_ctx->count) { 151 ftl_l2p_pin(dev, pin_ctx->lba, pin_ctx->count, 152 test_valid_map_pin_cb, mngt, pin_ctx); 153 } else { 154 if (!ctx->status) { 155 uint64_t valid = ctx->valid_map.base_valid_count + 156 ctx->valid_map.cache_valid_count; 157 158 if (ftl_bitmap_count_set(dev->valid_map) != valid) { 159 ctx->status = -EINVAL; 160 } 161 } 162 163 /* All done */ 164 if (ctx->status) { 165 ftl_mngt_fail_step(mngt); 166 } else { 167 ftl_mngt_next_step(mngt); 168 } 169 } 170 } 171 172 /* 173 * Verifies the contents of L2P versus valid map. Makes sure any physical addresses in the L2P 174 * have their corresponding valid bits set and that two different logical addresses don't point 175 * to the same physical address. 176 * 177 * For debugging purposes only, directed via environment variable - whole L2P needs to be loaded in 178 * and checked. 179 */ 180 static const struct ftl_mngt_process_desc desc_self_test = { 181 .name = "[Test] Startup Test", 182 .ctx_size = sizeof(struct ftl_validate_ctx), 183 .steps = { 184 { 185 .name = "[TEST] Initialize selftest", 186 187 .action = ftl_mngt_test_prepare, 188 .cleanup = ftl_mngt_test_cleanup 189 }, 190 { 191 .name = "[TEST] Validate map and L2P consistency", 192 .action = ftl_mngt_test_valid_map 193 }, 194 { 195 .name = "[TEST] Deinitialize cleanup", 196 .action = ftl_mngt_test_cleanup 197 }, 198 {} 199 } 200 }; 201 202 void 203 ftl_mngt_self_test(struct spdk_ftl_dev *dev, struct ftl_mngt_process *mngt) 204 { 205 if (getenv("FTL_SELF_TEST")) { 206 ftl_mngt_call_process(mngt, &desc_self_test); 207 } else { 208 FTL_NOTICELOG(dev, "Self test skipped\n"); 209 ftl_mngt_next_step(mngt); 210 } 211 } 212