xref: /spdk/test/unit/lib/bdev/bdev_zone.c/bdev_zone_ut.c (revision 2f5c602574a98ede645991abe279a96e19c50196)
1 /*-
2  *   BSD LICENSE
3  *
4  *   Copyright (c) Intel Corporation.
5  *   All rights reserved.
6  *
7  *   Redistribution and use in source and binary forms, with or without
8  *   modification, are permitted provided that the following conditions
9  *   are met:
10  *
11  *     * Redistributions of source code must retain the above copyright
12  *       notice, this list of conditions and the following disclaimer.
13  *     * Redistributions in binary form must reproduce the above copyright
14  *       notice, this list of conditions and the following disclaimer in
15  *       the documentation and/or other materials provided with the
16  *       distribution.
17  *     * Neither the name of Intel Corporation nor the names of its
18  *       contributors may be used to endorse or promote products derived
19  *       from this software without specific prior written permission.
20  *
21  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *   A PARTICULAR PURPOSE AiRE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "spdk/stdinc.h"
35 #include "spdk_cunit.h"
36 #include "spdk/env.h"
37 #include "spdk_internal/mock.h"
38 
39 #include "bdev/bdev_zone.c"
40 
41 DEFINE_STUB_V(bdev_io_init, (struct spdk_bdev_io *bdev_io,
42 			     struct spdk_bdev *bdev, void *cb_arg,
43 			     spdk_bdev_io_completion_cb cb));
44 
45 DEFINE_STUB_V(bdev_io_submit, (struct spdk_bdev_io *bdev_io));
46 
47 /* Construct zone_io_operation structure */
48 struct zone_io_operation {
49 	struct spdk_bdev_desc *desc;
50 	struct spdk_io_channel *ch;
51 	struct iovec iov;
52 	union {
53 		struct {
54 			uint64_t zone_id;
55 			size_t num_zones;
56 			enum spdk_bdev_zone_action zone_action;
57 			void *buf;
58 			struct spdk_bdev_zone_info *info_;
59 		} zone_mgmt;
60 		struct {
61 			void *md_buf;
62 			struct iovec *iovs;
63 			int iovcnt;
64 			uint64_t num_blocks;
65 			uint64_t offset_blocks;
66 			uint64_t start_lba;
67 		} bdev;
68 	};
69 	spdk_bdev_io_completion_cb cb;
70 	void *cb_arg;
71 	enum spdk_bdev_io_type io_type;
72 };
73 
74 /* Global variables */
75 struct zone_io_operation *g_zone_op = NULL;
76 static struct spdk_bdev *g_bdev = NULL;
77 static struct spdk_bdev_io  *g_bdev_io = NULL;
78 static struct spdk_bdev_zone_info g_zone_info = {0};
79 static enum spdk_bdev_zone_action g_zone_action = SPDK_BDEV_ZONE_OPEN;
80 static enum spdk_bdev_zone_action g_unexpected_zone_action = SPDK_BDEV_ZONE_CLOSE;
81 static enum spdk_bdev_io_type g_io_type = SPDK_BDEV_IO_TYPE_GET_ZONE_INFO;
82 
83 static uint64_t g_expected_zone_id;
84 static uint64_t g_expected_num_zones;
85 static uint64_t g_unexpected_zone_id;
86 static uint64_t g_unexpected_num_zones;
87 static uint64_t g_num_blocks;
88 static uint64_t g_unexpected_num_blocks;
89 static uint64_t g_start_lba;
90 static uint64_t g_unexpected_start_lba;
91 static uint64_t g_bdev_blocklen;
92 static uint64_t g_unexpected_bdev_blocklen;
93 static bool g_append_with_md;
94 static int g_unexpected_iovcnt;
95 static void *g_md_buf;
96 static void *g_unexpetced_md_buf;
97 static void *g_buf;
98 static void *g_unexpected_buf;
99 
100 static int
101 test_setup(void)
102 {
103 	/* Initiate expected and unexpected value here */
104 	g_expected_zone_id = 0x1000;
105 	g_expected_num_zones = 1024;
106 	g_unexpected_zone_id = 0xFFFF;
107 	g_unexpected_num_zones = 0;
108 	g_num_blocks = 4096 * 1024;
109 	g_unexpected_num_blocks = 0;
110 	g_start_lba = 4096;
111 	g_unexpected_start_lba = 0;
112 	g_bdev_blocklen = 4096;
113 	g_unexpected_bdev_blocklen = 0;
114 	g_append_with_md = false;
115 	g_unexpected_iovcnt = 1000;
116 	g_md_buf = (void *)0xEFDCFEDE;
117 	g_unexpetced_md_buf = (void *)0xFECDEFDC;
118 	g_buf = (void *)0xFEEDBEEF;
119 	g_unexpected_buf = (void *)0xDEADBEEF;
120 
121 	return 0;
122 }
123 
124 static int
125 test_cleanup(void)
126 {
127 	return 0;
128 }
129 
130 static void
131 start_operation(void)
132 {
133 	g_zone_op = calloc(1, sizeof(struct zone_io_operation));
134 	SPDK_CU_ASSERT_FATAL(g_zone_op != NULL);
135 
136 	switch (g_io_type) {
137 	case SPDK_BDEV_IO_TYPE_ZONE_APPEND:
138 		g_zone_op->bdev.iovs = &g_zone_op->iov;
139 		g_zone_op->bdev.iovs[0].iov_base = g_unexpected_buf;
140 		g_zone_op->bdev.iovs[0].iov_len = g_unexpected_num_blocks * g_unexpected_bdev_blocklen;
141 		g_zone_op->bdev.iovcnt = g_unexpected_iovcnt;
142 		g_zone_op->bdev.md_buf = g_unexpetced_md_buf;
143 		g_zone_op->bdev.num_blocks = g_unexpected_num_blocks;
144 		g_zone_op->bdev.offset_blocks = g_unexpected_zone_id;
145 		g_zone_op->bdev.start_lba = g_unexpected_start_lba;
146 		break;
147 	default:
148 		g_zone_op->bdev.iovcnt = 0;
149 		g_zone_op->zone_mgmt.zone_id = g_unexpected_zone_id;
150 		g_zone_op->zone_mgmt.num_zones = g_unexpected_num_zones;
151 		g_zone_op->zone_mgmt.zone_action = g_unexpected_zone_action;
152 		g_zone_op->zone_mgmt.buf = g_unexpected_buf;
153 		break;
154 	}
155 }
156 
157 static void
158 stop_operation(void)
159 {
160 	free(g_bdev_io);
161 	free(g_bdev);
162 	free(g_zone_op);
163 	g_bdev_io = NULL;
164 	g_bdev = NULL;
165 	g_zone_op = NULL;
166 }
167 
168 struct spdk_bdev_io *
169 bdev_channel_get_io(struct spdk_bdev_channel *channel)
170 {
171 	struct spdk_bdev_io *bdev_io;
172 
173 	bdev_io = calloc(1, sizeof(struct spdk_bdev_io));
174 	SPDK_CU_ASSERT_FATAL(bdev_io != NULL);
175 
176 	bdev_io->internal.ch = channel;
177 	bdev_io->type = g_io_type;
178 
179 	CU_ASSERT(g_zone_op != NULL);
180 
181 	switch (g_io_type) {
182 	case SPDK_BDEV_IO_TYPE_GET_ZONE_INFO:
183 	case SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT:
184 		bdev_io->u.bdev.iovcnt = 0;
185 		bdev_io->u.zone_mgmt.zone_id  = g_zone_op->zone_mgmt.zone_id;
186 		bdev_io->u.zone_mgmt.num_zones = g_zone_op->zone_mgmt.num_zones;
187 		bdev_io->u.zone_mgmt.zone_action = g_zone_op->zone_mgmt.zone_action;
188 		bdev_io->u.zone_mgmt.buf = g_zone_op->zone_mgmt.buf;
189 		break;
190 	case SPDK_BDEV_IO_TYPE_ZONE_APPEND:
191 		bdev_io->u.bdev.iovs = g_zone_op->bdev.iovs;
192 		bdev_io->u.bdev.iovs[0].iov_base = g_zone_op->bdev.iovs[0].iov_base;
193 		bdev_io->u.bdev.iovs[0].iov_len = g_zone_op->bdev.iovs[0].iov_len;
194 		bdev_io->u.bdev.iovcnt = g_zone_op->bdev.iovcnt;
195 		bdev_io->u.bdev.md_buf = g_zone_op->bdev.md_buf;
196 		bdev_io->u.bdev.num_blocks = g_zone_op->bdev.num_blocks;
197 		bdev_io->u.bdev.offset_blocks = g_zone_op->bdev.offset_blocks;
198 		break;
199 	default:
200 		CU_ASSERT(0);
201 	}
202 
203 	g_bdev_io = bdev_io;
204 
205 	return bdev_io;
206 }
207 
208 int
209 spdk_bdev_open_ext(const char *bdev_name, bool write, spdk_bdev_event_cb_t event_cb,
210 		   void *event_ctx, struct spdk_bdev_desc **_desc)
211 {
212 	*_desc = (void *)0x1;
213 	return 0;
214 }
215 
216 struct spdk_io_channel *
217 spdk_bdev_get_io_channel(struct spdk_bdev_desc *desc)
218 {
219 	return (struct spdk_io_channel *)0x1;
220 }
221 
222 void
223 spdk_put_io_channel(struct spdk_io_channel *ch)
224 {
225 	CU_ASSERT(ch == (void *)1);
226 }
227 
228 struct spdk_bdev *
229 spdk_bdev_desc_get_bdev(struct spdk_bdev_desc *desc)
230 {
231 	struct spdk_bdev *bdev;
232 
233 	bdev = calloc(1, sizeof(struct spdk_bdev));
234 	SPDK_CU_ASSERT_FATAL(bdev != NULL);
235 
236 	if (g_io_type == SPDK_BDEV_IO_TYPE_ZONE_APPEND) {
237 		bdev->blocklen = g_bdev_blocklen;
238 	}
239 
240 	g_bdev = bdev;
241 
242 	return bdev;
243 }
244 
245 static void
246 test_get_zone_size(void)
247 {
248 	struct spdk_bdev bdev = {};
249 	uint64_t get_zone_size;
250 
251 	bdev.zone_size = 1024 * 4096;
252 
253 	get_zone_size = spdk_bdev_get_zone_size(&bdev);
254 	CU_ASSERT(get_zone_size == 1024 * 4096);
255 }
256 
257 static void
258 test_get_num_zones(void)
259 {
260 	struct spdk_bdev bdev = {};
261 	uint64_t get_num_zones;
262 
263 	bdev.blockcnt = 1024 * 1024 * 1024;
264 	bdev.zone_size = 1024 * 4096;
265 
266 	get_num_zones = spdk_bdev_get_num_zones(&bdev);
267 	CU_ASSERT(get_num_zones == 256);
268 }
269 
270 static void
271 test_get_max_zone_append_size(void)
272 {
273 	struct spdk_bdev bdev = {};
274 	uint32_t get_max_zone_append_size;
275 
276 	bdev.max_zone_append_size = 32;
277 
278 	get_max_zone_append_size = spdk_bdev_get_max_zone_append_size(&bdev);
279 	CU_ASSERT(get_max_zone_append_size == 32);
280 }
281 
282 static void
283 test_get_max_open_zones(void)
284 {
285 	struct spdk_bdev bdev = {};
286 	uint32_t get_max_open_zones;
287 
288 	bdev.max_open_zones = 8192;
289 
290 	get_max_open_zones = spdk_bdev_get_max_open_zones(&bdev);
291 	CU_ASSERT(get_max_open_zones == 8192);
292 }
293 
294 static void
295 test_get_max_active_zones(void)
296 {
297 	struct spdk_bdev bdev = {};
298 	uint32_t get_max_active_zones;
299 
300 	bdev.max_active_zones = 9216;
301 
302 	get_max_active_zones = spdk_bdev_get_max_active_zones(&bdev);
303 	CU_ASSERT(get_max_active_zones == 9216);
304 }
305 
306 static void
307 test_get_optimal_open_zones(void)
308 {
309 	struct spdk_bdev bdev = {};
310 	uint32_t get_optimal_open_zones;
311 
312 	bdev.optimal_open_zones = 4096;
313 
314 	get_optimal_open_zones = spdk_bdev_get_optimal_open_zones(&bdev);
315 	CU_ASSERT(get_optimal_open_zones == 4096);
316 }
317 
318 static void
319 test_bdev_io_get_append_location(void)
320 {
321 	struct spdk_bdev_io bdev_io = {};
322 	uint64_t get_offset_blocks;
323 
324 	bdev_io.u.bdev.offset_blocks = 1024 * 10;
325 
326 	get_offset_blocks = spdk_bdev_io_get_append_location(&bdev_io);
327 	CU_ASSERT(get_offset_blocks == 1024 * 10);
328 }
329 
330 static void
331 test_zone_get_operation(void)
332 {
333 	test_get_zone_size();
334 	test_get_num_zones();
335 	test_get_max_zone_append_size();
336 	test_get_max_open_zones();
337 	test_get_max_active_zones();
338 	test_get_optimal_open_zones();
339 }
340 
341 #define DECLARE_VIRTUAL_BDEV_START() \
342     struct spdk_bdev bdev; \
343     struct spdk_io_channel *ch; \
344     struct spdk_bdev_desc *desc = NULL; \
345     int rc; \
346     memset(&bdev, 0, sizeof(bdev)); \
347     bdev.name = "bdev_zone_ut"; \
348     rc = spdk_bdev_open_ext(bdev.name, true, NULL, NULL, &desc); \
349     CU_ASSERT(rc == 0); \
350     SPDK_CU_ASSERT_FATAL(desc != NULL); \
351     ch = spdk_bdev_get_io_channel(desc); \
352     CU_ASSERT(ch != NULL);\
353 
354 static void
355 test_bdev_zone_get_info(void)
356 {
357 	DECLARE_VIRTUAL_BDEV_START();
358 
359 	g_zone_info.zone_id = g_expected_zone_id;
360 	g_io_type = SPDK_BDEV_IO_TYPE_GET_ZONE_INFO;
361 
362 	start_operation();
363 
364 	rc = spdk_bdev_get_zone_info(desc, ch, g_expected_zone_id, g_expected_num_zones, &g_zone_info, NULL,
365 				     NULL);
366 	CU_ASSERT(rc == 0);
367 	CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_GET_ZONE_INFO);
368 	CU_ASSERT(g_bdev_io->u.zone_mgmt.zone_id == g_expected_zone_id);
369 	CU_ASSERT(g_bdev_io->u.zone_mgmt.num_zones == g_expected_num_zones);
370 	CU_ASSERT(g_bdev_io->u.zone_mgmt.buf == &g_zone_info);
371 
372 	stop_operation();
373 }
374 
375 static void
376 test_bdev_zone_management(void)
377 {
378 	DECLARE_VIRTUAL_BDEV_START();
379 
380 	g_zone_info.zone_id = g_expected_zone_id;
381 	g_io_type = SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT;
382 
383 	start_operation();
384 
385 	rc = spdk_bdev_zone_management(desc, ch, g_expected_zone_id, g_zone_action, NULL,
386 				       NULL);
387 	CU_ASSERT(rc == 0);
388 	CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT);
389 	CU_ASSERT(g_bdev_io->u.zone_mgmt.zone_id == g_expected_zone_id);
390 	CU_ASSERT(g_bdev_io->u.zone_mgmt.zone_action == g_zone_action);
391 	CU_ASSERT(g_bdev_io->u.zone_mgmt.num_zones == 1);
392 
393 	stop_operation();
394 }
395 
396 static void
397 test_bdev_zone_append(void)
398 {
399 	DECLARE_VIRTUAL_BDEV_START();
400 
401 	g_io_type = SPDK_BDEV_IO_TYPE_ZONE_APPEND;
402 	g_append_with_md = false;
403 
404 	start_operation();
405 
406 	rc = spdk_bdev_zone_append(desc, ch, g_buf, g_start_lba, g_num_blocks, NULL, NULL);
407 
408 	CU_ASSERT(rc == 0);
409 	CU_ASSERT(g_bdev_io->internal.desc == desc);
410 	CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_ZONE_APPEND);
411 	CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == g_buf);
412 	CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_len == g_num_blocks * g_bdev_blocklen);
413 	CU_ASSERT(g_bdev_io->u.bdev.iovcnt == 1);
414 	CU_ASSERT(g_bdev_io->u.bdev.md_buf == NULL);
415 	CU_ASSERT(g_bdev_io->u.bdev.num_blocks == g_num_blocks);
416 	CU_ASSERT(g_bdev_io->u.bdev.offset_blocks == g_expected_zone_id);
417 
418 	stop_operation();
419 }
420 
421 static void
422 test_bdev_zone_append_with_md(void)
423 {
424 	DECLARE_VIRTUAL_BDEV_START();
425 
426 	g_io_type = SPDK_BDEV_IO_TYPE_ZONE_APPEND;
427 	g_append_with_md = true;
428 
429 	start_operation();
430 
431 	rc = spdk_bdev_zone_append_with_md(desc, ch, g_buf, g_md_buf, g_start_lba, g_num_blocks, NULL,
432 					   NULL);
433 
434 	CU_ASSERT(rc == 0);
435 	CU_ASSERT(g_bdev_io->internal.desc == desc);
436 	CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_ZONE_APPEND);
437 	CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == g_buf);
438 	CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_len == g_num_blocks * g_bdev_blocklen);
439 	CU_ASSERT(g_bdev_io->u.bdev.iovcnt == 1);
440 	CU_ASSERT(g_bdev_io->u.bdev.md_buf == g_md_buf);
441 	CU_ASSERT(g_bdev_io->u.bdev.num_blocks == g_num_blocks);
442 	CU_ASSERT(g_bdev_io->u.bdev.offset_blocks == g_expected_zone_id);
443 
444 	stop_operation();
445 }
446 
447 int
448 main(int argc, char **argv)
449 {
450 	CU_pSuite suite = NULL;
451 	unsigned int num_failures;
452 
453 	CU_set_error_action(CUEA_ABORT);
454 	CU_initialize_registry();
455 
456 	suite = CU_add_suite("zone", test_setup, test_cleanup);
457 	CU_ADD_TEST(suite, test_zone_get_operation);
458 	CU_ADD_TEST(suite, test_bdev_zone_get_info);
459 	CU_ADD_TEST(suite, test_bdev_zone_management);
460 	CU_ADD_TEST(suite, test_bdev_zone_append);
461 	CU_ADD_TEST(suite, test_bdev_zone_append_with_md);
462 	CU_ADD_TEST(suite, test_bdev_io_get_append_location);
463 
464 	CU_basic_set_mode(CU_BRM_VERBOSE);
465 	CU_basic_run_tests();
466 	num_failures = CU_get_number_of_failures();
467 	CU_cleanup_registry();
468 	return num_failures;
469 }
470