xref: /spdk/test/unit/lib/bdev/raid/bdev_raid_sb.c/bdev_raid_sb_ut.c (revision cb768e815fd023ef05e77a71df7f0a7fb9557376)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2022 Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #include "spdk/stdinc.h"
7 #include "spdk_internal/cunit.h"
8 #include "spdk/env.h"
9 #include "spdk_internal/mock.h"
10 
11 #include "common/lib/test_env.c"
12 #include "bdev/raid/bdev_raid_sb.c"
13 
14 #define TEST_BUF_ALIGN	64
15 
16 DEFINE_STUB(spdk_bdev_queue_io_wait, int, (struct spdk_bdev *bdev, struct spdk_io_channel *ch,
17 		struct spdk_bdev_io_wait_entry *entry), 0);
18 DEFINE_STUB(spdk_bdev_get_name, const char *, (const struct spdk_bdev *bdev), "test_bdev");
19 DEFINE_STUB(spdk_bdev_get_buf_align, size_t, (const struct spdk_bdev *bdev), TEST_BUF_ALIGN);
20 
21 void *g_buf;
22 TAILQ_HEAD(, spdk_bdev_io) g_bdev_io_queue = TAILQ_HEAD_INITIALIZER(g_bdev_io_queue);
23 int g_read_counter;
24 int g_write_counter;
25 struct spdk_bdev g_bdev;
26 struct spdk_bdev_io g_bdev_io = {
27 	.bdev = &g_bdev,
28 };
29 
30 static int
_test_setup(uint32_t blocklen,uint32_t md_len)31 _test_setup(uint32_t blocklen, uint32_t md_len)
32 {
33 	g_bdev.blocklen = blocklen;
34 	g_bdev.md_len = md_len;
35 
36 	g_buf = spdk_dma_zmalloc(SPDK_ALIGN_CEIL(RAID_BDEV_SB_MAX_LENGTH,
37 				 spdk_bdev_get_data_block_size(&g_bdev)), TEST_BUF_ALIGN, NULL);
38 	if (!g_buf) {
39 		return -ENOMEM;
40 	}
41 
42 	return 0;
43 }
44 
45 static int
test_setup(void)46 test_setup(void)
47 {
48 	return _test_setup(512, 0);
49 }
50 
51 static int
test_setup_md(void)52 test_setup_md(void)
53 {
54 	return _test_setup(512, 8);
55 }
56 
57 static int
test_setup_md_interleaved(void)58 test_setup_md_interleaved(void)
59 {
60 	return _test_setup(512 + 8, 8);
61 }
62 
63 static int
test_cleanup(void)64 test_cleanup(void)
65 {
66 	spdk_dma_free(g_buf);
67 
68 	return 0;
69 }
70 
71 bool
spdk_bdev_is_md_interleaved(const struct spdk_bdev * bdev)72 spdk_bdev_is_md_interleaved(const struct spdk_bdev *bdev)
73 {
74 	return spdk_u32_is_pow2(bdev->blocklen) == false;
75 }
76 
77 uint32_t
spdk_bdev_get_data_block_size(const struct spdk_bdev * bdev)78 spdk_bdev_get_data_block_size(const struct spdk_bdev *bdev)
79 {
80 	return spdk_bdev_is_md_interleaved(bdev) ? bdev->blocklen - bdev->md_len : bdev->blocklen;
81 }
82 
83 struct spdk_bdev *
spdk_bdev_desc_get_bdev(struct spdk_bdev_desc * desc)84 spdk_bdev_desc_get_bdev(struct spdk_bdev_desc *desc)
85 {
86 	return &g_bdev;
87 }
88 
89 const struct spdk_uuid *
spdk_bdev_get_uuid(const struct spdk_bdev * bdev)90 spdk_bdev_get_uuid(const struct spdk_bdev *bdev)
91 {
92 	return &bdev->uuid;
93 }
94 
95 void
spdk_bdev_free_io(struct spdk_bdev_io * bdev_io)96 spdk_bdev_free_io(struct spdk_bdev_io *bdev_io)
97 {
98 	if (bdev_io != &g_bdev_io) {
99 		free(bdev_io);
100 	}
101 }
102 
103 int
spdk_bdev_read(struct spdk_bdev_desc * desc,struct spdk_io_channel * ch,void * buf,uint64_t offset,uint64_t nbytes,spdk_bdev_io_completion_cb cb,void * cb_arg)104 spdk_bdev_read(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
105 	       void *buf, uint64_t offset, uint64_t nbytes,
106 	       spdk_bdev_io_completion_cb cb, void *cb_arg)
107 {
108 	struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(desc);
109 	struct spdk_bdev_io *bdev_io = &g_bdev_io;
110 	uint64_t offset_blocks = offset / bdev->blocklen;
111 	uint32_t data_block_size = spdk_bdev_get_data_block_size(bdev);
112 	void *src = g_buf + offset_blocks * data_block_size;
113 
114 	g_read_counter++;
115 
116 	memset(buf, 0xab, nbytes);
117 
118 	while (nbytes > 0) {
119 		memcpy(buf, src, data_block_size);
120 		src += data_block_size;
121 		buf += bdev->blocklen;
122 		nbytes -= bdev->blocklen;
123 	}
124 
125 	cb(bdev_io, true, cb_arg);
126 	return 0;
127 }
128 
129 int
spdk_bdev_write(struct spdk_bdev_desc * desc,struct spdk_io_channel * ch,void * buf,uint64_t offset,uint64_t nbytes,spdk_bdev_io_completion_cb cb,void * cb_arg)130 spdk_bdev_write(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
131 		void *buf, uint64_t offset, uint64_t nbytes,
132 		spdk_bdev_io_completion_cb cb, void *cb_arg)
133 {
134 	struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(desc);
135 	struct raid_bdev_superblock *sb = buf;
136 	struct spdk_bdev_io *bdev_io;
137 	void *dest = g_buf;
138 	uint32_t data_block_size = spdk_bdev_get_data_block_size(bdev);
139 
140 	g_write_counter++;
141 	CU_ASSERT(offset == 0);
142 	CU_ASSERT(nbytes == spdk_divide_round_up(sb->length, data_block_size) * bdev->blocklen);
143 
144 	while (nbytes > 0) {
145 		memcpy(dest, buf, data_block_size);
146 		dest += data_block_size;
147 		buf += bdev->blocklen;
148 		nbytes -= bdev->blocklen;
149 	}
150 
151 	bdev_io = calloc(1, sizeof(*bdev_io));
152 	SPDK_CU_ASSERT_FATAL(bdev_io != NULL);
153 	bdev_io->internal.cb = cb;
154 	bdev_io->internal.caller_ctx = cb_arg;
155 	bdev_io->bdev = bdev;
156 
157 	TAILQ_INSERT_TAIL(&g_bdev_io_queue, bdev_io, internal.link);
158 
159 	return 0;
160 }
161 
162 static void
process_io_completions(void)163 process_io_completions(void)
164 {
165 	struct spdk_bdev_io *bdev_io;
166 
167 	while ((bdev_io = TAILQ_FIRST(&g_bdev_io_queue))) {
168 		TAILQ_REMOVE(&g_bdev_io_queue, bdev_io, internal.link);
169 
170 		bdev_io->internal.cb(bdev_io, true, bdev_io->internal.caller_ctx);
171 	}
172 }
173 
174 static void
prepare_sb(struct raid_bdev_superblock * sb)175 prepare_sb(struct raid_bdev_superblock *sb)
176 {
177 	/* prepare a simplest valid sb */
178 	memset(sb, 0, RAID_BDEV_SB_MAX_LENGTH);
179 	memcpy(sb->signature, RAID_BDEV_SB_SIG, sizeof(sb->signature));
180 	sb->version.major = RAID_BDEV_SB_VERSION_MAJOR;
181 	sb->version.minor = RAID_BDEV_SB_VERSION_MINOR;
182 	sb->length = sizeof(*sb);
183 	sb->crc = spdk_crc32c_update(sb, sb->length, 0);
184 }
185 
186 static void
write_sb_cb(int status,struct raid_bdev * raid_bdev,void * ctx)187 write_sb_cb(int status, struct raid_bdev *raid_bdev, void *ctx)
188 {
189 	int *status_out = ctx;
190 
191 	*status_out = status;
192 }
193 
194 static void
test_raid_bdev_write_superblock(void)195 test_raid_bdev_write_superblock(void)
196 {
197 	struct raid_base_bdev_info base_info[3] = {{0}};
198 	struct raid_bdev raid_bdev = {
199 		.num_base_bdevs = SPDK_COUNTOF(base_info),
200 		.base_bdev_info = base_info,
201 		.bdev = g_bdev,
202 	};
203 	int status;
204 	uint8_t i;
205 
206 	for (i = 0; i < SPDK_COUNTOF(base_info); i++) {
207 		base_info[i].raid_bdev = &raid_bdev;
208 		if (i > 0) {
209 			base_info[i].is_configured = true;
210 		}
211 	}
212 
213 	status = raid_bdev_alloc_superblock(&raid_bdev, spdk_bdev_get_data_block_size(&raid_bdev.bdev));
214 	CU_ASSERT(status == 0);
215 
216 	/* test initial sb write */
217 	raid_bdev_init_superblock(&raid_bdev);
218 
219 	status = INT_MAX;
220 	g_write_counter = 0;
221 	raid_bdev_write_superblock(&raid_bdev, write_sb_cb, &status);
222 	CU_ASSERT(g_write_counter == raid_bdev.num_base_bdevs - 1);
223 	CU_ASSERT(TAILQ_EMPTY(&g_bdev_io_queue) == false);
224 	process_io_completions();
225 	CU_ASSERT(status == 0);
226 	CU_ASSERT(memcmp(raid_bdev.sb, g_buf, raid_bdev.sb->length) == 0);
227 
228 	/* test max size sb write */
229 	raid_bdev.sb->length = RAID_BDEV_SB_MAX_LENGTH;
230 	if (spdk_bdev_is_md_interleaved(&raid_bdev.bdev)) {
231 		SPDK_CU_ASSERT_FATAL(raid_bdev.sb_io_buf != raid_bdev.sb);
232 		spdk_dma_free(raid_bdev.sb_io_buf);
233 	}
234 	raid_bdev.sb_io_buf = NULL;
235 
236 	status = INT_MAX;
237 	g_write_counter = 0;
238 	raid_bdev_write_superblock(&raid_bdev, write_sb_cb, &status);
239 	CU_ASSERT(g_write_counter == raid_bdev.num_base_bdevs - 1);
240 	CU_ASSERT(TAILQ_EMPTY(&g_bdev_io_queue) == false);
241 	process_io_completions();
242 	CU_ASSERT(status == 0);
243 	CU_ASSERT(memcmp(raid_bdev.sb, g_buf, raid_bdev.sb->length) == 0);
244 
245 	raid_bdev_free_superblock(&raid_bdev);
246 }
247 
248 static void
load_sb_cb(const struct raid_bdev_superblock * sb,int status,void * ctx)249 load_sb_cb(const struct raid_bdev_superblock *sb, int status, void *ctx)
250 {
251 	int *status_out = ctx;
252 
253 	if (status == 0) {
254 		CU_ASSERT(memcmp(sb, g_buf, sb->length) == 0);
255 	}
256 
257 	*status_out = status;
258 }
259 
260 static void
test_raid_bdev_load_base_bdev_superblock(void)261 test_raid_bdev_load_base_bdev_superblock(void)
262 {
263 	const uint32_t data_block_size = spdk_bdev_get_data_block_size(&g_bdev);
264 	struct raid_bdev_superblock *sb = g_buf;
265 	int rc;
266 	int status;
267 
268 	/* valid superblock */
269 	prepare_sb(sb);
270 
271 	g_read_counter = 0;
272 	status = INT_MAX;
273 	rc = raid_bdev_load_base_bdev_superblock(NULL, NULL, load_sb_cb, &status);
274 	CU_ASSERT(rc == 0);
275 	CU_ASSERT(status == 0);
276 	CU_ASSERT(g_read_counter == 1);
277 
278 	/* invalid signature */
279 	prepare_sb(sb);
280 	sb->signature[3] = 'Z';
281 	raid_bdev_sb_update_crc(sb);
282 
283 	g_read_counter = 0;
284 	status = INT_MAX;
285 	rc = raid_bdev_load_base_bdev_superblock(NULL, NULL, load_sb_cb, &status);
286 	CU_ASSERT(rc == 0);
287 	CU_ASSERT(status == -EINVAL);
288 	CU_ASSERT(g_read_counter == 1);
289 
290 	/* make the sb longer than 1 bdev block - expect 2 reads */
291 	prepare_sb(sb);
292 	sb->length = data_block_size * 3;
293 	memset(sb->base_bdevs, 0xef, sb->length - offsetof(struct raid_bdev_superblock, base_bdevs));
294 	raid_bdev_sb_update_crc(sb);
295 
296 	g_read_counter = 0;
297 	status = INT_MAX;
298 	rc = raid_bdev_load_base_bdev_superblock(NULL, NULL, load_sb_cb, &status);
299 	CU_ASSERT(rc == 0);
300 	CU_ASSERT(status == 0);
301 	CU_ASSERT(g_read_counter == 2);
302 
303 	/* corrupted sb contents, length > 1 bdev block - expect 2 reads */
304 	prepare_sb(sb);
305 	sb->length = data_block_size * 3;
306 	raid_bdev_sb_update_crc(sb);
307 	sb->reserved[0] = 0xff;
308 
309 	g_read_counter = 0;
310 	status = INT_MAX;
311 	rc = raid_bdev_load_base_bdev_superblock(NULL, NULL, load_sb_cb, &status);
312 	CU_ASSERT(rc == 0);
313 	CU_ASSERT(status == -EINVAL);
314 	CU_ASSERT(g_read_counter == 2);
315 
316 	/* invalid signature, length > 1 bdev block - expect 1 read */
317 	prepare_sb(sb);
318 	sb->signature[3] = 'Z';
319 	sb->length = data_block_size * 3;
320 	raid_bdev_sb_update_crc(sb);
321 
322 	g_read_counter = 0;
323 	status = INT_MAX;
324 	rc = raid_bdev_load_base_bdev_superblock(NULL, NULL, load_sb_cb, &status);
325 	CU_ASSERT(rc == 0);
326 	CU_ASSERT(status == -EINVAL);
327 	CU_ASSERT(g_read_counter == 1);
328 }
329 
330 static void
test_raid_bdev_parse_superblock(void)331 test_raid_bdev_parse_superblock(void)
332 {
333 	struct raid_bdev_superblock *sb = g_buf;
334 	struct raid_bdev_read_sb_ctx ctx = {
335 		.buf = g_buf,
336 		.buf_size = g_bdev.blocklen,
337 	};
338 
339 	/* valid superblock */
340 	prepare_sb(sb);
341 	CU_ASSERT(raid_bdev_parse_superblock(&ctx) == 0);
342 
343 	/* invalid signature */
344 	prepare_sb(sb);
345 	sb->signature[3] = 'Z';
346 	raid_bdev_sb_update_crc(sb);
347 	CU_ASSERT(raid_bdev_parse_superblock(&ctx) == -EINVAL);
348 
349 	/* invalid crc */
350 	prepare_sb(sb);
351 	sb->crc = 0xdeadbeef;
352 	CU_ASSERT(raid_bdev_parse_superblock(&ctx) == -EINVAL);
353 
354 	/* corrupted sb contents */
355 	prepare_sb(sb);
356 	sb->reserved[0] = 0xff;
357 	CU_ASSERT(raid_bdev_parse_superblock(&ctx) == -EINVAL);
358 
359 	/* invalid major version */
360 	prepare_sb(sb);
361 	sb->version.major = 9999;
362 	raid_bdev_sb_update_crc(sb);
363 	CU_ASSERT(raid_bdev_parse_superblock(&ctx) == -EINVAL);
364 
365 	/* sb longer than 1 bdev block */
366 	prepare_sb(sb);
367 	sb->length = spdk_bdev_get_data_block_size(&g_bdev) * 3;
368 	raid_bdev_sb_update_crc(sb);
369 	CU_ASSERT(raid_bdev_parse_superblock(&ctx) == -EAGAIN);
370 	ctx.buf_size = g_bdev.blocklen * 3;
371 	CU_ASSERT(raid_bdev_parse_superblock(&ctx) == 0);
372 
373 	/* invalid base bdev slot number */
374 	prepare_sb(sb);
375 	sb->base_bdevs[0].slot = sb->num_base_bdevs = sb->base_bdevs_size = 2;
376 	raid_bdev_sb_update_crc(sb);
377 	CU_ASSERT(raid_bdev_parse_superblock(&ctx) == -EINVAL);
378 }
379 
380 int
main(int argc,char ** argv)381 main(int argc, char **argv)
382 {
383 	unsigned int num_failures;
384 	CU_TestInfo tests[] = {
385 		{ "test_raid_bdev_write_superblock", test_raid_bdev_write_superblock },
386 		{ "test_raid_bdev_load_base_bdev_superblock", test_raid_bdev_load_base_bdev_superblock },
387 		{ "test_raid_bdev_parse_superblock", test_raid_bdev_parse_superblock },
388 		CU_TEST_INFO_NULL,
389 	};
390 	CU_SuiteInfo suites[] = {
391 		{ "raid_sb", test_setup, test_cleanup, NULL, NULL, tests },
392 		{ "raid_sb_md", test_setup_md, test_cleanup, NULL, NULL, tests },
393 		{ "raid_sb_md_interleaved", test_setup_md_interleaved, test_cleanup, NULL, NULL, tests },
394 		CU_SUITE_INFO_NULL,
395 	};
396 
397 	CU_initialize_registry();
398 	CU_register_suites(suites);
399 	num_failures = spdk_ut_run_tests(argc, argv, NULL);
400 	CU_cleanup_registry();
401 	return num_failures;
402 }
403