xref: /spdk/test/unit/lib/bdev/bdev_zone.c/bdev_zone_ut.c (revision 12fbe739a31b09aff0d05f354d4f3bbef99afc55)
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
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
95  test_cleanup(void)
96  {
97  	return 0;
98  }
99  
100  static 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
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 *
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
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 *
187  spdk_bdev_get_io_channel(struct spdk_bdev_desc *desc)
188  {
189  	return (struct spdk_io_channel *)0x1;
190  }
191  
192  void
193  spdk_put_io_channel(struct spdk_io_channel *ch)
194  {
195  	CU_ASSERT(ch == (void *)1);
196  }
197  
198  struct spdk_bdev *
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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