xref: /spdk/test/unit/lib/bdev/bdev_zone.c/bdev_zone_ut.c (revision ea941caeaf896fdf2aef7685f86f37023060faed)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2019 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 "bdev/bdev_zone.c"
12 
13 DEFINE_STUB_V(bdev_io_init, (struct spdk_bdev_io *bdev_io,
14 			     struct spdk_bdev *bdev, void *cb_arg,
15 			     spdk_bdev_io_completion_cb cb));
16 
17 DEFINE_STUB_V(bdev_io_submit, (struct spdk_bdev_io *bdev_io));
18 
19 /* Construct zone_io_operation structure */
20 struct zone_io_operation {
21 	struct spdk_bdev_desc *desc;
22 	struct spdk_io_channel *ch;
23 	struct iovec iov;
24 	union {
25 		struct {
26 			uint64_t zone_id;
27 			size_t num_zones;
28 			enum spdk_bdev_zone_action zone_action;
29 			void *buf;
30 			struct spdk_bdev_zone_info *info_;
31 		} zone_mgmt;
32 		struct {
33 			void *md_buf;
34 			struct iovec *iovs;
35 			int iovcnt;
36 			uint64_t num_blocks;
37 			uint64_t offset_blocks;
38 			uint64_t start_lba;
39 		} bdev;
40 	};
41 	spdk_bdev_io_completion_cb cb;
42 	void *cb_arg;
43 	enum spdk_bdev_io_type io_type;
44 };
45 
46 /* Global variables */
47 struct zone_io_operation *g_zone_op = NULL;
48 static struct spdk_bdev *g_bdev = NULL;
49 static struct spdk_bdev_io  *g_bdev_io = NULL;
50 static struct spdk_bdev_zone_info g_zone_info = {0};
51 static enum spdk_bdev_zone_action g_zone_action = SPDK_BDEV_ZONE_OPEN;
52 static enum spdk_bdev_zone_action g_unexpected_zone_action = SPDK_BDEV_ZONE_CLOSE;
53 static enum spdk_bdev_io_type g_io_type = SPDK_BDEV_IO_TYPE_GET_ZONE_INFO;
54 
55 static uint64_t g_expected_zone_id;
56 static uint64_t g_expected_num_zones;
57 static uint64_t g_unexpected_zone_id;
58 static uint64_t g_unexpected_num_zones;
59 static uint64_t g_num_blocks;
60 static uint64_t g_unexpected_num_blocks;
61 static uint64_t g_start_lba;
62 static uint64_t g_unexpected_start_lba;
63 static uint64_t g_bdev_blocklen;
64 static uint64_t g_unexpected_bdev_blocklen;
65 static int g_unexpected_iovcnt;
66 static void *g_md_buf;
67 static void *g_unexpected_md_buf;
68 static void *g_buf;
69 static void *g_unexpected_buf;
70 
71 static int
test_setup(void)72 test_setup(void)
73 {
74 	/* Initiate expected and unexpected value here */
75 	g_expected_zone_id = 0x1000;
76 	g_expected_num_zones = 1024;
77 	g_unexpected_zone_id = 0xFFFF;
78 	g_unexpected_num_zones = 0;
79 	g_num_blocks = 4096 * 1024;
80 	g_unexpected_num_blocks = 0;
81 	g_start_lba = 4096;
82 	g_unexpected_start_lba = 0;
83 	g_bdev_blocklen = 4096;
84 	g_unexpected_bdev_blocklen = 0;
85 	g_unexpected_iovcnt = 1000;
86 	g_md_buf = (void *)0xEFDCFEDE;
87 	g_unexpected_md_buf = (void *)0xFECDEFDC;
88 	g_buf = (void *)0xFEEDBEEF;
89 	g_unexpected_buf = (void *)0xDEADBEEF;
90 
91 	return 0;
92 }
93 
94 static int
test_cleanup(void)95 test_cleanup(void)
96 {
97 	return 0;
98 }
99 
100 static void
start_operation(void)101 start_operation(void)
102 {
103 	g_zone_op = calloc(1, sizeof(struct zone_io_operation));
104 	SPDK_CU_ASSERT_FATAL(g_zone_op != NULL);
105 
106 	switch (g_io_type) {
107 	case SPDK_BDEV_IO_TYPE_ZONE_APPEND:
108 		g_zone_op->bdev.iovs = &g_zone_op->iov;
109 		g_zone_op->bdev.iovs[0].iov_base = g_unexpected_buf;
110 		g_zone_op->bdev.iovs[0].iov_len = g_unexpected_num_blocks * g_unexpected_bdev_blocklen;
111 		g_zone_op->bdev.iovcnt = g_unexpected_iovcnt;
112 		g_zone_op->bdev.md_buf = g_unexpected_md_buf;
113 		g_zone_op->bdev.num_blocks = g_unexpected_num_blocks;
114 		g_zone_op->bdev.offset_blocks = g_unexpected_zone_id;
115 		g_zone_op->bdev.start_lba = g_unexpected_start_lba;
116 		break;
117 	default:
118 		g_zone_op->bdev.iovcnt = 0;
119 		g_zone_op->zone_mgmt.zone_id = g_unexpected_zone_id;
120 		g_zone_op->zone_mgmt.num_zones = g_unexpected_num_zones;
121 		g_zone_op->zone_mgmt.zone_action = g_unexpected_zone_action;
122 		g_zone_op->zone_mgmt.buf = g_unexpected_buf;
123 		break;
124 	}
125 }
126 
127 static void
stop_operation(void)128 stop_operation(void)
129 {
130 	free(g_bdev_io);
131 	free(g_bdev);
132 	free(g_zone_op);
133 	g_bdev_io = NULL;
134 	g_bdev = NULL;
135 	g_zone_op = NULL;
136 }
137 
138 struct spdk_bdev_io *
bdev_channel_get_io(struct spdk_bdev_channel * channel)139 bdev_channel_get_io(struct spdk_bdev_channel *channel)
140 {
141 	struct spdk_bdev_io *bdev_io;
142 
143 	bdev_io = calloc(1, sizeof(struct spdk_bdev_io));
144 	SPDK_CU_ASSERT_FATAL(bdev_io != NULL);
145 
146 	bdev_io->internal.ch = channel;
147 	bdev_io->type = g_io_type;
148 
149 	CU_ASSERT(g_zone_op != NULL);
150 
151 	switch (g_io_type) {
152 	case SPDK_BDEV_IO_TYPE_GET_ZONE_INFO:
153 	case SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT:
154 		bdev_io->u.bdev.iovcnt = 0;
155 		bdev_io->u.zone_mgmt.zone_id  = g_zone_op->zone_mgmt.zone_id;
156 		bdev_io->u.zone_mgmt.num_zones = g_zone_op->zone_mgmt.num_zones;
157 		bdev_io->u.zone_mgmt.zone_action = g_zone_op->zone_mgmt.zone_action;
158 		bdev_io->u.zone_mgmt.buf = g_zone_op->zone_mgmt.buf;
159 		break;
160 	case SPDK_BDEV_IO_TYPE_ZONE_APPEND:
161 		bdev_io->u.bdev.iovs = g_zone_op->bdev.iovs;
162 		bdev_io->u.bdev.iovs[0].iov_base = g_zone_op->bdev.iovs[0].iov_base;
163 		bdev_io->u.bdev.iovs[0].iov_len = g_zone_op->bdev.iovs[0].iov_len;
164 		bdev_io->u.bdev.iovcnt = g_zone_op->bdev.iovcnt;
165 		bdev_io->u.bdev.md_buf = g_zone_op->bdev.md_buf;
166 		bdev_io->u.bdev.num_blocks = g_zone_op->bdev.num_blocks;
167 		bdev_io->u.bdev.offset_blocks = g_zone_op->bdev.offset_blocks;
168 		break;
169 	default:
170 		CU_ASSERT(0);
171 	}
172 
173 	g_bdev_io = bdev_io;
174 
175 	return bdev_io;
176 }
177 
178 int
spdk_bdev_open_ext(const char * bdev_name,bool write,spdk_bdev_event_cb_t event_cb,void * event_ctx,struct spdk_bdev_desc ** _desc)179 spdk_bdev_open_ext(const char *bdev_name, bool write, spdk_bdev_event_cb_t event_cb,
180 		   void *event_ctx, struct spdk_bdev_desc **_desc)
181 {
182 	*_desc = (void *)0x1;
183 	return 0;
184 }
185 
186 struct spdk_io_channel *
spdk_bdev_get_io_channel(struct spdk_bdev_desc * desc)187 spdk_bdev_get_io_channel(struct spdk_bdev_desc *desc)
188 {
189 	return (struct spdk_io_channel *)0x1;
190 }
191 
192 void
spdk_put_io_channel(struct spdk_io_channel * ch)193 spdk_put_io_channel(struct spdk_io_channel *ch)
194 {
195 	CU_ASSERT(ch == (void *)1);
196 }
197 
198 struct spdk_bdev *
spdk_bdev_desc_get_bdev(struct spdk_bdev_desc * desc)199 spdk_bdev_desc_get_bdev(struct spdk_bdev_desc *desc)
200 {
201 	struct spdk_bdev *bdev;
202 
203 	bdev = calloc(1, sizeof(struct spdk_bdev));
204 	SPDK_CU_ASSERT_FATAL(bdev != NULL);
205 
206 	if (g_io_type == SPDK_BDEV_IO_TYPE_ZONE_APPEND) {
207 		bdev->blocklen = g_bdev_blocklen;
208 	}
209 
210 	g_bdev = bdev;
211 
212 	return bdev;
213 }
214 
215 static void
test_get_zone_size(void)216 test_get_zone_size(void)
217 {
218 	struct spdk_bdev bdev = {};
219 	uint64_t get_zone_size;
220 
221 	bdev.zone_size = 1024 * 4096;
222 
223 	get_zone_size = spdk_bdev_get_zone_size(&bdev);
224 	CU_ASSERT(get_zone_size == 1024 * 4096);
225 }
226 
227 static void
test_get_num_zones(void)228 test_get_num_zones(void)
229 {
230 	struct spdk_bdev bdev = {};
231 	uint64_t get_num_zones;
232 
233 	bdev.blockcnt = 1024 * 1024 * 1024;
234 	bdev.zone_size = 1024 * 4096;
235 
236 	get_num_zones = spdk_bdev_get_num_zones(&bdev);
237 	CU_ASSERT(get_num_zones == 256);
238 }
239 
240 static void
test_get_zone_id(void)241 test_get_zone_id(void)
242 {
243 	struct spdk_bdev bdev = {};
244 	uint64_t get_zone_id;
245 
246 	bdev.blockcnt = 1024 * 1024 * 1024;
247 	bdev.zone_size = 1024 * 4096;
248 
249 	get_zone_id = spdk_bdev_get_zone_id(&bdev, 0x800032);
250 	CU_ASSERT(get_zone_id == 0x800000);
251 }
252 
253 static void
test_get_max_zone_append_size(void)254 test_get_max_zone_append_size(void)
255 {
256 	struct spdk_bdev bdev = {};
257 	uint32_t get_max_zone_append_size;
258 
259 	bdev.max_zone_append_size = 32;
260 
261 	get_max_zone_append_size = spdk_bdev_get_max_zone_append_size(&bdev);
262 	CU_ASSERT(get_max_zone_append_size == 32);
263 }
264 
265 static void
test_get_max_open_zones(void)266 test_get_max_open_zones(void)
267 {
268 	struct spdk_bdev bdev = {};
269 	uint32_t get_max_open_zones;
270 
271 	bdev.max_open_zones = 8192;
272 
273 	get_max_open_zones = spdk_bdev_get_max_open_zones(&bdev);
274 	CU_ASSERT(get_max_open_zones == 8192);
275 }
276 
277 static void
test_get_max_active_zones(void)278 test_get_max_active_zones(void)
279 {
280 	struct spdk_bdev bdev = {};
281 	uint32_t get_max_active_zones;
282 
283 	bdev.max_active_zones = 9216;
284 
285 	get_max_active_zones = spdk_bdev_get_max_active_zones(&bdev);
286 	CU_ASSERT(get_max_active_zones == 9216);
287 }
288 
289 static void
test_get_optimal_open_zones(void)290 test_get_optimal_open_zones(void)
291 {
292 	struct spdk_bdev bdev = {};
293 	uint32_t get_optimal_open_zones;
294 
295 	bdev.optimal_open_zones = 4096;
296 
297 	get_optimal_open_zones = spdk_bdev_get_optimal_open_zones(&bdev);
298 	CU_ASSERT(get_optimal_open_zones == 4096);
299 }
300 
301 static void
test_bdev_io_get_append_location(void)302 test_bdev_io_get_append_location(void)
303 {
304 	struct spdk_bdev_io bdev_io = {};
305 	uint64_t get_offset_blocks;
306 
307 	bdev_io.u.bdev.offset_blocks = 1024 * 10;
308 
309 	get_offset_blocks = spdk_bdev_io_get_append_location(&bdev_io);
310 	CU_ASSERT(get_offset_blocks == 1024 * 10);
311 }
312 
313 static void
test_zone_get_operation(void)314 test_zone_get_operation(void)
315 {
316 	test_get_zone_size();
317 	test_get_num_zones();
318 	test_get_zone_id();
319 	test_get_max_zone_append_size();
320 	test_get_max_open_zones();
321 	test_get_max_active_zones();
322 	test_get_optimal_open_zones();
323 }
324 
325 #define DECLARE_VIRTUAL_BDEV_START() \
326     struct spdk_bdev bdev; \
327     struct spdk_io_channel *ch; \
328     struct spdk_bdev_desc *desc = NULL; \
329     int rc; \
330     memset(&bdev, 0, sizeof(bdev)); \
331     bdev.name = "bdev_zone_ut"; \
332     rc = spdk_bdev_open_ext(bdev.name, true, NULL, NULL, &desc); \
333     CU_ASSERT(rc == 0); \
334     SPDK_CU_ASSERT_FATAL(desc != NULL); \
335     ch = spdk_bdev_get_io_channel(desc); \
336     CU_ASSERT(ch != NULL);\
337 
338 static void
test_bdev_zone_get_info(void)339 test_bdev_zone_get_info(void)
340 {
341 	DECLARE_VIRTUAL_BDEV_START();
342 
343 	g_zone_info.zone_id = g_expected_zone_id;
344 	g_io_type = SPDK_BDEV_IO_TYPE_GET_ZONE_INFO;
345 
346 	start_operation();
347 
348 	rc = spdk_bdev_get_zone_info(desc, ch, g_expected_zone_id, g_expected_num_zones, &g_zone_info, NULL,
349 				     NULL);
350 	CU_ASSERT(rc == 0);
351 	CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_GET_ZONE_INFO);
352 	CU_ASSERT(g_bdev_io->u.zone_mgmt.zone_id == g_expected_zone_id);
353 	CU_ASSERT(g_bdev_io->u.zone_mgmt.num_zones == g_expected_num_zones);
354 	CU_ASSERT(g_bdev_io->u.zone_mgmt.buf == &g_zone_info);
355 
356 	stop_operation();
357 }
358 
359 static void
test_bdev_zone_management(void)360 test_bdev_zone_management(void)
361 {
362 	DECLARE_VIRTUAL_BDEV_START();
363 
364 	g_zone_info.zone_id = g_expected_zone_id;
365 	g_io_type = SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT;
366 
367 	start_operation();
368 
369 	rc = spdk_bdev_zone_management(desc, ch, g_expected_zone_id, g_zone_action, NULL,
370 				       NULL);
371 	CU_ASSERT(rc == 0);
372 	CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT);
373 	CU_ASSERT(g_bdev_io->u.zone_mgmt.zone_id == g_expected_zone_id);
374 	CU_ASSERT(g_bdev_io->u.zone_mgmt.zone_action == g_zone_action);
375 	CU_ASSERT(g_bdev_io->u.zone_mgmt.num_zones == 1);
376 
377 	stop_operation();
378 }
379 
380 static void
test_bdev_zone_append(void)381 test_bdev_zone_append(void)
382 {
383 	DECLARE_VIRTUAL_BDEV_START();
384 
385 	g_io_type = SPDK_BDEV_IO_TYPE_ZONE_APPEND;
386 
387 	start_operation();
388 
389 	rc = spdk_bdev_zone_append(desc, ch, g_buf, g_start_lba, g_num_blocks, NULL, NULL);
390 
391 	CU_ASSERT(rc == 0);
392 	CU_ASSERT(g_bdev_io->internal.desc == desc);
393 	CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_ZONE_APPEND);
394 	CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == g_buf);
395 	CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_len == g_num_blocks * g_bdev_blocklen);
396 	CU_ASSERT(g_bdev_io->u.bdev.iovcnt == 1);
397 	CU_ASSERT(g_bdev_io->u.bdev.md_buf == NULL);
398 	CU_ASSERT(g_bdev_io->u.bdev.num_blocks == g_num_blocks);
399 	CU_ASSERT(g_bdev_io->u.bdev.offset_blocks == g_expected_zone_id);
400 
401 	stop_operation();
402 }
403 
404 static void
test_bdev_zone_append_with_md(void)405 test_bdev_zone_append_with_md(void)
406 {
407 	DECLARE_VIRTUAL_BDEV_START();
408 
409 	g_io_type = SPDK_BDEV_IO_TYPE_ZONE_APPEND;
410 
411 	start_operation();
412 
413 	rc = spdk_bdev_zone_append_with_md(desc, ch, g_buf, g_md_buf, g_start_lba, g_num_blocks, NULL,
414 					   NULL);
415 
416 	CU_ASSERT(rc == 0);
417 	CU_ASSERT(g_bdev_io->internal.desc == desc);
418 	CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_ZONE_APPEND);
419 	CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == g_buf);
420 	CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_len == g_num_blocks * g_bdev_blocklen);
421 	CU_ASSERT(g_bdev_io->u.bdev.iovcnt == 1);
422 	CU_ASSERT(g_bdev_io->u.bdev.md_buf == g_md_buf);
423 	CU_ASSERT(g_bdev_io->u.bdev.num_blocks == g_num_blocks);
424 	CU_ASSERT(g_bdev_io->u.bdev.offset_blocks == g_expected_zone_id);
425 
426 	stop_operation();
427 }
428 
429 static void
test_bdev_zone_appendv(void)430 test_bdev_zone_appendv(void)
431 {
432 	DECLARE_VIRTUAL_BDEV_START();
433 
434 	g_io_type = SPDK_BDEV_IO_TYPE_ZONE_APPEND;
435 
436 	start_operation();
437 
438 	rc = spdk_bdev_zone_appendv(desc, ch, g_zone_op->bdev.iovs, g_unexpected_iovcnt, g_start_lba,
439 				    g_num_blocks, NULL, NULL);
440 
441 	CU_ASSERT(rc == 0);
442 	CU_ASSERT(g_bdev_io->internal.desc == desc);
443 	CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_ZONE_APPEND);
444 	CU_ASSERT(g_bdev_io->u.bdev.iovs == g_zone_op->bdev.iovs);
445 	CU_ASSERT(g_bdev_io->u.bdev.iovcnt == g_unexpected_iovcnt);
446 	CU_ASSERT(g_bdev_io->u.bdev.md_buf == NULL);
447 	CU_ASSERT(g_bdev_io->u.bdev.num_blocks == g_num_blocks);
448 	CU_ASSERT(g_bdev_io->u.bdev.offset_blocks == g_expected_zone_id);
449 
450 	stop_operation();
451 }
452 
453 static void
test_bdev_zone_appendv_with_md(void)454 test_bdev_zone_appendv_with_md(void)
455 {
456 	DECLARE_VIRTUAL_BDEV_START();
457 
458 	g_io_type = SPDK_BDEV_IO_TYPE_ZONE_APPEND;
459 
460 	start_operation();
461 
462 	rc = spdk_bdev_zone_appendv_with_md(desc, ch, g_zone_op->bdev.iovs, g_unexpected_iovcnt, g_md_buf,
463 					    g_start_lba, g_num_blocks, NULL, NULL);
464 
465 	CU_ASSERT(rc == 0);
466 	CU_ASSERT(g_bdev_io->internal.desc == desc);
467 	CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_ZONE_APPEND);
468 	CU_ASSERT(g_bdev_io->u.bdev.iovs == g_zone_op->bdev.iovs);
469 	CU_ASSERT(g_bdev_io->u.bdev.iovcnt == g_unexpected_iovcnt);
470 	CU_ASSERT(g_bdev_io->u.bdev.md_buf == g_md_buf);
471 	CU_ASSERT(g_bdev_io->u.bdev.num_blocks == g_num_blocks);
472 	CU_ASSERT(g_bdev_io->u.bdev.offset_blocks == g_expected_zone_id);
473 
474 	stop_operation();
475 }
476 
477 int
main(int argc,char ** argv)478 main(int argc, char **argv)
479 {
480 	CU_pSuite suite = NULL;
481 	unsigned int num_failures;
482 
483 	CU_initialize_registry();
484 
485 	suite = CU_add_suite("zone", test_setup, test_cleanup);
486 	CU_ADD_TEST(suite, test_zone_get_operation);
487 	CU_ADD_TEST(suite, test_bdev_zone_get_info);
488 	CU_ADD_TEST(suite, test_bdev_zone_management);
489 	CU_ADD_TEST(suite, test_bdev_zone_append);
490 	CU_ADD_TEST(suite, test_bdev_zone_append_with_md);
491 	CU_ADD_TEST(suite, test_bdev_zone_appendv);
492 	CU_ADD_TEST(suite, test_bdev_zone_appendv_with_md);
493 	CU_ADD_TEST(suite, test_bdev_io_get_append_location);
494 
495 	num_failures = spdk_ut_run_tests(argc, argv, NULL);
496 	CU_cleanup_registry();
497 	return num_failures;
498 }
499