xref: /spdk/test/unit/lib/bdev/bdev_zone.c/bdev_zone_ut.c (revision 8bb0ded3e55c182cea67af1f6790f8de5f38c05f)
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_max_open_zones(void)
259 {
260 	struct spdk_bdev bdev = {};
261 	uint32_t get_max_open_zones;
262 
263 	bdev.max_open_zones = 8192;
264 
265 	get_max_open_zones = spdk_bdev_get_max_open_zones(&bdev);
266 	CU_ASSERT(get_max_open_zones == 8192);
267 }
268 
269 static void
270 test_get_optimal_open_zones(void)
271 {
272 	struct spdk_bdev bdev = {};
273 	uint32_t get_optimal_open_zones;
274 
275 	bdev.optimal_open_zones = 4096;
276 
277 	get_optimal_open_zones = spdk_bdev_get_optimal_open_zones(&bdev);
278 	CU_ASSERT(get_optimal_open_zones == 4096);
279 }
280 
281 static void
282 test_bdev_io_get_append_location(void)
283 {
284 	struct spdk_bdev_io bdev_io = {};
285 	uint64_t get_offset_blocks;
286 
287 	bdev_io.u.bdev.offset_blocks = 1024 * 10;
288 
289 	get_offset_blocks = spdk_bdev_io_get_append_location(&bdev_io);
290 	CU_ASSERT(get_offset_blocks == 1024 * 10);
291 }
292 
293 static void
294 test_zone_get_operation(void)
295 {
296 	test_get_zone_size();
297 	test_get_max_open_zones();
298 	test_get_optimal_open_zones();
299 }
300 
301 #define DECLARE_VIRTUAL_BDEV_START() \
302     struct spdk_bdev bdev; \
303     struct spdk_io_channel *ch; \
304     struct spdk_bdev_desc *desc = NULL; \
305     int rc; \
306     memset(&bdev, 0, sizeof(bdev)); \
307     bdev.name = "bdev_zone_ut"; \
308     rc = spdk_bdev_open_ext(bdev.name, true, NULL, NULL, &desc); \
309     CU_ASSERT(rc == 0); \
310     SPDK_CU_ASSERT_FATAL(desc != NULL); \
311     ch = spdk_bdev_get_io_channel(desc); \
312     CU_ASSERT(ch != NULL);\
313 
314 static void
315 test_bdev_zone_get_info(void)
316 {
317 	DECLARE_VIRTUAL_BDEV_START();
318 
319 	g_zone_info.zone_id = g_expected_zone_id;
320 	g_io_type = SPDK_BDEV_IO_TYPE_GET_ZONE_INFO;
321 
322 	start_operation();
323 
324 	rc = spdk_bdev_get_zone_info(desc, ch, g_expected_zone_id, g_expected_num_zones, &g_zone_info, NULL,
325 				     NULL);
326 	CU_ASSERT(rc == 0);
327 	CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_GET_ZONE_INFO);
328 	CU_ASSERT(g_bdev_io->u.zone_mgmt.zone_id == g_expected_zone_id);
329 	CU_ASSERT(g_bdev_io->u.zone_mgmt.num_zones == g_expected_num_zones);
330 	CU_ASSERT(g_bdev_io->u.zone_mgmt.buf == &g_zone_info);
331 
332 	stop_operation();
333 }
334 
335 static void
336 test_bdev_zone_management(void)
337 {
338 	DECLARE_VIRTUAL_BDEV_START();
339 
340 	g_zone_info.zone_id = g_expected_zone_id;
341 	g_io_type = SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT;
342 
343 	start_operation();
344 
345 	rc = spdk_bdev_zone_management(desc, ch, g_expected_zone_id, g_zone_action, NULL,
346 				       NULL);
347 	CU_ASSERT(rc == 0);
348 	CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_ZONE_MANAGEMENT);
349 	CU_ASSERT(g_bdev_io->u.zone_mgmt.zone_id == g_expected_zone_id);
350 	CU_ASSERT(g_bdev_io->u.zone_mgmt.zone_action == g_zone_action);
351 	CU_ASSERT(g_bdev_io->u.zone_mgmt.num_zones == 1);
352 
353 	stop_operation();
354 }
355 
356 static void
357 test_bdev_zone_append(void)
358 {
359 	DECLARE_VIRTUAL_BDEV_START();
360 
361 	g_io_type = SPDK_BDEV_IO_TYPE_ZONE_APPEND;
362 	g_append_with_md = false;
363 
364 	start_operation();
365 
366 	rc = spdk_bdev_zone_append(desc, ch, g_buf, g_start_lba, g_num_blocks, NULL, NULL);
367 
368 	CU_ASSERT(rc == 0);
369 	CU_ASSERT(g_bdev_io->internal.desc == desc);
370 	CU_ASSERT(g_bdev_io->type == SPDK_BDEV_IO_TYPE_ZONE_APPEND);
371 	CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_base == g_buf);
372 	CU_ASSERT(g_bdev_io->u.bdev.iovs[0].iov_len == g_num_blocks * g_bdev_blocklen);
373 	CU_ASSERT(g_bdev_io->u.bdev.iovcnt == 1);
374 	CU_ASSERT(g_bdev_io->u.bdev.md_buf == NULL);
375 	CU_ASSERT(g_bdev_io->u.bdev.num_blocks == g_num_blocks);
376 	CU_ASSERT(g_bdev_io->u.bdev.offset_blocks == g_expected_zone_id);
377 
378 	stop_operation();
379 }
380 
381 static void
382 test_bdev_zone_append_with_md(void)
383 {
384 	DECLARE_VIRTUAL_BDEV_START();
385 
386 	g_io_type = SPDK_BDEV_IO_TYPE_ZONE_APPEND;
387 	g_append_with_md = true;
388 
389 	start_operation();
390 
391 	rc = spdk_bdev_zone_append_with_md(desc, ch, g_buf, g_md_buf, g_start_lba, g_num_blocks, NULL,
392 					   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 == g_md_buf);
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 int
408 main(int argc, char **argv)
409 {
410 	CU_pSuite suite = NULL;
411 	unsigned int num_failures;
412 
413 	CU_set_error_action(CUEA_ABORT);
414 	CU_initialize_registry();
415 
416 	suite = CU_add_suite("zone", test_setup, test_cleanup);
417 	CU_ADD_TEST(suite, test_zone_get_operation);
418 	CU_ADD_TEST(suite, test_bdev_zone_get_info);
419 	CU_ADD_TEST(suite, test_bdev_zone_management);
420 	CU_ADD_TEST(suite, test_bdev_zone_append);
421 	CU_ADD_TEST(suite, test_bdev_zone_append_with_md);
422 	CU_ADD_TEST(suite, test_bdev_io_get_append_location);
423 
424 	CU_basic_set_mode(CU_BRM_VERBOSE);
425 	CU_basic_run_tests();
426 	num_failures = CU_get_number_of_failures();
427 	CU_cleanup_registry();
428 	return num_failures;
429 }
430