xref: /spdk/lib/ftl/mngt/ftl_mngt_self_test.c (revision 784b9d48746955f210926648a0131f84f58de76f)
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