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