xref: /spdk/test/unit/lib/bdev/raid/raid0.c/raid0_ut.c (revision 1b9c5629935b12cf24549719cbb99e502c13dd64)
1698da718SArtur Paszkiewicz /*   SPDX-License-Identifier: BSD-3-Clause
2698da718SArtur Paszkiewicz  *   Copyright (C) 2024 Intel Corporation.
3698da718SArtur Paszkiewicz  *   All rights reserved.
4698da718SArtur Paszkiewicz  */
5698da718SArtur Paszkiewicz 
6698da718SArtur Paszkiewicz #include "spdk/stdinc.h"
7698da718SArtur Paszkiewicz #include "spdk_internal/cunit.h"
8698da718SArtur Paszkiewicz #include "spdk/env.h"
9698da718SArtur Paszkiewicz 
10698da718SArtur Paszkiewicz #include "common/lib/ut_multithread.c"
11698da718SArtur Paszkiewicz 
12698da718SArtur Paszkiewicz #include "bdev/raid/raid0.c"
13698da718SArtur Paszkiewicz #include "../common.c"
14698da718SArtur Paszkiewicz 
15698da718SArtur Paszkiewicz #define MAX_BASE_DRIVES 32
16698da718SArtur Paszkiewicz #define MAX_TEST_IO_RANGE (3 * 3 * 3 * (MAX_BASE_DRIVES + 5))
17698da718SArtur Paszkiewicz #define BLOCK_CNT (1024ul * 1024ul * 1024ul * 1024ul)
18698da718SArtur Paszkiewicz 
19698da718SArtur Paszkiewicz /* Data structure to capture the output of IO for verification */
20698da718SArtur Paszkiewicz struct io_output {
21698da718SArtur Paszkiewicz 	struct spdk_bdev_desc       *desc;
22698da718SArtur Paszkiewicz 	struct spdk_io_channel      *ch;
23698da718SArtur Paszkiewicz 	uint64_t                    offset_blocks;
24698da718SArtur Paszkiewicz 	uint64_t                    num_blocks;
25698da718SArtur Paszkiewicz 	spdk_bdev_io_completion_cb  cb;
26698da718SArtur Paszkiewicz 	void                        *cb_arg;
27698da718SArtur Paszkiewicz 	enum spdk_bdev_io_type      iotype;
28698da718SArtur Paszkiewicz 	struct iovec                *iovs;
29698da718SArtur Paszkiewicz 	int                         iovcnt;
30698da718SArtur Paszkiewicz 	void                        *md_buf;
31698da718SArtur Paszkiewicz };
32698da718SArtur Paszkiewicz 
33698da718SArtur Paszkiewicz struct raid_io_ranges {
34698da718SArtur Paszkiewicz 	uint64_t lba;
35698da718SArtur Paszkiewicz 	uint64_t nblocks;
36698da718SArtur Paszkiewicz };
37698da718SArtur Paszkiewicz 
38698da718SArtur Paszkiewicz /* Globals */
39698da718SArtur Paszkiewicz struct io_output *g_io_output = NULL;
40698da718SArtur Paszkiewicz uint32_t g_io_output_index;
41698da718SArtur Paszkiewicz uint32_t g_io_comp_status;
42698da718SArtur Paszkiewicz bool g_child_io_status_flag;
43698da718SArtur Paszkiewicz TAILQ_HEAD(bdev, spdk_bdev);
44698da718SArtur Paszkiewicz uint32_t g_block_len;
45698da718SArtur Paszkiewicz uint32_t g_strip_size;
46698da718SArtur Paszkiewicz uint32_t g_max_io_size;
47698da718SArtur Paszkiewicz uint8_t g_max_base_drives;
48698da718SArtur Paszkiewicz struct raid_io_ranges g_io_ranges[MAX_TEST_IO_RANGE];
49698da718SArtur Paszkiewicz uint32_t g_io_range_idx;
50698da718SArtur Paszkiewicz bool g_enable_dif;
51698da718SArtur Paszkiewicz 
52698da718SArtur Paszkiewicz DEFINE_STUB_V(raid_bdev_module_list_add, (struct raid_bdev_module *raid_module));
53698da718SArtur Paszkiewicz DEFINE_STUB_V(raid_bdev_queue_io_wait, (struct raid_bdev_io *raid_io, struct spdk_bdev *bdev,
54698da718SArtur Paszkiewicz 					struct spdk_io_channel *ch, spdk_bdev_io_wait_cb cb_fn));
55698da718SArtur Paszkiewicz DEFINE_STUB(spdk_bdev_flush_blocks, int, (struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
56698da718SArtur Paszkiewicz 		uint64_t offset_blocks, uint64_t num_blocks, spdk_bdev_io_completion_cb cb,
57698da718SArtur Paszkiewicz 		void *cb_arg), 0);
58698da718SArtur Paszkiewicz DEFINE_STUB(spdk_bdev_is_dif_head_of_md, bool, (const struct spdk_bdev *bdev), false);
59698da718SArtur Paszkiewicz DEFINE_STUB(spdk_bdev_notify_blockcnt_change, int, (struct spdk_bdev *bdev, uint64_t size), 0);
60698da718SArtur Paszkiewicz 
61698da718SArtur Paszkiewicz bool
spdk_bdev_is_md_interleaved(const struct spdk_bdev * bdev)62698da718SArtur Paszkiewicz spdk_bdev_is_md_interleaved(const struct spdk_bdev *bdev)
63698da718SArtur Paszkiewicz {
64698da718SArtur Paszkiewicz 	return (bdev->md_len != 0) && bdev->md_interleave;
65698da718SArtur Paszkiewicz }
66698da718SArtur Paszkiewicz 
67698da718SArtur Paszkiewicz bool
spdk_bdev_is_md_separate(const struct spdk_bdev * bdev)68698da718SArtur Paszkiewicz spdk_bdev_is_md_separate(const struct spdk_bdev *bdev)
69698da718SArtur Paszkiewicz {
70698da718SArtur Paszkiewicz 	return (bdev->md_len != 0) && !bdev->md_interleave;
71698da718SArtur Paszkiewicz }
72698da718SArtur Paszkiewicz 
73698da718SArtur Paszkiewicz uint32_t
spdk_bdev_get_md_size(const struct spdk_bdev * bdev)74698da718SArtur Paszkiewicz spdk_bdev_get_md_size(const struct spdk_bdev *bdev)
75698da718SArtur Paszkiewicz {
76698da718SArtur Paszkiewicz 	return bdev->md_len;
77698da718SArtur Paszkiewicz }
78698da718SArtur Paszkiewicz 
79698da718SArtur Paszkiewicz uint32_t
spdk_bdev_get_block_size(const struct spdk_bdev * bdev)80698da718SArtur Paszkiewicz spdk_bdev_get_block_size(const struct spdk_bdev *bdev)
81698da718SArtur Paszkiewicz {
82698da718SArtur Paszkiewicz 	return bdev->blocklen;
83698da718SArtur Paszkiewicz }
84698da718SArtur Paszkiewicz 
85698da718SArtur Paszkiewicz static int
set_test_opts(void)86698da718SArtur Paszkiewicz set_test_opts(void)
87698da718SArtur Paszkiewicz {
88698da718SArtur Paszkiewicz 	g_max_base_drives = MAX_BASE_DRIVES;
89698da718SArtur Paszkiewicz 	g_block_len = 4096;
90698da718SArtur Paszkiewicz 	g_strip_size = 64;
91698da718SArtur Paszkiewicz 	g_max_io_size = 1024;
92698da718SArtur Paszkiewicz 	g_enable_dif = false;
93698da718SArtur Paszkiewicz 
94698da718SArtur Paszkiewicz 	return 0;
95698da718SArtur Paszkiewicz }
96698da718SArtur Paszkiewicz 
97698da718SArtur Paszkiewicz static int
set_test_opts_dif(void)98698da718SArtur Paszkiewicz set_test_opts_dif(void)
99698da718SArtur Paszkiewicz {
100698da718SArtur Paszkiewicz 	set_test_opts();
101698da718SArtur Paszkiewicz 	g_enable_dif = true;
102698da718SArtur Paszkiewicz 
103698da718SArtur Paszkiewicz 	return 0;
104698da718SArtur Paszkiewicz }
105698da718SArtur Paszkiewicz 
106698da718SArtur Paszkiewicz /* Set globals before every test run */
107698da718SArtur Paszkiewicz static void
set_globals(void)108698da718SArtur Paszkiewicz set_globals(void)
109698da718SArtur Paszkiewicz {
110698da718SArtur Paszkiewicz 	uint32_t max_splits;
111698da718SArtur Paszkiewicz 
112698da718SArtur Paszkiewicz 	if (g_max_io_size < g_strip_size) {
113698da718SArtur Paszkiewicz 		max_splits = 2;
114698da718SArtur Paszkiewicz 	} else {
115698da718SArtur Paszkiewicz 		max_splits = (g_max_io_size / g_strip_size) + 1;
116698da718SArtur Paszkiewicz 	}
117698da718SArtur Paszkiewicz 	if (max_splits < g_max_base_drives) {
118698da718SArtur Paszkiewicz 		max_splits = g_max_base_drives;
119698da718SArtur Paszkiewicz 	}
120698da718SArtur Paszkiewicz 
121698da718SArtur Paszkiewicz 	g_io_output = calloc(max_splits, sizeof(struct io_output));
122698da718SArtur Paszkiewicz 	SPDK_CU_ASSERT_FATAL(g_io_output != NULL);
123698da718SArtur Paszkiewicz 	g_io_output_index = 0;
124698da718SArtur Paszkiewicz 	g_io_comp_status = 0;
125698da718SArtur Paszkiewicz 	g_child_io_status_flag = true;
126698da718SArtur Paszkiewicz }
127698da718SArtur Paszkiewicz 
128698da718SArtur Paszkiewicz /* Reset globals */
129698da718SArtur Paszkiewicz static void
reset_globals(void)130698da718SArtur Paszkiewicz reset_globals(void)
131698da718SArtur Paszkiewicz {
132698da718SArtur Paszkiewicz 	if (g_io_output) {
133698da718SArtur Paszkiewicz 		free(g_io_output);
134698da718SArtur Paszkiewicz 		g_io_output = NULL;
135698da718SArtur Paszkiewicz 	}
136698da718SArtur Paszkiewicz }
137698da718SArtur Paszkiewicz 
138698da718SArtur Paszkiewicz static void
generate_dif(struct iovec * iovs,int iovcnt,void * md_buf,uint64_t offset_blocks,uint32_t num_blocks,struct spdk_bdev * bdev)139698da718SArtur Paszkiewicz generate_dif(struct iovec *iovs, int iovcnt, void *md_buf,
140698da718SArtur Paszkiewicz 	     uint64_t offset_blocks, uint32_t num_blocks, struct spdk_bdev *bdev)
141698da718SArtur Paszkiewicz {
142698da718SArtur Paszkiewicz 	struct spdk_dif_ctx dif_ctx;
143698da718SArtur Paszkiewicz 	int rc;
144698da718SArtur Paszkiewicz 	struct spdk_dif_ctx_init_ext_opts dif_opts;
145698da718SArtur Paszkiewicz 	spdk_dif_type_t dif_type;
146698da718SArtur Paszkiewicz 	bool md_interleaved;
147698da718SArtur Paszkiewicz 	struct iovec md_iov;
148698da718SArtur Paszkiewicz 
149698da718SArtur Paszkiewicz 	dif_type = spdk_bdev_get_dif_type(bdev);
150698da718SArtur Paszkiewicz 	md_interleaved = spdk_bdev_is_md_interleaved(bdev);
151698da718SArtur Paszkiewicz 
152698da718SArtur Paszkiewicz 	if (dif_type == SPDK_DIF_DISABLE) {
153698da718SArtur Paszkiewicz 		return;
154698da718SArtur Paszkiewicz 	}
155698da718SArtur Paszkiewicz 
156698da718SArtur Paszkiewicz 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
157698da718SArtur Paszkiewicz 	dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16;
158698da718SArtur Paszkiewicz 	rc = spdk_dif_ctx_init(&dif_ctx,
159698da718SArtur Paszkiewicz 			       spdk_bdev_get_block_size(bdev),
160698da718SArtur Paszkiewicz 			       spdk_bdev_get_md_size(bdev),
161698da718SArtur Paszkiewicz 			       md_interleaved,
162698da718SArtur Paszkiewicz 			       spdk_bdev_is_dif_head_of_md(bdev),
163698da718SArtur Paszkiewicz 			       dif_type,
164698da718SArtur Paszkiewicz 			       bdev->dif_check_flags,
165698da718SArtur Paszkiewicz 			       offset_blocks,
166698da718SArtur Paszkiewicz 			       0xFFFF, 0x123, 0, 0, &dif_opts);
167698da718SArtur Paszkiewicz 	SPDK_CU_ASSERT_FATAL(rc == 0);
168698da718SArtur Paszkiewicz 
169698da718SArtur Paszkiewicz 	if (!md_interleaved) {
170698da718SArtur Paszkiewicz 		md_iov.iov_base = md_buf;
171698da718SArtur Paszkiewicz 		md_iov.iov_len	= spdk_bdev_get_md_size(bdev) * num_blocks;
172698da718SArtur Paszkiewicz 
173698da718SArtur Paszkiewicz 		rc = spdk_dix_generate(iovs, iovcnt, &md_iov, num_blocks, &dif_ctx);
174698da718SArtur Paszkiewicz 		SPDK_CU_ASSERT_FATAL(rc == 0);
175698da718SArtur Paszkiewicz 	}
176698da718SArtur Paszkiewicz }
177698da718SArtur Paszkiewicz 
178698da718SArtur Paszkiewicz static void
verify_dif(struct iovec * iovs,int iovcnt,void * md_buf,uint64_t offset_blocks,uint32_t num_blocks,struct spdk_bdev * bdev)179698da718SArtur Paszkiewicz verify_dif(struct iovec *iovs, int iovcnt, void *md_buf,
180698da718SArtur Paszkiewicz 	   uint64_t offset_blocks, uint32_t num_blocks, struct spdk_bdev *bdev)
181698da718SArtur Paszkiewicz {
182698da718SArtur Paszkiewicz 	struct spdk_dif_ctx dif_ctx;
183698da718SArtur Paszkiewicz 	int rc;
184698da718SArtur Paszkiewicz 	struct spdk_dif_ctx_init_ext_opts dif_opts;
185698da718SArtur Paszkiewicz 	struct spdk_dif_error errblk;
186698da718SArtur Paszkiewicz 	spdk_dif_type_t dif_type;
187698da718SArtur Paszkiewicz 	bool md_interleaved;
188698da718SArtur Paszkiewicz 	struct iovec md_iov;
189698da718SArtur Paszkiewicz 
190698da718SArtur Paszkiewicz 	dif_type = spdk_bdev_get_dif_type(bdev);
191698da718SArtur Paszkiewicz 	md_interleaved = spdk_bdev_is_md_interleaved(bdev);
192698da718SArtur Paszkiewicz 
193698da718SArtur Paszkiewicz 	if (dif_type == SPDK_DIF_DISABLE) {
194698da718SArtur Paszkiewicz 		return;
195698da718SArtur Paszkiewicz 	}
196698da718SArtur Paszkiewicz 
197698da718SArtur Paszkiewicz 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
198698da718SArtur Paszkiewicz 	dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16;
199698da718SArtur Paszkiewicz 	rc = spdk_dif_ctx_init(&dif_ctx,
200698da718SArtur Paszkiewicz 			       spdk_bdev_get_block_size(bdev),
201698da718SArtur Paszkiewicz 			       spdk_bdev_get_md_size(bdev),
202698da718SArtur Paszkiewicz 			       md_interleaved,
203698da718SArtur Paszkiewicz 			       spdk_bdev_is_dif_head_of_md(bdev),
204698da718SArtur Paszkiewicz 			       dif_type,
205698da718SArtur Paszkiewicz 			       bdev->dif_check_flags,
206698da718SArtur Paszkiewicz 			       offset_blocks,
207698da718SArtur Paszkiewicz 			       0xFFFF, 0x123, 0, 0, &dif_opts);
208698da718SArtur Paszkiewicz 	SPDK_CU_ASSERT_FATAL(rc == 0);
209698da718SArtur Paszkiewicz 
210698da718SArtur Paszkiewicz 	if (!md_interleaved) {
211698da718SArtur Paszkiewicz 		md_iov.iov_base = md_buf;
212698da718SArtur Paszkiewicz 		md_iov.iov_len	= spdk_bdev_get_md_size(bdev) * num_blocks;
213698da718SArtur Paszkiewicz 
214698da718SArtur Paszkiewicz 		rc = spdk_dix_verify(iovs, iovcnt,
215698da718SArtur Paszkiewicz 				     &md_iov, num_blocks, &dif_ctx, &errblk);
216698da718SArtur Paszkiewicz 		SPDK_CU_ASSERT_FATAL(rc == 0);
217698da718SArtur Paszkiewicz 	}
218698da718SArtur Paszkiewicz }
219698da718SArtur Paszkiewicz 
220698da718SArtur Paszkiewicz static void
remap_dif(void * md_buf,uint64_t num_blocks,struct spdk_bdev * bdev,uint32_t remapped_offset)221698da718SArtur Paszkiewicz remap_dif(void *md_buf, uint64_t num_blocks, struct spdk_bdev *bdev, uint32_t remapped_offset)
222698da718SArtur Paszkiewicz {
223698da718SArtur Paszkiewicz 	struct spdk_dif_ctx dif_ctx;
224698da718SArtur Paszkiewicz 	int rc;
225698da718SArtur Paszkiewicz 	struct spdk_dif_ctx_init_ext_opts dif_opts;
226698da718SArtur Paszkiewicz 	struct spdk_dif_error errblk;
227698da718SArtur Paszkiewicz 	spdk_dif_type_t dif_type;
228698da718SArtur Paszkiewicz 	bool md_interleaved;
229698da718SArtur Paszkiewicz 	struct iovec md_iov;
230698da718SArtur Paszkiewicz 
231698da718SArtur Paszkiewicz 	dif_type = spdk_bdev_get_dif_type(bdev);
232698da718SArtur Paszkiewicz 	md_interleaved = spdk_bdev_is_md_interleaved(bdev);
233698da718SArtur Paszkiewicz 
234698da718SArtur Paszkiewicz 	if (dif_type == SPDK_DIF_DISABLE) {
235698da718SArtur Paszkiewicz 		return;
236698da718SArtur Paszkiewicz 	}
237698da718SArtur Paszkiewicz 
238698da718SArtur Paszkiewicz 	dif_opts.size = SPDK_SIZEOF(&dif_opts, dif_pi_format);
239698da718SArtur Paszkiewicz 	dif_opts.dif_pi_format = SPDK_DIF_PI_FORMAT_16;
240698da718SArtur Paszkiewicz 	rc = spdk_dif_ctx_init(&dif_ctx,
241698da718SArtur Paszkiewicz 			       spdk_bdev_get_block_size(bdev),
242698da718SArtur Paszkiewicz 			       spdk_bdev_get_md_size(bdev),
243698da718SArtur Paszkiewicz 			       md_interleaved,
244698da718SArtur Paszkiewicz 			       spdk_bdev_is_dif_head_of_md(bdev),
245698da718SArtur Paszkiewicz 			       dif_type,
246698da718SArtur Paszkiewicz 			       bdev->dif_check_flags,
247698da718SArtur Paszkiewicz 			       0,
248698da718SArtur Paszkiewicz 			       0xFFFF, 0x123, 0, 0, &dif_opts);
249698da718SArtur Paszkiewicz 	SPDK_CU_ASSERT_FATAL(rc == 0);
250698da718SArtur Paszkiewicz 
251698da718SArtur Paszkiewicz 	if (!md_interleaved) {
252698da718SArtur Paszkiewicz 		md_iov.iov_base = md_buf;
253698da718SArtur Paszkiewicz 		md_iov.iov_len	= spdk_bdev_get_md_size(bdev) * num_blocks;
254698da718SArtur Paszkiewicz 
255698da718SArtur Paszkiewicz 		spdk_dif_ctx_set_remapped_init_ref_tag(&dif_ctx, remapped_offset);
256698da718SArtur Paszkiewicz 
257698da718SArtur Paszkiewicz 		rc = spdk_dix_remap_ref_tag(&md_iov, num_blocks, &dif_ctx, &errblk, false);
258698da718SArtur Paszkiewicz 		SPDK_CU_ASSERT_FATAL(rc == 0);
259698da718SArtur Paszkiewicz 	}
260698da718SArtur Paszkiewicz }
261698da718SArtur Paszkiewicz 
262698da718SArtur Paszkiewicz /* Store the IO completion status in global variable to verify by various tests */
263698da718SArtur Paszkiewicz void
raid_test_bdev_io_complete(struct raid_bdev_io * raid_io,enum spdk_bdev_io_status status)264698da718SArtur Paszkiewicz raid_test_bdev_io_complete(struct raid_bdev_io *raid_io, enum spdk_bdev_io_status status)
265698da718SArtur Paszkiewicz {
266698da718SArtur Paszkiewicz 	g_io_comp_status = ((status == SPDK_BDEV_IO_STATUS_SUCCESS) ? true : false);
267698da718SArtur Paszkiewicz }
268698da718SArtur Paszkiewicz 
269698da718SArtur Paszkiewicz int
raid_bdev_remap_dix_reftag(void * md_buf,uint64_t num_blocks,struct spdk_bdev * bdev,uint32_t remapped_offset)270*1b9c5629SArtur Paszkiewicz raid_bdev_remap_dix_reftag(void *md_buf, uint64_t num_blocks,
271*1b9c5629SArtur Paszkiewicz 			   struct spdk_bdev *bdev, uint32_t remapped_offset)
272*1b9c5629SArtur Paszkiewicz {
273*1b9c5629SArtur Paszkiewicz 	remap_dif(md_buf, num_blocks, bdev, remapped_offset);
274*1b9c5629SArtur Paszkiewicz 
275*1b9c5629SArtur Paszkiewicz 	return 0;
276*1b9c5629SArtur Paszkiewicz }
277*1b9c5629SArtur Paszkiewicz 
278*1b9c5629SArtur Paszkiewicz int
raid_bdev_verify_dix_reftag(struct iovec * iovs,int iovcnt,void * md_buf,uint64_t num_blocks,struct spdk_bdev * bdev,uint32_t offset_blocks)279698da718SArtur Paszkiewicz raid_bdev_verify_dix_reftag(struct iovec *iovs, int iovcnt, void *md_buf,
280698da718SArtur Paszkiewicz 			    uint64_t num_blocks, struct spdk_bdev *bdev, uint32_t offset_blocks)
281698da718SArtur Paszkiewicz {
282698da718SArtur Paszkiewicz 	verify_dif(iovs, iovcnt, md_buf, offset_blocks, num_blocks, bdev);
283698da718SArtur Paszkiewicz 
284698da718SArtur Paszkiewicz 	return 0;
285698da718SArtur Paszkiewicz }
286698da718SArtur Paszkiewicz 
287698da718SArtur Paszkiewicz static void
set_io_output(struct io_output * output,struct spdk_bdev_desc * desc,struct spdk_io_channel * ch,uint64_t offset_blocks,uint64_t num_blocks,spdk_bdev_io_completion_cb cb,void * cb_arg,enum spdk_bdev_io_type iotype,struct iovec * iovs,int iovcnt,void * md)288698da718SArtur Paszkiewicz set_io_output(struct io_output *output,
289698da718SArtur Paszkiewicz 	      struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
290698da718SArtur Paszkiewicz 	      uint64_t offset_blocks, uint64_t num_blocks,
291698da718SArtur Paszkiewicz 	      spdk_bdev_io_completion_cb cb, void *cb_arg,
292698da718SArtur Paszkiewicz 	      enum spdk_bdev_io_type iotype, struct iovec *iovs,
293698da718SArtur Paszkiewicz 	      int iovcnt, void *md)
294698da718SArtur Paszkiewicz {
295698da718SArtur Paszkiewicz 	output->desc = desc;
296698da718SArtur Paszkiewicz 	output->ch = ch;
297698da718SArtur Paszkiewicz 	output->offset_blocks = offset_blocks;
298698da718SArtur Paszkiewicz 	output->num_blocks = num_blocks;
299698da718SArtur Paszkiewicz 	output->cb = cb;
300698da718SArtur Paszkiewicz 	output->cb_arg = cb_arg;
301698da718SArtur Paszkiewicz 	output->iotype = iotype;
302698da718SArtur Paszkiewicz 	output->iovs = iovs;
303698da718SArtur Paszkiewicz 	output->iovcnt = iovcnt;
304698da718SArtur Paszkiewicz 	output->md_buf = md;
305698da718SArtur Paszkiewicz }
306698da718SArtur Paszkiewicz 
307698da718SArtur Paszkiewicz static struct spdk_bdev_io *
get_child_io(struct io_output * output)308698da718SArtur Paszkiewicz get_child_io(struct io_output *output)
309698da718SArtur Paszkiewicz {
310698da718SArtur Paszkiewicz 	struct spdk_bdev_io *bdev_io;
311698da718SArtur Paszkiewicz 
312698da718SArtur Paszkiewicz 	bdev_io = calloc(1, sizeof(*bdev_io));
313698da718SArtur Paszkiewicz 	SPDK_CU_ASSERT_FATAL(bdev_io != NULL);
314698da718SArtur Paszkiewicz 
315698da718SArtur Paszkiewicz 	bdev_io->bdev = spdk_bdev_desc_get_bdev(output->desc);
316698da718SArtur Paszkiewicz 	bdev_io->type = output->iotype;
317698da718SArtur Paszkiewicz 	bdev_io->u.bdev.offset_blocks = output->offset_blocks;
318698da718SArtur Paszkiewicz 	bdev_io->u.bdev.num_blocks = output->num_blocks;
319698da718SArtur Paszkiewicz 	bdev_io->u.bdev.iovs = output->iovs;
320698da718SArtur Paszkiewicz 	bdev_io->u.bdev.iovcnt = output->iovcnt;
321698da718SArtur Paszkiewicz 	bdev_io->u.bdev.md_buf = output->md_buf;
322698da718SArtur Paszkiewicz 
323698da718SArtur Paszkiewicz 	return bdev_io;
324698da718SArtur Paszkiewicz }
325698da718SArtur Paszkiewicz 
326698da718SArtur Paszkiewicz static void
child_io_complete(struct spdk_bdev_io * bdev_io,spdk_bdev_io_completion_cb cb,void * cb_arg)327698da718SArtur Paszkiewicz child_io_complete(struct spdk_bdev_io *bdev_io, spdk_bdev_io_completion_cb cb, void *cb_arg)
328698da718SArtur Paszkiewicz {
329698da718SArtur Paszkiewicz 	if (g_child_io_status_flag && bdev_io->type == SPDK_BDEV_IO_TYPE_READ) {
330698da718SArtur Paszkiewicz 		verify_dif(bdev_io->u.bdev.iovs, bdev_io->u.bdev.iovcnt, bdev_io->u.bdev.md_buf,
331698da718SArtur Paszkiewicz 			   bdev_io->u.bdev.offset_blocks, bdev_io->u.bdev.num_blocks, bdev_io->bdev);
332698da718SArtur Paszkiewicz 	}
333698da718SArtur Paszkiewicz 
334698da718SArtur Paszkiewicz 	cb(bdev_io, g_child_io_status_flag, cb_arg);
335698da718SArtur Paszkiewicz }
336698da718SArtur Paszkiewicz 
337698da718SArtur Paszkiewicz int
spdk_bdev_writev_blocks_ext(struct spdk_bdev_desc * desc,struct spdk_io_channel * ch,struct iovec * iov,int iovcnt,uint64_t offset_blocks,uint64_t num_blocks,spdk_bdev_io_completion_cb cb,void * cb_arg,struct spdk_bdev_ext_io_opts * opts)338698da718SArtur Paszkiewicz spdk_bdev_writev_blocks_ext(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
339698da718SArtur Paszkiewicz 			    struct iovec *iov, int iovcnt,
340698da718SArtur Paszkiewicz 			    uint64_t offset_blocks, uint64_t num_blocks,
341698da718SArtur Paszkiewicz 			    spdk_bdev_io_completion_cb cb, void *cb_arg,
342698da718SArtur Paszkiewicz 			    struct spdk_bdev_ext_io_opts *opts)
343698da718SArtur Paszkiewicz {
344698da718SArtur Paszkiewicz 	struct io_output *output = &g_io_output[g_io_output_index];
345698da718SArtur Paszkiewicz 	struct spdk_bdev_io *child_io;
346698da718SArtur Paszkiewicz 
347698da718SArtur Paszkiewicz 	if (g_max_io_size < g_strip_size) {
348698da718SArtur Paszkiewicz 		SPDK_CU_ASSERT_FATAL(g_io_output_index < 2);
349698da718SArtur Paszkiewicz 	} else {
350698da718SArtur Paszkiewicz 		SPDK_CU_ASSERT_FATAL(g_io_output_index < (g_max_io_size / g_strip_size) + 1);
351698da718SArtur Paszkiewicz 	}
352698da718SArtur Paszkiewicz 	set_io_output(output, desc, ch, offset_blocks, num_blocks, cb, cb_arg,
353698da718SArtur Paszkiewicz 		      SPDK_BDEV_IO_TYPE_WRITE, iov, iovcnt, opts->metadata);
354698da718SArtur Paszkiewicz 	g_io_output_index++;
355698da718SArtur Paszkiewicz 
356698da718SArtur Paszkiewicz 	child_io = get_child_io(output);
357698da718SArtur Paszkiewicz 	child_io_complete(child_io, cb, cb_arg);
358698da718SArtur Paszkiewicz 
359698da718SArtur Paszkiewicz 	return 0;
360698da718SArtur Paszkiewicz }
361698da718SArtur Paszkiewicz 
362698da718SArtur Paszkiewicz int
spdk_bdev_unmap_blocks(struct spdk_bdev_desc * desc,struct spdk_io_channel * ch,uint64_t offset_blocks,uint64_t num_blocks,spdk_bdev_io_completion_cb cb,void * cb_arg)363698da718SArtur Paszkiewicz spdk_bdev_unmap_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
364698da718SArtur Paszkiewicz 		       uint64_t offset_blocks, uint64_t num_blocks,
365698da718SArtur Paszkiewicz 		       spdk_bdev_io_completion_cb cb, void *cb_arg)
366698da718SArtur Paszkiewicz {
367698da718SArtur Paszkiewicz 	struct io_output *output = &g_io_output[g_io_output_index];
368698da718SArtur Paszkiewicz 	struct spdk_bdev_io *child_io;
369698da718SArtur Paszkiewicz 
370698da718SArtur Paszkiewicz 	set_io_output(output, desc, ch, offset_blocks, num_blocks, cb, cb_arg,
371698da718SArtur Paszkiewicz 		      SPDK_BDEV_IO_TYPE_UNMAP, NULL, 0, NULL);
372698da718SArtur Paszkiewicz 	g_io_output_index++;
373698da718SArtur Paszkiewicz 
374698da718SArtur Paszkiewicz 	child_io = get_child_io(output);
375698da718SArtur Paszkiewicz 	child_io_complete(child_io, cb, cb_arg);
376698da718SArtur Paszkiewicz 
377698da718SArtur Paszkiewicz 	return 0;
378698da718SArtur Paszkiewicz }
379698da718SArtur Paszkiewicz 
380698da718SArtur Paszkiewicz void
spdk_bdev_free_io(struct spdk_bdev_io * bdev_io)381698da718SArtur Paszkiewicz spdk_bdev_free_io(struct spdk_bdev_io *bdev_io)
382698da718SArtur Paszkiewicz {
383698da718SArtur Paszkiewicz 	if (bdev_io) {
384698da718SArtur Paszkiewicz 		free(bdev_io);
385698da718SArtur Paszkiewicz 	}
386698da718SArtur Paszkiewicz }
387698da718SArtur Paszkiewicz 
388698da718SArtur Paszkiewicz int
spdk_bdev_readv_blocks_ext(struct spdk_bdev_desc * desc,struct spdk_io_channel * ch,struct iovec * iov,int iovcnt,uint64_t offset_blocks,uint64_t num_blocks,spdk_bdev_io_completion_cb cb,void * cb_arg,struct spdk_bdev_ext_io_opts * opts)389698da718SArtur Paszkiewicz spdk_bdev_readv_blocks_ext(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
390698da718SArtur Paszkiewicz 			   struct iovec *iov, int iovcnt,
391698da718SArtur Paszkiewicz 			   uint64_t offset_blocks, uint64_t num_blocks,
392698da718SArtur Paszkiewicz 			   spdk_bdev_io_completion_cb cb, void *cb_arg,
393698da718SArtur Paszkiewicz 			   struct spdk_bdev_ext_io_opts *opts)
394698da718SArtur Paszkiewicz {
395698da718SArtur Paszkiewicz 	struct io_output *output = &g_io_output[g_io_output_index];
396698da718SArtur Paszkiewicz 	struct spdk_bdev_io *child_io;
397698da718SArtur Paszkiewicz 
398698da718SArtur Paszkiewicz 	SPDK_CU_ASSERT_FATAL(g_io_output_index <= (g_max_io_size / g_strip_size) + 1);
399698da718SArtur Paszkiewicz 	set_io_output(output, desc, ch, offset_blocks, num_blocks, cb, cb_arg,
400698da718SArtur Paszkiewicz 		      SPDK_BDEV_IO_TYPE_READ, iov, iovcnt, opts->metadata);
401698da718SArtur Paszkiewicz 	generate_dif(iov, iovcnt, opts->metadata, offset_blocks, num_blocks,
402698da718SArtur Paszkiewicz 		     spdk_bdev_desc_get_bdev(desc));
403698da718SArtur Paszkiewicz 	g_io_output_index++;
404698da718SArtur Paszkiewicz 
405698da718SArtur Paszkiewicz 	child_io = get_child_io(output);
406698da718SArtur Paszkiewicz 	child_io_complete(child_io, cb, cb_arg);
407698da718SArtur Paszkiewicz 
408698da718SArtur Paszkiewicz 	return 0;
409698da718SArtur Paszkiewicz }
410698da718SArtur Paszkiewicz 
411698da718SArtur Paszkiewicz static void
raid_io_cleanup(struct raid_bdev_io * raid_io)412698da718SArtur Paszkiewicz raid_io_cleanup(struct raid_bdev_io *raid_io)
413698da718SArtur Paszkiewicz {
414698da718SArtur Paszkiewicz 	if (raid_io->iovs) {
415698da718SArtur Paszkiewicz 		int i;
416698da718SArtur Paszkiewicz 
417698da718SArtur Paszkiewicz 		for (i = 0; i < raid_io->iovcnt; i++) {
418698da718SArtur Paszkiewicz 			free(raid_io->iovs[i].iov_base);
419698da718SArtur Paszkiewicz 		}
420698da718SArtur Paszkiewicz 		free(raid_io->iovs);
421698da718SArtur Paszkiewicz 	}
422698da718SArtur Paszkiewicz 
423698da718SArtur Paszkiewicz 	free(raid_io->md_buf);
424698da718SArtur Paszkiewicz 	free(raid_io);
425698da718SArtur Paszkiewicz }
426698da718SArtur Paszkiewicz 
427698da718SArtur Paszkiewicz static void
raid_io_initialize(struct raid_bdev_io * raid_io,struct raid_bdev_io_channel * raid_ch,struct raid_bdev * raid_bdev,uint64_t lba,uint64_t blocks,int16_t iotype)428698da718SArtur Paszkiewicz raid_io_initialize(struct raid_bdev_io *raid_io, struct raid_bdev_io_channel *raid_ch,
429698da718SArtur Paszkiewicz 		   struct raid_bdev *raid_bdev, uint64_t lba, uint64_t blocks, int16_t iotype)
430698da718SArtur Paszkiewicz {
431698da718SArtur Paszkiewicz 	struct iovec *iovs = NULL;
432698da718SArtur Paszkiewicz 	int iovcnt = 0;
433698da718SArtur Paszkiewicz 	void *md_buf = NULL;
434698da718SArtur Paszkiewicz 
435698da718SArtur Paszkiewicz 	if (iotype != SPDK_BDEV_IO_TYPE_UNMAP && iotype != SPDK_BDEV_IO_TYPE_FLUSH) {
436698da718SArtur Paszkiewicz 		iovcnt = 1;
437698da718SArtur Paszkiewicz 		iovs = calloc(iovcnt, sizeof(struct iovec));
438698da718SArtur Paszkiewicz 		SPDK_CU_ASSERT_FATAL(iovs != NULL);
439698da718SArtur Paszkiewicz 		iovs->iov_len = blocks * g_block_len;
440698da718SArtur Paszkiewicz 		iovs->iov_base = calloc(1, iovs->iov_len);
441698da718SArtur Paszkiewicz 		SPDK_CU_ASSERT_FATAL(iovs->iov_base != NULL);
442698da718SArtur Paszkiewicz 
443698da718SArtur Paszkiewicz 		if (spdk_bdev_is_md_separate(&raid_bdev->bdev)) {
444698da718SArtur Paszkiewicz 			md_buf = calloc(1, blocks * spdk_bdev_get_md_size(&raid_bdev->bdev));
445698da718SArtur Paszkiewicz 			SPDK_CU_ASSERT_FATAL(md_buf != NULL);
446698da718SArtur Paszkiewicz 		}
447698da718SArtur Paszkiewicz 	}
448698da718SArtur Paszkiewicz 
449698da718SArtur Paszkiewicz 	raid_test_bdev_io_init(raid_io, raid_bdev, raid_ch, iotype, lba, blocks, iovs, iovcnt, md_buf);
450698da718SArtur Paszkiewicz }
451698da718SArtur Paszkiewicz 
452698da718SArtur Paszkiewicz static void
verify_io(struct raid_bdev_io * raid_io,uint32_t io_status)453698da718SArtur Paszkiewicz verify_io(struct raid_bdev_io *raid_io, uint32_t io_status)
454698da718SArtur Paszkiewicz {
455698da718SArtur Paszkiewicz 	struct raid_bdev *raid_bdev = raid_io->raid_bdev;
456698da718SArtur Paszkiewicz 	uint8_t num_base_drives = raid_bdev->num_base_bdevs;
457698da718SArtur Paszkiewicz 	uint32_t strip_shift = spdk_u32log2(g_strip_size);
458698da718SArtur Paszkiewicz 	uint64_t start_strip = raid_io->offset_blocks >> strip_shift;
459698da718SArtur Paszkiewicz 	uint64_t end_strip = (raid_io->offset_blocks + raid_io->num_blocks - 1) >>
460698da718SArtur Paszkiewicz 			     strip_shift;
461698da718SArtur Paszkiewicz 	uint32_t splits_reqd = (end_strip - start_strip + 1);
462698da718SArtur Paszkiewicz 	uint32_t strip;
463698da718SArtur Paszkiewicz 	uint64_t pd_strip;
464698da718SArtur Paszkiewicz 	uint8_t pd_idx;
465698da718SArtur Paszkiewicz 	uint32_t offset_in_strip;
466698da718SArtur Paszkiewicz 	uint64_t pd_lba;
467698da718SArtur Paszkiewicz 	uint64_t pd_blocks;
468698da718SArtur Paszkiewicz 	uint32_t index = 0;
469698da718SArtur Paszkiewicz 	struct io_output *output;
470698da718SArtur Paszkiewicz 
471698da718SArtur Paszkiewicz 	SPDK_CU_ASSERT_FATAL(raid_bdev != NULL);
472698da718SArtur Paszkiewicz 	SPDK_CU_ASSERT_FATAL(num_base_drives != 0);
473698da718SArtur Paszkiewicz 
474698da718SArtur Paszkiewicz 	CU_ASSERT(splits_reqd == g_io_output_index);
475698da718SArtur Paszkiewicz 	for (strip = start_strip; strip <= end_strip; strip++, index++) {
476698da718SArtur Paszkiewicz 		pd_strip = strip / num_base_drives;
477698da718SArtur Paszkiewicz 		pd_idx = strip % num_base_drives;
478698da718SArtur Paszkiewicz 		if (strip == start_strip) {
479698da718SArtur Paszkiewicz 			offset_in_strip = raid_io->offset_blocks & (g_strip_size - 1);
480698da718SArtur Paszkiewicz 			pd_lba = (pd_strip << strip_shift) + offset_in_strip;
481698da718SArtur Paszkiewicz 			if (strip == end_strip) {
482698da718SArtur Paszkiewicz 				pd_blocks = raid_io->num_blocks;
483698da718SArtur Paszkiewicz 			} else {
484698da718SArtur Paszkiewicz 				pd_blocks = g_strip_size - offset_in_strip;
485698da718SArtur Paszkiewicz 			}
486698da718SArtur Paszkiewicz 		} else if (strip == end_strip) {
487698da718SArtur Paszkiewicz 			pd_lba = pd_strip << strip_shift;
488698da718SArtur Paszkiewicz 			pd_blocks = ((raid_io->offset_blocks + raid_io->num_blocks - 1) &
489698da718SArtur Paszkiewicz 				     (g_strip_size - 1)) + 1;
490698da718SArtur Paszkiewicz 		} else {
491698da718SArtur Paszkiewicz 			pd_lba = pd_strip << raid_bdev->strip_size_shift;
492698da718SArtur Paszkiewicz 			pd_blocks = raid_bdev->strip_size;
493698da718SArtur Paszkiewicz 		}
494698da718SArtur Paszkiewicz 		output = &g_io_output[index];
495698da718SArtur Paszkiewicz 		CU_ASSERT(pd_lba == output->offset_blocks);
496698da718SArtur Paszkiewicz 		CU_ASSERT(pd_blocks == output->num_blocks);
497698da718SArtur Paszkiewicz 		CU_ASSERT(raid_bdev_channel_get_base_channel(raid_io->raid_ch, pd_idx) == output->ch);
498698da718SArtur Paszkiewicz 		CU_ASSERT(raid_bdev->base_bdev_info[pd_idx].desc == output->desc);
499698da718SArtur Paszkiewicz 		CU_ASSERT(raid_io->type == output->iotype);
500698da718SArtur Paszkiewicz 		if (raid_io->type == SPDK_BDEV_IO_TYPE_WRITE) {
501698da718SArtur Paszkiewicz 			verify_dif(output->iovs, output->iovcnt, output->md_buf,
502698da718SArtur Paszkiewicz 				   output->offset_blocks, output->num_blocks,
503698da718SArtur Paszkiewicz 				   spdk_bdev_desc_get_bdev(raid_bdev->base_bdev_info[pd_idx].desc));
504698da718SArtur Paszkiewicz 		}
505698da718SArtur Paszkiewicz 	}
506698da718SArtur Paszkiewicz 	CU_ASSERT(g_io_comp_status == io_status);
507698da718SArtur Paszkiewicz }
508698da718SArtur Paszkiewicz 
509698da718SArtur Paszkiewicz static void
verify_io_without_payload(struct raid_bdev_io * raid_io,uint32_t io_status)510698da718SArtur Paszkiewicz verify_io_without_payload(struct raid_bdev_io *raid_io, uint32_t io_status)
511698da718SArtur Paszkiewicz {
512698da718SArtur Paszkiewicz 	struct raid_bdev *raid_bdev = raid_io->raid_bdev;
513698da718SArtur Paszkiewicz 	uint8_t num_base_drives = raid_bdev->num_base_bdevs;
514698da718SArtur Paszkiewicz 	uint32_t strip_shift = spdk_u32log2(g_strip_size);
515698da718SArtur Paszkiewicz 	uint64_t start_offset_in_strip = raid_io->offset_blocks % g_strip_size;
516698da718SArtur Paszkiewicz 	uint64_t end_offset_in_strip = (raid_io->offset_blocks + raid_io->num_blocks - 1) %
517698da718SArtur Paszkiewicz 				       g_strip_size;
518698da718SArtur Paszkiewicz 	uint64_t start_strip = raid_io->offset_blocks >> strip_shift;
519698da718SArtur Paszkiewicz 	uint64_t end_strip = (raid_io->offset_blocks + raid_io->num_blocks - 1) >>
520698da718SArtur Paszkiewicz 			     strip_shift;
521698da718SArtur Paszkiewicz 	uint8_t n_disks_involved;
522698da718SArtur Paszkiewicz 	uint64_t start_strip_disk_idx;
523698da718SArtur Paszkiewicz 	uint64_t end_strip_disk_idx;
524698da718SArtur Paszkiewicz 	uint64_t nblocks_in_start_disk;
525698da718SArtur Paszkiewicz 	uint64_t offset_in_start_disk;
526698da718SArtur Paszkiewicz 	uint8_t disk_idx;
527698da718SArtur Paszkiewicz 	uint64_t base_io_idx;
528698da718SArtur Paszkiewicz 	uint64_t sum_nblocks = 0;
529698da718SArtur Paszkiewicz 	struct io_output *output;
530698da718SArtur Paszkiewicz 
531698da718SArtur Paszkiewicz 	SPDK_CU_ASSERT_FATAL(raid_bdev != NULL);
532698da718SArtur Paszkiewicz 	SPDK_CU_ASSERT_FATAL(num_base_drives != 0);
533698da718SArtur Paszkiewicz 	SPDK_CU_ASSERT_FATAL(raid_io->type != SPDK_BDEV_IO_TYPE_READ);
534698da718SArtur Paszkiewicz 	SPDK_CU_ASSERT_FATAL(raid_io->type != SPDK_BDEV_IO_TYPE_WRITE);
535698da718SArtur Paszkiewicz 
536698da718SArtur Paszkiewicz 	n_disks_involved = spdk_min(end_strip - start_strip + 1, num_base_drives);
537698da718SArtur Paszkiewicz 	CU_ASSERT(n_disks_involved == g_io_output_index);
538698da718SArtur Paszkiewicz 
539698da718SArtur Paszkiewicz 	start_strip_disk_idx = start_strip % num_base_drives;
540698da718SArtur Paszkiewicz 	end_strip_disk_idx = end_strip % num_base_drives;
541698da718SArtur Paszkiewicz 
542698da718SArtur Paszkiewicz 	offset_in_start_disk = g_io_output[0].offset_blocks;
543698da718SArtur Paszkiewicz 	nblocks_in_start_disk = g_io_output[0].num_blocks;
544698da718SArtur Paszkiewicz 
545698da718SArtur Paszkiewicz 	for (base_io_idx = 0, disk_idx = start_strip_disk_idx; base_io_idx < n_disks_involved;
546698da718SArtur Paszkiewicz 	     base_io_idx++, disk_idx++) {
547698da718SArtur Paszkiewicz 		uint64_t start_offset_in_disk;
548698da718SArtur Paszkiewicz 		uint64_t end_offset_in_disk;
549698da718SArtur Paszkiewicz 
550698da718SArtur Paszkiewicz 		output = &g_io_output[base_io_idx];
551698da718SArtur Paszkiewicz 
552698da718SArtur Paszkiewicz 		/* round disk_idx */
553698da718SArtur Paszkiewicz 		if (disk_idx >= num_base_drives) {
554698da718SArtur Paszkiewicz 			disk_idx %= num_base_drives;
555698da718SArtur Paszkiewicz 		}
556698da718SArtur Paszkiewicz 
557698da718SArtur Paszkiewicz 		/* start_offset_in_disk aligned in strip check:
558698da718SArtur Paszkiewicz 		 * The first base io has a same start_offset_in_strip with the whole raid io.
559698da718SArtur Paszkiewicz 		 * Other base io should have aligned start_offset_in_strip which is 0.
560698da718SArtur Paszkiewicz 		 */
561698da718SArtur Paszkiewicz 		start_offset_in_disk = output->offset_blocks;
562698da718SArtur Paszkiewicz 		if (base_io_idx == 0) {
563698da718SArtur Paszkiewicz 			CU_ASSERT(start_offset_in_disk % g_strip_size == start_offset_in_strip);
564698da718SArtur Paszkiewicz 		} else {
565698da718SArtur Paszkiewicz 			CU_ASSERT(start_offset_in_disk % g_strip_size == 0);
566698da718SArtur Paszkiewicz 		}
567698da718SArtur Paszkiewicz 
568698da718SArtur Paszkiewicz 		/* end_offset_in_disk aligned in strip check:
569698da718SArtur Paszkiewicz 		 * Base io on disk at which end_strip is located, has a same end_offset_in_strip
570698da718SArtur Paszkiewicz 		 * with the whole raid io.
571698da718SArtur Paszkiewicz 		 * Other base io should have aligned end_offset_in_strip.
572698da718SArtur Paszkiewicz 		 */
573698da718SArtur Paszkiewicz 		end_offset_in_disk = output->offset_blocks + output->num_blocks - 1;
574698da718SArtur Paszkiewicz 		if (disk_idx == end_strip_disk_idx) {
575698da718SArtur Paszkiewicz 			CU_ASSERT(end_offset_in_disk % g_strip_size == end_offset_in_strip);
576698da718SArtur Paszkiewicz 		} else {
577698da718SArtur Paszkiewicz 			CU_ASSERT(end_offset_in_disk % g_strip_size == g_strip_size - 1);
578698da718SArtur Paszkiewicz 		}
579698da718SArtur Paszkiewicz 
580698da718SArtur Paszkiewicz 		/* start_offset_in_disk compared with start_disk.
581698da718SArtur Paszkiewicz 		 * 1. For disk_idx which is larger than start_strip_disk_idx: Its start_offset_in_disk
582698da718SArtur Paszkiewicz 		 *    mustn't be larger than the start offset of start_offset_in_disk; And the gap
583698da718SArtur Paszkiewicz 		 *    must be less than strip size.
584698da718SArtur Paszkiewicz 		 * 2. For disk_idx which is less than start_strip_disk_idx, Its start_offset_in_disk
585698da718SArtur Paszkiewicz 		 *    must be larger than the start offset of start_offset_in_disk; And the gap mustn't
586698da718SArtur Paszkiewicz 		 *    be less than strip size.
587698da718SArtur Paszkiewicz 		 */
588698da718SArtur Paszkiewicz 		if (disk_idx > start_strip_disk_idx) {
589698da718SArtur Paszkiewicz 			CU_ASSERT(start_offset_in_disk <= offset_in_start_disk);
590698da718SArtur Paszkiewicz 			CU_ASSERT(offset_in_start_disk - start_offset_in_disk < g_strip_size);
591698da718SArtur Paszkiewicz 		} else if (disk_idx < start_strip_disk_idx) {
592698da718SArtur Paszkiewicz 			CU_ASSERT(start_offset_in_disk > offset_in_start_disk);
593698da718SArtur Paszkiewicz 			CU_ASSERT(output->offset_blocks - offset_in_start_disk <= g_strip_size);
594698da718SArtur Paszkiewicz 		}
595698da718SArtur Paszkiewicz 
596698da718SArtur Paszkiewicz 		/* nblocks compared with start_disk:
597698da718SArtur Paszkiewicz 		 * The gap between them must be within a strip size.
598698da718SArtur Paszkiewicz 		 */
599698da718SArtur Paszkiewicz 		if (output->num_blocks <= nblocks_in_start_disk) {
600698da718SArtur Paszkiewicz 			CU_ASSERT(nblocks_in_start_disk - output->num_blocks <= g_strip_size);
601698da718SArtur Paszkiewicz 		} else {
602698da718SArtur Paszkiewicz 			CU_ASSERT(output->num_blocks - nblocks_in_start_disk < g_strip_size);
603698da718SArtur Paszkiewicz 		}
604698da718SArtur Paszkiewicz 
605698da718SArtur Paszkiewicz 		sum_nblocks += output->num_blocks;
606698da718SArtur Paszkiewicz 
607698da718SArtur Paszkiewicz 		CU_ASSERT(raid_bdev_channel_get_base_channel(raid_io->raid_ch, disk_idx) == output->ch);
608698da718SArtur Paszkiewicz 		CU_ASSERT(raid_bdev->base_bdev_info[disk_idx].desc == output->desc);
609698da718SArtur Paszkiewicz 		CU_ASSERT(raid_io->type == output->iotype);
610698da718SArtur Paszkiewicz 	}
611698da718SArtur Paszkiewicz 
612698da718SArtur Paszkiewicz 	/* Sum of each nblocks should be same with raid bdev_io */
613698da718SArtur Paszkiewicz 	CU_ASSERT(raid_io->num_blocks == sum_nblocks);
614698da718SArtur Paszkiewicz 
615698da718SArtur Paszkiewicz 	CU_ASSERT(g_io_comp_status == io_status);
616698da718SArtur Paszkiewicz }
617698da718SArtur Paszkiewicz 
618698da718SArtur Paszkiewicz static struct raid_bdev *
create_raid0(void)619698da718SArtur Paszkiewicz create_raid0(void)
620698da718SArtur Paszkiewicz {
621698da718SArtur Paszkiewicz 	struct raid_bdev *raid_bdev;
622698da718SArtur Paszkiewicz 	struct raid_base_bdev_info *base_info;
623698da718SArtur Paszkiewicz 	struct raid_params params = {
624698da718SArtur Paszkiewicz 		.num_base_bdevs = g_max_base_drives,
625698da718SArtur Paszkiewicz 		.base_bdev_blockcnt = BLOCK_CNT,
626698da718SArtur Paszkiewicz 		.base_bdev_blocklen = g_block_len,
627698da718SArtur Paszkiewicz 		.strip_size = g_strip_size,
628698da718SArtur Paszkiewicz 		.md_type = g_enable_dif ? RAID_PARAMS_MD_SEPARATE : RAID_PARAMS_MD_NONE,
629698da718SArtur Paszkiewicz 	};
630698da718SArtur Paszkiewicz 
631698da718SArtur Paszkiewicz 	raid_bdev = raid_test_create_raid_bdev(&params, &g_raid0_module);
632698da718SArtur Paszkiewicz 
633698da718SArtur Paszkiewicz 	SPDK_CU_ASSERT_FATAL(raid0_start(raid_bdev) == 0);
634698da718SArtur Paszkiewicz 
635698da718SArtur Paszkiewicz 	if (g_enable_dif) {
636698da718SArtur Paszkiewicz 		raid_bdev->bdev.dif_type = SPDK_DIF_TYPE1;
637698da718SArtur Paszkiewicz 		raid_bdev->bdev.dif_check_flags =
638698da718SArtur Paszkiewicz 			SPDK_DIF_FLAGS_GUARD_CHECK | SPDK_DIF_FLAGS_REFTAG_CHECK |
639698da718SArtur Paszkiewicz 			SPDK_DIF_FLAGS_APPTAG_CHECK;
640698da718SArtur Paszkiewicz 
641698da718SArtur Paszkiewicz 		RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
642698da718SArtur Paszkiewicz 			struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(base_info->desc);
643698da718SArtur Paszkiewicz 
644698da718SArtur Paszkiewicz 			bdev->dif_type = raid_bdev->bdev.dif_type;
645698da718SArtur Paszkiewicz 			bdev->dif_check_flags = raid_bdev->bdev.dif_check_flags;
646698da718SArtur Paszkiewicz 		}
647698da718SArtur Paszkiewicz 	}
648698da718SArtur Paszkiewicz 
649698da718SArtur Paszkiewicz 	return raid_bdev;
650698da718SArtur Paszkiewicz }
651698da718SArtur Paszkiewicz 
652698da718SArtur Paszkiewicz static void
delete_raid0(struct raid_bdev * raid_bdev)653698da718SArtur Paszkiewicz delete_raid0(struct raid_bdev *raid_bdev)
654698da718SArtur Paszkiewicz {
655698da718SArtur Paszkiewicz 	raid_test_delete_raid_bdev(raid_bdev);
656698da718SArtur Paszkiewicz }
657698da718SArtur Paszkiewicz 
658698da718SArtur Paszkiewicz static void
test_write_io(void)659698da718SArtur Paszkiewicz test_write_io(void)
660698da718SArtur Paszkiewicz {
661698da718SArtur Paszkiewicz 	struct raid_bdev *raid_bdev;
662698da718SArtur Paszkiewicz 	uint8_t i;
663698da718SArtur Paszkiewicz 	uint64_t io_len;
664698da718SArtur Paszkiewicz 	uint64_t lba = 0;
665698da718SArtur Paszkiewicz 	struct raid_bdev_io *raid_io;
666698da718SArtur Paszkiewicz 	struct raid_bdev_io_channel *raid_ch;
667698da718SArtur Paszkiewicz 
668698da718SArtur Paszkiewicz 	set_globals();
669698da718SArtur Paszkiewicz 
670698da718SArtur Paszkiewicz 	raid_bdev = create_raid0();
671698da718SArtur Paszkiewicz 	raid_ch = raid_test_create_io_channel(raid_bdev);
672698da718SArtur Paszkiewicz 
673698da718SArtur Paszkiewicz 	/* test 2 IO sizes based on global strip size set earlier */
674698da718SArtur Paszkiewicz 	for (i = 0; i < 2; i++) {
675698da718SArtur Paszkiewicz 		raid_io = calloc(1, sizeof(*raid_io));
676698da718SArtur Paszkiewicz 		SPDK_CU_ASSERT_FATAL(raid_io != NULL);
677698da718SArtur Paszkiewicz 		io_len = (g_strip_size / 2) << i;
678698da718SArtur Paszkiewicz 		raid_io_initialize(raid_io, raid_ch, raid_bdev, lba, io_len, SPDK_BDEV_IO_TYPE_WRITE);
679698da718SArtur Paszkiewicz 		lba += g_strip_size;
680698da718SArtur Paszkiewicz 		memset(g_io_output, 0, ((g_max_io_size / g_strip_size) + 1) * sizeof(struct io_output));
681698da718SArtur Paszkiewicz 		g_io_output_index = 0;
682698da718SArtur Paszkiewicz 		generate_dif(raid_io->iovs, raid_io->iovcnt, raid_io->md_buf,
683698da718SArtur Paszkiewicz 			     raid_io->offset_blocks, raid_io->num_blocks, &raid_bdev->bdev);
684698da718SArtur Paszkiewicz 		raid0_submit_rw_request(raid_io);
685698da718SArtur Paszkiewicz 		verify_io(raid_io, g_child_io_status_flag);
686698da718SArtur Paszkiewicz 		raid_io_cleanup(raid_io);
687698da718SArtur Paszkiewicz 	}
688698da718SArtur Paszkiewicz 
689698da718SArtur Paszkiewicz 	raid_test_destroy_io_channel(raid_ch);
690698da718SArtur Paszkiewicz 	delete_raid0(raid_bdev);
691698da718SArtur Paszkiewicz 
692698da718SArtur Paszkiewicz 	reset_globals();
693698da718SArtur Paszkiewicz }
694698da718SArtur Paszkiewicz 
695698da718SArtur Paszkiewicz static void
test_read_io(void)696698da718SArtur Paszkiewicz test_read_io(void)
697698da718SArtur Paszkiewicz {
698698da718SArtur Paszkiewicz 	struct raid_bdev *raid_bdev;
699698da718SArtur Paszkiewicz 	uint8_t i;
700698da718SArtur Paszkiewicz 	uint64_t io_len;
701698da718SArtur Paszkiewicz 	uint64_t lba = 0;
702698da718SArtur Paszkiewicz 	struct raid_bdev_io *raid_io;
703698da718SArtur Paszkiewicz 	struct raid_bdev_io_channel *raid_ch;
704698da718SArtur Paszkiewicz 
705698da718SArtur Paszkiewicz 	set_globals();
706698da718SArtur Paszkiewicz 
707698da718SArtur Paszkiewicz 	raid_bdev = create_raid0();
708698da718SArtur Paszkiewicz 	raid_ch = raid_test_create_io_channel(raid_bdev);
709698da718SArtur Paszkiewicz 
710698da718SArtur Paszkiewicz 	/* test 2 IO sizes based on global strip size set earlier */
711698da718SArtur Paszkiewicz 	lba = 0;
712698da718SArtur Paszkiewicz 	for (i = 0; i < 2; i++) {
713698da718SArtur Paszkiewicz 		raid_io = calloc(1, sizeof(*raid_io));
714698da718SArtur Paszkiewicz 		SPDK_CU_ASSERT_FATAL(raid_io != NULL);
715698da718SArtur Paszkiewicz 		io_len = (g_strip_size / 2) << i;
716698da718SArtur Paszkiewicz 		raid_io_initialize(raid_io, raid_ch, raid_bdev, lba, io_len, SPDK_BDEV_IO_TYPE_READ);
717698da718SArtur Paszkiewicz 		lba += g_strip_size;
718698da718SArtur Paszkiewicz 		memset(g_io_output, 0, ((g_max_io_size / g_strip_size) + 1) * sizeof(struct io_output));
719698da718SArtur Paszkiewicz 		g_io_output_index = 0;
720698da718SArtur Paszkiewicz 		raid0_submit_rw_request(raid_io);
721698da718SArtur Paszkiewicz 		verify_io(raid_io, g_child_io_status_flag);
722698da718SArtur Paszkiewicz 		raid_io_cleanup(raid_io);
723698da718SArtur Paszkiewicz 	}
724698da718SArtur Paszkiewicz 
725698da718SArtur Paszkiewicz 	raid_test_destroy_io_channel(raid_ch);
726698da718SArtur Paszkiewicz 	delete_raid0(raid_bdev);
727698da718SArtur Paszkiewicz 
728698da718SArtur Paszkiewicz 	reset_globals();
729698da718SArtur Paszkiewicz }
730698da718SArtur Paszkiewicz 
731698da718SArtur Paszkiewicz static void
raid_bdev_io_generate_by_strips(uint64_t n_strips)732698da718SArtur Paszkiewicz raid_bdev_io_generate_by_strips(uint64_t n_strips)
733698da718SArtur Paszkiewicz {
734698da718SArtur Paszkiewicz 	uint64_t lba;
735698da718SArtur Paszkiewicz 	uint64_t nblocks;
736698da718SArtur Paszkiewicz 	uint64_t start_offset;
737698da718SArtur Paszkiewicz 	uint64_t end_offset;
738698da718SArtur Paszkiewicz 	uint64_t offsets_in_strip[3];
739698da718SArtur Paszkiewicz 	uint64_t start_bdev_idx;
740698da718SArtur Paszkiewicz 	uint64_t start_bdev_offset;
741698da718SArtur Paszkiewicz 	uint64_t start_bdev_idxs[3];
742698da718SArtur Paszkiewicz 	int i, j, l;
743698da718SArtur Paszkiewicz 
744698da718SArtur Paszkiewicz 	/* 3 different situations of offset in strip */
745698da718SArtur Paszkiewicz 	offsets_in_strip[0] = 0;
746698da718SArtur Paszkiewicz 	offsets_in_strip[1] = g_strip_size >> 1;
747698da718SArtur Paszkiewicz 	offsets_in_strip[2] = g_strip_size - 1;
748698da718SArtur Paszkiewicz 
749698da718SArtur Paszkiewicz 	/* 3 different situations of start_bdev_idx */
750698da718SArtur Paszkiewicz 	start_bdev_idxs[0] = 0;
751698da718SArtur Paszkiewicz 	start_bdev_idxs[1] = g_max_base_drives >> 1;
752698da718SArtur Paszkiewicz 	start_bdev_idxs[2] = g_max_base_drives - 1;
753698da718SArtur Paszkiewicz 
754698da718SArtur Paszkiewicz 	/* consider different offset in strip */
755698da718SArtur Paszkiewicz 	for (i = 0; i < 3; i++) {
756698da718SArtur Paszkiewicz 		start_offset = offsets_in_strip[i];
757698da718SArtur Paszkiewicz 		for (j = 0; j < 3; j++) {
758698da718SArtur Paszkiewicz 			end_offset = offsets_in_strip[j];
759698da718SArtur Paszkiewicz 			if (n_strips == 1 && start_offset > end_offset) {
760698da718SArtur Paszkiewicz 				continue;
761698da718SArtur Paszkiewicz 			}
762698da718SArtur Paszkiewicz 
763698da718SArtur Paszkiewicz 			/* consider at which base_bdev lba is started. */
764698da718SArtur Paszkiewicz 			for (l = 0; l < 3; l++) {
765698da718SArtur Paszkiewicz 				start_bdev_idx = start_bdev_idxs[l];
766698da718SArtur Paszkiewicz 				start_bdev_offset = start_bdev_idx * g_strip_size;
767698da718SArtur Paszkiewicz 				lba = start_bdev_offset + start_offset;
768698da718SArtur Paszkiewicz 				nblocks = (n_strips - 1) * g_strip_size + end_offset - start_offset + 1;
769698da718SArtur Paszkiewicz 
770698da718SArtur Paszkiewicz 				g_io_ranges[g_io_range_idx].lba = lba;
771698da718SArtur Paszkiewicz 				g_io_ranges[g_io_range_idx].nblocks = nblocks;
772698da718SArtur Paszkiewicz 
773698da718SArtur Paszkiewicz 				SPDK_CU_ASSERT_FATAL(g_io_range_idx < MAX_TEST_IO_RANGE);
774698da718SArtur Paszkiewicz 				g_io_range_idx++;
775698da718SArtur Paszkiewicz 			}
776698da718SArtur Paszkiewicz 		}
777698da718SArtur Paszkiewicz 	}
778698da718SArtur Paszkiewicz }
779698da718SArtur Paszkiewicz 
780698da718SArtur Paszkiewicz static void
raid_bdev_io_generate(void)781698da718SArtur Paszkiewicz raid_bdev_io_generate(void)
782698da718SArtur Paszkiewicz {
783698da718SArtur Paszkiewicz 	uint64_t n_strips;
784698da718SArtur Paszkiewicz 	uint64_t n_strips_span = g_max_base_drives;
785698da718SArtur Paszkiewicz 	uint64_t n_strips_times[5] = {g_max_base_drives + 1, g_max_base_drives * 2 - 1,
786698da718SArtur Paszkiewicz 				      g_max_base_drives * 2, g_max_base_drives * 3,
787698da718SArtur Paszkiewicz 				      g_max_base_drives * 4
788698da718SArtur Paszkiewicz 				     };
789698da718SArtur Paszkiewicz 	uint32_t i;
790698da718SArtur Paszkiewicz 
791698da718SArtur Paszkiewicz 	g_io_range_idx = 0;
792698da718SArtur Paszkiewicz 
793698da718SArtur Paszkiewicz 	/* consider different number of strips from 1 to strips spanned base bdevs,
794698da718SArtur Paszkiewicz 	 * and even to times of strips spanned base bdevs
795698da718SArtur Paszkiewicz 	 */
796698da718SArtur Paszkiewicz 	for (n_strips = 1; n_strips < n_strips_span; n_strips++) {
797698da718SArtur Paszkiewicz 		raid_bdev_io_generate_by_strips(n_strips);
798698da718SArtur Paszkiewicz 	}
799698da718SArtur Paszkiewicz 
800698da718SArtur Paszkiewicz 	for (i = 0; i < SPDK_COUNTOF(n_strips_times); i++) {
801698da718SArtur Paszkiewicz 		n_strips = n_strips_times[i];
802698da718SArtur Paszkiewicz 		raid_bdev_io_generate_by_strips(n_strips);
803698da718SArtur Paszkiewicz 	}
804698da718SArtur Paszkiewicz }
805698da718SArtur Paszkiewicz 
806698da718SArtur Paszkiewicz static void
test_unmap_io(void)807698da718SArtur Paszkiewicz test_unmap_io(void)
808698da718SArtur Paszkiewicz {
809698da718SArtur Paszkiewicz 	struct raid_bdev *raid_bdev;
810698da718SArtur Paszkiewicz 	uint32_t count;
811698da718SArtur Paszkiewicz 	uint64_t io_len;
812698da718SArtur Paszkiewicz 	uint64_t lba;
813698da718SArtur Paszkiewicz 	struct raid_bdev_io *raid_io;
814698da718SArtur Paszkiewicz 	struct raid_bdev_io_channel *raid_ch;
815698da718SArtur Paszkiewicz 
816698da718SArtur Paszkiewicz 	set_globals();
817698da718SArtur Paszkiewicz 
818698da718SArtur Paszkiewicz 	raid_bdev = create_raid0();
819698da718SArtur Paszkiewicz 	raid_ch = raid_test_create_io_channel(raid_bdev);
820698da718SArtur Paszkiewicz 
821698da718SArtur Paszkiewicz 	raid_bdev_io_generate();
822698da718SArtur Paszkiewicz 	for (count = 0; count < g_io_range_idx; count++) {
823698da718SArtur Paszkiewicz 		raid_io = calloc(1, sizeof(*raid_io));
824698da718SArtur Paszkiewicz 		SPDK_CU_ASSERT_FATAL(raid_io != NULL);
825698da718SArtur Paszkiewicz 		io_len = g_io_ranges[count].nblocks;
826698da718SArtur Paszkiewicz 		lba = g_io_ranges[count].lba;
827698da718SArtur Paszkiewicz 		raid_io_initialize(raid_io, raid_ch, raid_bdev, lba, io_len, SPDK_BDEV_IO_TYPE_UNMAP);
828698da718SArtur Paszkiewicz 		memset(g_io_output, 0, g_max_base_drives * sizeof(struct io_output));
829698da718SArtur Paszkiewicz 		g_io_output_index = 0;
830698da718SArtur Paszkiewicz 		raid0_submit_null_payload_request(raid_io);
831698da718SArtur Paszkiewicz 		verify_io_without_payload(raid_io, g_child_io_status_flag);
832698da718SArtur Paszkiewicz 		raid_io_cleanup(raid_io);
833698da718SArtur Paszkiewicz 	}
834698da718SArtur Paszkiewicz 
835698da718SArtur Paszkiewicz 	raid_test_destroy_io_channel(raid_ch);
836698da718SArtur Paszkiewicz 	delete_raid0(raid_bdev);
837698da718SArtur Paszkiewicz 
838698da718SArtur Paszkiewicz 	reset_globals();
839698da718SArtur Paszkiewicz }
840698da718SArtur Paszkiewicz 
841698da718SArtur Paszkiewicz /* Test IO failures */
842698da718SArtur Paszkiewicz static void
test_io_failure(void)843698da718SArtur Paszkiewicz test_io_failure(void)
844698da718SArtur Paszkiewicz {
845698da718SArtur Paszkiewicz 	struct raid_bdev *raid_bdev;
846698da718SArtur Paszkiewicz 	uint32_t count;
847698da718SArtur Paszkiewicz 	uint64_t io_len;
848698da718SArtur Paszkiewicz 	uint64_t lba;
849698da718SArtur Paszkiewicz 	struct raid_bdev_io *raid_io;
850698da718SArtur Paszkiewicz 	struct raid_bdev_io_channel *raid_ch;
851698da718SArtur Paszkiewicz 
852698da718SArtur Paszkiewicz 	set_globals();
853698da718SArtur Paszkiewicz 
854698da718SArtur Paszkiewicz 	raid_bdev = create_raid0();
855698da718SArtur Paszkiewicz 	raid_ch = raid_test_create_io_channel(raid_bdev);
856698da718SArtur Paszkiewicz 
857698da718SArtur Paszkiewicz 	lba = 0;
858698da718SArtur Paszkiewicz 	g_child_io_status_flag = false;
859698da718SArtur Paszkiewicz 	for (count = 0; count < 1; count++) {
860698da718SArtur Paszkiewicz 		raid_io = calloc(1, sizeof(*raid_io));
861698da718SArtur Paszkiewicz 		SPDK_CU_ASSERT_FATAL(raid_io != NULL);
862698da718SArtur Paszkiewicz 		io_len = (g_strip_size / 2) << count;
863698da718SArtur Paszkiewicz 		raid_io_initialize(raid_io, raid_ch, raid_bdev, lba, io_len, SPDK_BDEV_IO_TYPE_WRITE);
864698da718SArtur Paszkiewicz 		lba += g_strip_size;
865698da718SArtur Paszkiewicz 		memset(g_io_output, 0, ((g_max_io_size / g_strip_size) + 1) * sizeof(struct io_output));
866698da718SArtur Paszkiewicz 		g_io_output_index = 0;
867698da718SArtur Paszkiewicz 		generate_dif(raid_io->iovs, raid_io->iovcnt, raid_io->md_buf,
868698da718SArtur Paszkiewicz 			     raid_io->offset_blocks, raid_io->num_blocks, &raid_bdev->bdev);
869698da718SArtur Paszkiewicz 		raid0_submit_rw_request(raid_io);
870698da718SArtur Paszkiewicz 		verify_io(raid_io, g_child_io_status_flag);
871698da718SArtur Paszkiewicz 		raid_io_cleanup(raid_io);
872698da718SArtur Paszkiewicz 	}
873698da718SArtur Paszkiewicz 
874698da718SArtur Paszkiewicz 	raid_test_destroy_io_channel(raid_ch);
875698da718SArtur Paszkiewicz 	delete_raid0(raid_bdev);
876698da718SArtur Paszkiewicz 
877698da718SArtur Paszkiewicz 	reset_globals();
878698da718SArtur Paszkiewicz }
879698da718SArtur Paszkiewicz 
880698da718SArtur Paszkiewicz int
main(int argc,char ** argv)881698da718SArtur Paszkiewicz main(int argc, char **argv)
882698da718SArtur Paszkiewicz {
883698da718SArtur Paszkiewicz 	unsigned int    num_failures;
884698da718SArtur Paszkiewicz 
885698da718SArtur Paszkiewicz 	CU_TestInfo tests[] = {
886698da718SArtur Paszkiewicz 		{ "test_write_io", test_write_io },
887698da718SArtur Paszkiewicz 		{ "test_read_io", test_read_io },
888698da718SArtur Paszkiewicz 		{ "test_unmap_io", test_unmap_io },
889698da718SArtur Paszkiewicz 		{ "test_io_failure", test_io_failure },
890698da718SArtur Paszkiewicz 		CU_TEST_INFO_NULL,
891698da718SArtur Paszkiewicz 	};
892698da718SArtur Paszkiewicz 	CU_SuiteInfo suites[] = {
893698da718SArtur Paszkiewicz 		{ "raid0", set_test_opts, NULL, NULL, NULL, tests },
894698da718SArtur Paszkiewicz 		{ "raid0_dif", set_test_opts_dif, NULL, NULL, NULL, tests },
895698da718SArtur Paszkiewicz 		CU_SUITE_INFO_NULL,
896698da718SArtur Paszkiewicz 	};
897698da718SArtur Paszkiewicz 
898698da718SArtur Paszkiewicz 	CU_initialize_registry();
899698da718SArtur Paszkiewicz 	CU_register_suites(suites);
900698da718SArtur Paszkiewicz 
901698da718SArtur Paszkiewicz 	allocate_threads(1);
902698da718SArtur Paszkiewicz 	set_thread(0);
903698da718SArtur Paszkiewicz 
904698da718SArtur Paszkiewicz 	num_failures = spdk_ut_run_tests(argc, argv, NULL);
905698da718SArtur Paszkiewicz 	CU_cleanup_registry();
906698da718SArtur Paszkiewicz 
907698da718SArtur Paszkiewicz 	free_threads();
908698da718SArtur Paszkiewicz 
909698da718SArtur Paszkiewicz 	return num_failures;
910698da718SArtur Paszkiewicz }
911