Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (C) 2018 Intel Corporation.
3 : : * All rights reserved.
4 : : * Copyright (c) 2022-2023 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
5 : : */
6 : :
7 : : #include "spdk/stdinc.h"
8 : : #include "spdk_internal/cunit.h"
9 : : #include "spdk/env.h"
10 : : #include "spdk_internal/mock.h"
11 : : #include "thread/thread_internal.h"
12 : : #include "bdev/raid/bdev_raid.c"
13 : : #include "bdev/raid/bdev_raid_rpc.c"
14 : : #include "bdev/raid/raid0.c"
15 : : #include "common/lib/ut_multithread.c"
16 : :
17 : : #define MAX_BASE_DRIVES 32
18 : : #define MAX_RAIDS 2
19 : : #define INVALID_IO_SUBMIT 0xFFFF
20 : : #define MAX_TEST_IO_RANGE (3 * 3 * 3 * (MAX_BASE_DRIVES + 5))
21 : : #define BLOCK_CNT (1024ul * 1024ul * 1024ul * 1024ul)
22 : :
23 : : struct spdk_bdev_channel {
24 : : struct spdk_io_channel *channel;
25 : : };
26 : :
27 : : struct spdk_bdev_desc {
28 : : struct spdk_bdev *bdev;
29 : : };
30 : :
31 : : /* Data structure to capture the output of IO for verification */
32 : : struct io_output {
33 : : struct spdk_bdev_desc *desc;
34 : : struct spdk_io_channel *ch;
35 : : uint64_t offset_blocks;
36 : : uint64_t num_blocks;
37 : : spdk_bdev_io_completion_cb cb;
38 : : void *cb_arg;
39 : : enum spdk_bdev_io_type iotype;
40 : : };
41 : :
42 : : struct raid_io_ranges {
43 : : uint64_t lba;
44 : : uint64_t nblocks;
45 : : };
46 : :
47 : : /* Globals */
48 : : int g_bdev_io_submit_status;
49 : : struct io_output *g_io_output = NULL;
50 : : uint32_t g_io_output_index;
51 : : uint32_t g_io_comp_status;
52 : : bool g_child_io_status_flag;
53 : : void *g_rpc_req;
54 : : uint32_t g_rpc_req_size;
55 : : TAILQ_HEAD(bdev, spdk_bdev);
56 : : struct bdev g_bdev_list;
57 : : TAILQ_HEAD(waitq, spdk_bdev_io_wait_entry);
58 : : struct waitq g_io_waitq;
59 : : uint32_t g_block_len;
60 : : uint32_t g_strip_size;
61 : : uint32_t g_max_io_size;
62 : : uint8_t g_max_base_drives;
63 : : uint8_t g_max_raids;
64 : : uint8_t g_ignore_io_output;
65 : : uint8_t g_rpc_err;
66 : : char *g_get_raids_output[MAX_RAIDS];
67 : : uint32_t g_get_raids_count;
68 : : uint8_t g_json_decode_obj_err;
69 : : uint8_t g_json_decode_obj_create;
70 : : uint8_t g_config_level_create = 0;
71 : : uint8_t g_test_multi_raids;
72 : : struct raid_io_ranges g_io_ranges[MAX_TEST_IO_RANGE];
73 : : uint32_t g_io_range_idx;
74 : : uint64_t g_lba_offset;
75 : : uint64_t g_bdev_ch_io_device;
76 : : bool g_bdev_io_defer_completion;
77 : : TAILQ_HEAD(, spdk_bdev_io) g_deferred_ios = TAILQ_HEAD_INITIALIZER(g_deferred_ios);
78 : :
79 : 0 : DEFINE_STUB_V(spdk_bdev_module_examine_done, (struct spdk_bdev_module *module));
80 : 3 : DEFINE_STUB_V(spdk_bdev_module_list_add, (struct spdk_bdev_module *bdev_module));
81 [ - + ]: 288 : DEFINE_STUB(spdk_bdev_io_type_supported, bool, (struct spdk_bdev *bdev,
82 : : enum spdk_bdev_io_type io_type), true);
83 : 2016 : DEFINE_STUB_V(spdk_bdev_close, (struct spdk_bdev_desc *desc));
84 : 0 : DEFINE_STUB(spdk_bdev_flush_blocks, int, (struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
85 : : uint64_t offset_blocks, uint64_t num_blocks, spdk_bdev_io_completion_cb cb,
86 : : void *cb_arg), 0);
87 : 0 : DEFINE_STUB(spdk_conf_next_section, struct spdk_conf_section *, (struct spdk_conf_section *sp),
88 : : NULL);
89 : 18 : DEFINE_STUB_V(spdk_rpc_register_method, (const char *method, spdk_rpc_method_handler func,
90 : : uint32_t state_mask));
91 : 0 : DEFINE_STUB_V(spdk_rpc_register_alias_deprecated, (const char *method, const char *alias));
92 : 15 : DEFINE_STUB_V(spdk_jsonrpc_end_result, (struct spdk_jsonrpc_request *request,
93 : : struct spdk_json_write_ctx *w));
94 : 117 : DEFINE_STUB_V(spdk_jsonrpc_send_bool_response, (struct spdk_jsonrpc_request *request,
95 : : bool value));
96 : 0 : DEFINE_STUB(spdk_json_decode_string, int, (const struct spdk_json_val *val, void *out), 0);
97 : 0 : DEFINE_STUB(spdk_json_decode_uint32, int, (const struct spdk_json_val *val, void *out), 0);
98 : 0 : DEFINE_STUB(spdk_json_decode_uuid, int, (const struct spdk_json_val *val, void *out), 0);
99 : 0 : DEFINE_STUB(spdk_json_decode_array, int, (const struct spdk_json_val *values,
100 : : spdk_json_decode_fn decode_func,
101 : : void *out, size_t max_size, size_t *out_size, size_t stride), 0);
102 : 0 : DEFINE_STUB(spdk_json_decode_bool, int, (const struct spdk_json_val *val, void *out), 0);
103 : 693 : DEFINE_STUB(spdk_json_write_name, int, (struct spdk_json_write_ctx *w, const char *name), 0);
104 : 690 : DEFINE_STUB(spdk_json_write_object_begin, int, (struct spdk_json_write_ctx *w), 0);
105 : 3 : DEFINE_STUB(spdk_json_write_named_object_begin, int, (struct spdk_json_write_ctx *w,
106 : : const char *name), 0);
107 : 672 : DEFINE_STUB(spdk_json_write_string, int, (struct spdk_json_write_ctx *w, const char *val), 0);
108 : 693 : DEFINE_STUB(spdk_json_write_object_end, int, (struct spdk_json_write_ctx *w), 0);
109 : 36 : DEFINE_STUB(spdk_json_write_array_begin, int, (struct spdk_json_write_ctx *w), 0);
110 : 36 : DEFINE_STUB(spdk_json_write_array_end, int, (struct spdk_json_write_ctx *w), 0);
111 : 0 : DEFINE_STUB(spdk_json_write_named_array_begin, int, (struct spdk_json_write_ctx *w,
112 : : const char *name), 0);
113 : 0 : DEFINE_STUB(spdk_json_write_bool, int, (struct spdk_json_write_ctx *w, bool val), 0);
114 : 0 : DEFINE_STUB(spdk_json_write_null, int, (struct spdk_json_write_ctx *w), 0);
115 : 1344 : DEFINE_STUB(spdk_json_write_named_uint64, int, (struct spdk_json_write_ctx *w, const char *name,
116 : : uint64_t val), 0);
117 : 18 : DEFINE_STUB(spdk_strerror, const char *, (int errnum), NULL);
118 : 0 : DEFINE_STUB(spdk_bdev_queue_io_wait, int, (struct spdk_bdev *bdev, struct spdk_io_channel *ch,
119 : : struct spdk_bdev_io_wait_entry *entry), 0);
120 : 0 : DEFINE_STUB(spdk_bdev_get_memory_domains, int, (struct spdk_bdev *bdev,
121 : : struct spdk_memory_domain **domains, int array_size), 0);
122 : 0 : DEFINE_STUB(spdk_bdev_get_name, const char *, (const struct spdk_bdev *bdev), "test_bdev");
123 : 2010 : DEFINE_STUB(spdk_bdev_get_md_size, uint32_t, (const struct spdk_bdev *bdev), 0);
124 [ - + ]: 2010 : DEFINE_STUB(spdk_bdev_is_md_interleaved, bool, (const struct spdk_bdev *bdev), false);
125 [ - + ]: 48 : DEFINE_STUB(spdk_bdev_is_md_separate, bool, (const struct spdk_bdev *bdev), false);
126 : 2010 : DEFINE_STUB(spdk_bdev_get_dif_type, enum spdk_dif_type, (const struct spdk_bdev *bdev),
127 : : SPDK_DIF_DISABLE);
128 [ # # ]: 0 : DEFINE_STUB(spdk_bdev_is_dif_head_of_md, bool, (const struct spdk_bdev *bdev), false);
129 : 0 : DEFINE_STUB(spdk_bdev_notify_blockcnt_change, int, (struct spdk_bdev *bdev, uint64_t size), 0);
130 : 3 : DEFINE_STUB_V(raid_bdev_init_superblock, (struct raid_bdev *raid_bdev));
131 : :
132 : : int
133 : 2010 : raid_bdev_load_base_bdev_superblock(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
134 : : raid_bdev_load_sb_cb cb, void *cb_ctx)
135 : : {
136 : 2010 : cb(NULL, -EINVAL, cb_ctx);
137 : :
138 : 2010 : return 0;
139 : : }
140 : :
141 : : void
142 : 3 : raid_bdev_write_superblock(struct raid_bdev *raid_bdev, raid_bdev_write_sb_cb cb, void *cb_ctx)
143 : : {
144 : 3 : cb(0, raid_bdev, cb_ctx);
145 : 3 : }
146 : :
147 : : const struct spdk_uuid *
148 : 2016 : spdk_bdev_get_uuid(const struct spdk_bdev *bdev)
149 : : {
150 : 2016 : return &bdev->uuid;
151 : : }
152 : :
153 : : struct spdk_io_channel *
154 : 2970 : spdk_bdev_get_io_channel(struct spdk_bdev_desc *desc)
155 : : {
156 : 2970 : return spdk_get_io_channel(&g_bdev_ch_io_device);
157 : : }
158 : :
159 : : static void
160 : 3 : set_test_opts(void)
161 : : {
162 : :
163 : 3 : g_max_base_drives = MAX_BASE_DRIVES;
164 : 3 : g_max_raids = MAX_RAIDS;
165 : 3 : g_block_len = 4096;
166 : 3 : g_strip_size = 64;
167 : 3 : g_max_io_size = 1024;
168 : :
169 [ - + ]: 3 : printf("Test Options\n");
170 [ - + ]: 3 : printf("blocklen = %u, strip_size = %u, max_io_size = %u, g_max_base_drives = %u, "
171 : : "g_max_raids = %u\n",
172 : : g_block_len, g_strip_size, g_max_io_size, g_max_base_drives, g_max_raids);
173 : 3 : }
174 : :
175 : : /* Set globals before every test run */
176 : : static void
177 : 48 : set_globals(void)
178 : : {
179 : : uint32_t max_splits;
180 : :
181 : 48 : g_bdev_io_submit_status = 0;
182 [ - + ]: 48 : if (g_max_io_size < g_strip_size) {
183 : 0 : max_splits = 2;
184 : : } else {
185 [ - + ]: 48 : max_splits = (g_max_io_size / g_strip_size) + 1;
186 : : }
187 [ + - ]: 48 : if (max_splits < g_max_base_drives) {
188 : 48 : max_splits = g_max_base_drives;
189 : : }
190 : :
191 : 48 : g_io_output = calloc(max_splits, sizeof(struct io_output));
192 [ - + ]: 48 : SPDK_CU_ASSERT_FATAL(g_io_output != NULL);
193 : 48 : g_io_output_index = 0;
194 : 48 : memset(g_get_raids_output, 0, sizeof(g_get_raids_output));
195 : 48 : g_get_raids_count = 0;
196 : 48 : g_io_comp_status = 0;
197 : 48 : g_ignore_io_output = 0;
198 : 48 : g_config_level_create = 0;
199 : 48 : g_rpc_err = 0;
200 : 48 : g_test_multi_raids = 0;
201 : 48 : g_child_io_status_flag = true;
202 : 48 : TAILQ_INIT(&g_bdev_list);
203 : 48 : TAILQ_INIT(&g_io_waitq);
204 : 48 : g_rpc_req = NULL;
205 : 48 : g_rpc_req_size = 0;
206 : 48 : g_json_decode_obj_err = 0;
207 : 48 : g_json_decode_obj_create = 0;
208 : 48 : g_lba_offset = 0;
209 : 48 : g_bdev_io_defer_completion = false;
210 : 48 : }
211 : :
212 : : static void
213 : 48 : base_bdevs_cleanup(void)
214 : : {
215 : : struct spdk_bdev *bdev;
216 : : struct spdk_bdev *bdev_next;
217 : :
218 [ + - ]: 48 : if (!TAILQ_EMPTY(&g_bdev_list)) {
219 [ + + ]: 1968 : TAILQ_FOREACH_SAFE(bdev, &g_bdev_list, internal.link, bdev_next) {
220 : 1920 : free(bdev->name);
221 [ + + ]: 1920 : TAILQ_REMOVE(&g_bdev_list, bdev, internal.link);
222 : 1920 : free(bdev);
223 : : }
224 : : }
225 : 48 : }
226 : :
227 : : static void
228 : 3 : check_and_remove_raid_bdev(struct raid_bdev *raid_bdev)
229 : : {
230 : : struct raid_base_bdev_info *base_info;
231 : :
232 [ - + ]: 3 : assert(raid_bdev != NULL);
233 [ - + ]: 3 : assert(raid_bdev->base_bdev_info != NULL);
234 : :
235 [ + + ]: 99 : RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
236 [ + + ]: 96 : if (base_info->desc) {
237 : 93 : raid_bdev_free_base_bdev_resource(base_info);
238 : : }
239 : : }
240 [ - + ]: 3 : assert(raid_bdev->num_base_bdevs_discovered == 0);
241 : 3 : raid_bdev_cleanup_and_free(raid_bdev);
242 : 3 : }
243 : :
244 : : /* Reset globals */
245 : : static void
246 : 48 : reset_globals(void)
247 : : {
248 [ + - ]: 48 : if (g_io_output) {
249 : 48 : free(g_io_output);
250 : 48 : g_io_output = NULL;
251 : : }
252 : 48 : g_rpc_req = NULL;
253 : 48 : g_rpc_req_size = 0;
254 : 48 : }
255 : :
256 : : void
257 : 9 : spdk_bdev_io_get_buf(struct spdk_bdev_io *bdev_io, spdk_bdev_io_get_buf_cb cb,
258 : : uint64_t len)
259 : : {
260 : 9 : cb(bdev_io->internal.ch->channel, bdev_io, true);
261 : 9 : }
262 : :
263 : : /* Store the IO completion status in global variable to verify by various tests */
264 : : void
265 : 2931 : spdk_bdev_io_complete(struct spdk_bdev_io *bdev_io, enum spdk_bdev_io_status status)
266 : : {
267 : 2931 : g_io_comp_status = ((status == SPDK_BDEV_IO_STATUS_SUCCESS) ? true : false);
268 : 2931 : }
269 : :
270 : : static void
271 : 53256 : set_io_output(struct io_output *output,
272 : : struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
273 : : uint64_t offset_blocks, uint64_t num_blocks,
274 : : spdk_bdev_io_completion_cb cb, void *cb_arg,
275 : : enum spdk_bdev_io_type iotype)
276 : : {
277 : 53256 : output->desc = desc;
278 : 53256 : output->ch = ch;
279 : 53256 : output->offset_blocks = offset_blocks;
280 : 53256 : output->num_blocks = num_blocks;
281 : 53256 : output->cb = cb;
282 : 53256 : output->cb_arg = cb_arg;
283 : 53256 : output->iotype = iotype;
284 : 53256 : }
285 : :
286 : : static void
287 : 53256 : child_io_complete(struct spdk_bdev_io *child_io, spdk_bdev_io_completion_cb cb, void *cb_arg)
288 : : {
289 [ + + + + ]: 53256 : if (g_bdev_io_defer_completion) {
290 : 30 : child_io->internal.cb = cb;
291 : 30 : child_io->internal.caller_ctx = cb_arg;
292 : 30 : TAILQ_INSERT_TAIL(&g_deferred_ios, child_io, internal.link);
293 : : } else {
294 [ - + ]: 53226 : cb(child_io, g_child_io_status_flag, cb_arg);
295 : : }
296 : 53256 : }
297 : :
298 : : static void
299 : 30 : complete_deferred_ios(void)
300 : : {
301 : : struct spdk_bdev_io *child_io, *tmp;
302 : :
303 [ + + ]: 60 : TAILQ_FOREACH_SAFE(child_io, &g_deferred_ios, internal.link, tmp) {
304 [ - + ]: 30 : TAILQ_REMOVE(&g_deferred_ios, child_io, internal.link);
305 [ - + ]: 30 : child_io->internal.cb(child_io, g_child_io_status_flag, child_io->internal.caller_ctx);
306 : : }
307 : 30 : }
308 : :
309 : : /* It will cache the split IOs for verification */
310 : : int
311 : 42 : spdk_bdev_writev_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
312 : : struct iovec *iov, int iovcnt,
313 : : uint64_t offset_blocks, uint64_t num_blocks,
314 : : spdk_bdev_io_completion_cb cb, void *cb_arg)
315 : : {
316 : 42 : struct io_output *output = &g_io_output[g_io_output_index];
317 : : struct spdk_bdev_io *child_io;
318 : :
319 [ - + ]: 42 : if (g_ignore_io_output) {
320 : 0 : return 0;
321 : : }
322 : :
323 [ - + ]: 42 : if (g_max_io_size < g_strip_size) {
324 [ # # ]: 0 : SPDK_CU_ASSERT_FATAL(g_io_output_index < 2);
325 : : } else {
326 [ - + - + ]: 42 : SPDK_CU_ASSERT_FATAL(g_io_output_index < (g_max_io_size / g_strip_size) + 1);
327 : : }
328 [ + - ]: 42 : if (g_bdev_io_submit_status == 0) {
329 : 42 : set_io_output(output, desc, ch, offset_blocks, num_blocks, cb, cb_arg,
330 : : SPDK_BDEV_IO_TYPE_WRITE);
331 : 42 : g_io_output_index++;
332 : :
333 : 42 : child_io = calloc(1, sizeof(struct spdk_bdev_io));
334 [ - + ]: 42 : SPDK_CU_ASSERT_FATAL(child_io != NULL);
335 : 42 : child_io_complete(child_io, cb, cb_arg);
336 : : }
337 : :
338 : 42 : return g_bdev_io_submit_status;
339 : : }
340 : :
341 : : int
342 : 42 : spdk_bdev_writev_blocks_ext(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
343 : : struct iovec *iov, int iovcnt,
344 : : uint64_t offset_blocks, uint64_t num_blocks,
345 : : spdk_bdev_io_completion_cb cb, void *cb_arg,
346 : : struct spdk_bdev_ext_io_opts *opts)
347 : : {
348 : 42 : return spdk_bdev_writev_blocks(desc, ch, iov, iovcnt, offset_blocks, num_blocks, cb, cb_arg);
349 : : }
350 : :
351 : : int
352 : 0 : spdk_bdev_writev_blocks_with_md(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
353 : : struct iovec *iov, int iovcnt, void *md,
354 : : uint64_t offset_blocks, uint64_t num_blocks,
355 : : spdk_bdev_io_completion_cb cb, void *cb_arg)
356 : : {
357 : 0 : return spdk_bdev_writev_blocks(desc, ch, iov, iovcnt, offset_blocks, num_blocks, cb, cb_arg);
358 : : }
359 : :
360 : : int
361 : 96 : spdk_bdev_reset(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
362 : : spdk_bdev_io_completion_cb cb, void *cb_arg)
363 : : {
364 : 96 : struct io_output *output = &g_io_output[g_io_output_index];
365 : : struct spdk_bdev_io *child_io;
366 : :
367 [ - + ]: 96 : if (g_ignore_io_output) {
368 : 0 : return 0;
369 : : }
370 : :
371 [ + - ]: 96 : if (g_bdev_io_submit_status == 0) {
372 : 96 : set_io_output(output, desc, ch, 0, 0, cb, cb_arg, SPDK_BDEV_IO_TYPE_RESET);
373 : 96 : g_io_output_index++;
374 : :
375 : 96 : child_io = calloc(1, sizeof(struct spdk_bdev_io));
376 [ - + ]: 96 : SPDK_CU_ASSERT_FATAL(child_io != NULL);
377 : 96 : child_io_complete(child_io, cb, cb_arg);
378 : : }
379 : :
380 : 96 : return g_bdev_io_submit_status;
381 : : }
382 : :
383 : : int
384 : 53109 : spdk_bdev_unmap_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
385 : : uint64_t offset_blocks, uint64_t num_blocks,
386 : : spdk_bdev_io_completion_cb cb, void *cb_arg)
387 : : {
388 : 53109 : struct io_output *output = &g_io_output[g_io_output_index];
389 : : struct spdk_bdev_io *child_io;
390 : :
391 [ - + ]: 53109 : if (g_ignore_io_output) {
392 : 0 : return 0;
393 : : }
394 : :
395 [ + - ]: 53109 : if (g_bdev_io_submit_status == 0) {
396 : 53109 : set_io_output(output, desc, ch, offset_blocks, num_blocks, cb, cb_arg,
397 : : SPDK_BDEV_IO_TYPE_UNMAP);
398 : 53109 : g_io_output_index++;
399 : :
400 : 53109 : child_io = calloc(1, sizeof(struct spdk_bdev_io));
401 [ - + ]: 53109 : SPDK_CU_ASSERT_FATAL(child_io != NULL);
402 : 53109 : child_io_complete(child_io, cb, cb_arg);
403 : : }
404 : :
405 : 53109 : return g_bdev_io_submit_status;
406 : : }
407 : :
408 : : void
409 : 57 : spdk_bdev_destruct_done(struct spdk_bdev *bdev, int bdeverrno)
410 : : {
411 : 57 : CU_ASSERT(bdeverrno == 0);
412 [ - + ]: 57 : SPDK_CU_ASSERT_FATAL(bdev->internal.unregister_cb != NULL);
413 : 57 : bdev->internal.unregister_cb(bdev->internal.unregister_ctx, bdeverrno);
414 : 57 : }
415 : :
416 : : int
417 : 57 : spdk_bdev_register(struct spdk_bdev *bdev)
418 : : {
419 : 57 : TAILQ_INSERT_TAIL(&g_bdev_list, bdev, internal.link);
420 : 57 : return 0;
421 : : }
422 : :
423 : : void
424 : 57 : spdk_bdev_unregister(struct spdk_bdev *bdev, spdk_bdev_unregister_cb cb_fn, void *cb_arg)
425 : : {
426 : : int ret;
427 : :
428 [ - + ]: 57 : SPDK_CU_ASSERT_FATAL(spdk_bdev_get_by_name(bdev->name) == bdev);
429 [ + + ]: 57 : TAILQ_REMOVE(&g_bdev_list, bdev, internal.link);
430 : :
431 : 57 : bdev->internal.unregister_cb = cb_fn;
432 : 57 : bdev->internal.unregister_ctx = cb_arg;
433 : :
434 : 57 : ret = bdev->fn_table->destruct(bdev->ctxt);
435 : 57 : CU_ASSERT(ret == 1);
436 : :
437 : 57 : poll_threads();
438 : 57 : }
439 : :
440 : : int
441 : 2076 : spdk_bdev_open_ext(const char *bdev_name, bool write, spdk_bdev_event_cb_t event_cb,
442 : : void *event_ctx, struct spdk_bdev_desc **_desc)
443 : : {
444 : : struct spdk_bdev *bdev;
445 : :
446 : 2076 : bdev = spdk_bdev_get_by_name(bdev_name);
447 [ + + ]: 2076 : if (bdev == NULL) {
448 : 3 : return -ENODEV;
449 : : }
450 : :
451 : 2073 : *_desc = (void *)bdev;
452 : 2073 : return 0;
453 : : }
454 : :
455 : : struct spdk_bdev *
456 : 6042 : spdk_bdev_desc_get_bdev(struct spdk_bdev_desc *desc)
457 : : {
458 : 6042 : return (void *)desc;
459 : : }
460 : :
461 : : int
462 : 84 : spdk_json_write_named_uint32(struct spdk_json_write_ctx *w, const char *name, uint32_t val)
463 : : {
464 [ + + ]: 84 : if (!g_test_multi_raids) {
465 : 12 : struct rpc_bdev_raid_create *req = g_rpc_req;
466 [ + + + + ]: 12 : if (strcmp(name, "strip_size_kb") == 0) {
467 : 3 : CU_ASSERT(req->strip_size_kb == val);
468 [ - + - + ]: 9 : } else if (strcmp(name, "blocklen_shift") == 0) {
469 : 0 : CU_ASSERT(spdk_u32log2(g_block_len) == val);
470 [ + + + + ]: 9 : } else if (strcmp(name, "num_base_bdevs") == 0) {
471 : 3 : CU_ASSERT(req->base_bdevs.num_base_bdevs == val);
472 [ - + - + ]: 6 : } else if (strcmp(name, "state") == 0) {
473 : 0 : CU_ASSERT(val == RAID_BDEV_STATE_ONLINE);
474 [ - + - + ]: 6 : } else if (strcmp(name, "destruct_called") == 0) {
475 : 0 : CU_ASSERT(val == 0);
476 [ + + + + ]: 6 : } else if (strcmp(name, "num_base_bdevs_discovered") == 0) {
477 : 3 : CU_ASSERT(req->base_bdevs.num_base_bdevs == val);
478 : : }
479 : : }
480 : 84 : return 0;
481 : : }
482 : :
483 : : int
484 : 771 : spdk_json_write_named_string(struct spdk_json_write_ctx *w, const char *name, const char *val)
485 : : {
486 [ + + ]: 771 : if (g_test_multi_raids) {
487 [ + + + + ]: 666 : if (strcmp(name, "name") == 0) {
488 [ - + ]: 18 : g_get_raids_output[g_get_raids_count] = strdup(val);
489 [ - + ]: 18 : SPDK_CU_ASSERT_FATAL(g_get_raids_output[g_get_raids_count] != NULL);
490 : 18 : g_get_raids_count++;
491 : : }
492 : : } else {
493 : 105 : struct rpc_bdev_raid_create *req = g_rpc_req;
494 [ + + + + ]: 105 : if (strcmp(name, "raid_level") == 0) {
495 [ - + - + ]: 3 : CU_ASSERT(strcmp(val, raid_bdev_level_to_str(req->level)) == 0);
496 : : }
497 : : }
498 : 771 : return 0;
499 : : }
500 : :
501 : : int
502 : 693 : spdk_json_write_named_bool(struct spdk_json_write_ctx *w, const char *name, bool val)
503 : : {
504 [ + + ]: 693 : if (!g_test_multi_raids) {
505 : 99 : struct rpc_bdev_raid_create *req = g_rpc_req;
506 [ + + + + ]: 99 : if (strcmp(name, "superblock") == 0) {
507 [ - + ]: 3 : CU_ASSERT(val == req->superblock_enabled);
508 : : }
509 : : }
510 : 693 : return 0;
511 : : }
512 : :
513 : : void
514 : 53256 : spdk_bdev_free_io(struct spdk_bdev_io *bdev_io)
515 : : {
516 [ + - ]: 53256 : if (bdev_io) {
517 : 53256 : free(bdev_io);
518 : : }
519 : 53256 : }
520 : :
521 : : /* It will cache split IOs for verification */
522 : : int
523 : 9 : spdk_bdev_readv_blocks(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
524 : : struct iovec *iov, int iovcnt,
525 : : uint64_t offset_blocks, uint64_t num_blocks,
526 : : spdk_bdev_io_completion_cb cb, void *cb_arg)
527 : : {
528 : 9 : struct io_output *output = &g_io_output[g_io_output_index];
529 : : struct spdk_bdev_io *child_io;
530 : :
531 [ - + ]: 9 : if (g_ignore_io_output) {
532 : 0 : return 0;
533 : : }
534 : :
535 [ - + - + ]: 9 : SPDK_CU_ASSERT_FATAL(g_io_output_index <= (g_max_io_size / g_strip_size) + 1);
536 [ + - ]: 9 : if (g_bdev_io_submit_status == 0) {
537 : 9 : set_io_output(output, desc, ch, offset_blocks, num_blocks, cb, cb_arg,
538 : : SPDK_BDEV_IO_TYPE_READ);
539 : 9 : g_io_output_index++;
540 : :
541 : 9 : child_io = calloc(1, sizeof(struct spdk_bdev_io));
542 [ - + ]: 9 : SPDK_CU_ASSERT_FATAL(child_io != NULL);
543 : 9 : child_io_complete(child_io, cb, cb_arg);
544 : : }
545 : :
546 : 9 : return g_bdev_io_submit_status;
547 : : }
548 : :
549 : : int
550 : 9 : spdk_bdev_readv_blocks_ext(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
551 : : struct iovec *iov, int iovcnt,
552 : : uint64_t offset_blocks, uint64_t num_blocks,
553 : : spdk_bdev_io_completion_cb cb, void *cb_arg,
554 : : struct spdk_bdev_ext_io_opts *opts)
555 : : {
556 : 9 : return spdk_bdev_readv_blocks(desc, ch, iov, iovcnt, offset_blocks, num_blocks, cb, cb_arg);
557 : : }
558 : :
559 : : int
560 : 0 : spdk_bdev_readv_blocks_with_md(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch,
561 : : struct iovec *iov, int iovcnt, void *md,
562 : : uint64_t offset_blocks, uint64_t num_blocks,
563 : : spdk_bdev_io_completion_cb cb, void *cb_arg)
564 : : {
565 : 0 : return spdk_bdev_readv_blocks(desc, ch, iov, iovcnt, offset_blocks, num_blocks, cb, cb_arg);
566 : : }
567 : :
568 : :
569 : : void
570 : 2010 : spdk_bdev_module_release_bdev(struct spdk_bdev *bdev)
571 : : {
572 : 2010 : CU_ASSERT(bdev->internal.claim_type == SPDK_BDEV_CLAIM_EXCL_WRITE);
573 : 2010 : CU_ASSERT(bdev->internal.claim.v1.module != NULL);
574 : 2010 : bdev->internal.claim_type = SPDK_BDEV_CLAIM_NONE;
575 : 2010 : bdev->internal.claim.v1.module = NULL;
576 : 2010 : }
577 : :
578 : : int
579 : 2016 : spdk_bdev_module_claim_bdev(struct spdk_bdev *bdev, struct spdk_bdev_desc *desc,
580 : : struct spdk_bdev_module *module)
581 : : {
582 [ + + ]: 2016 : if (bdev->internal.claim_type != SPDK_BDEV_CLAIM_NONE) {
583 : 6 : CU_ASSERT(bdev->internal.claim.v1.module != NULL);
584 : 6 : return -1;
585 : : }
586 : 2010 : CU_ASSERT(bdev->internal.claim.v1.module == NULL);
587 : 2010 : bdev->internal.claim_type = SPDK_BDEV_CLAIM_EXCL_WRITE;
588 : 2010 : bdev->internal.claim.v1.module = module;
589 : 2010 : return 0;
590 : : }
591 : :
592 : : int
593 : 162 : spdk_json_decode_object(const struct spdk_json_val *values,
594 : : const struct spdk_json_object_decoder *decoders, size_t num_decoders,
595 : : void *out)
596 : : {
597 : : struct rpc_bdev_raid_create *req, *_out;
598 : : size_t i;
599 : :
600 [ + + ]: 162 : if (g_json_decode_obj_err) {
601 : 9 : return -1;
602 [ + + ]: 153 : } else if (g_json_decode_obj_create) {
603 : 75 : req = g_rpc_req;
604 : 75 : _out = out;
605 : :
606 [ - + ]: 75 : _out->name = strdup(req->name);
607 [ - + ]: 75 : SPDK_CU_ASSERT_FATAL(_out->name != NULL);
608 : 75 : _out->strip_size_kb = req->strip_size_kb;
609 : 75 : _out->level = req->level;
610 [ - + ]: 75 : _out->superblock_enabled = req->superblock_enabled;
611 : 75 : _out->base_bdevs.num_base_bdevs = req->base_bdevs.num_base_bdevs;
612 [ + + ]: 2475 : for (i = 0; i < req->base_bdevs.num_base_bdevs; i++) {
613 [ - + ]: 2400 : _out->base_bdevs.base_bdevs[i] = strdup(req->base_bdevs.base_bdevs[i]);
614 [ - + ]: 2400 : SPDK_CU_ASSERT_FATAL(_out->base_bdevs.base_bdevs[i]);
615 : : }
616 : : } else {
617 [ - + - + ]: 78 : memcpy(out, g_rpc_req, g_rpc_req_size);
618 : : }
619 : :
620 : 153 : return 0;
621 : : }
622 : :
623 : : struct spdk_json_write_ctx *
624 : 15 : spdk_jsonrpc_begin_result(struct spdk_jsonrpc_request *request)
625 : : {
626 : 15 : return (void *)1;
627 : : }
628 : :
629 : : void
630 : 12 : spdk_jsonrpc_send_error_response(struct spdk_jsonrpc_request *request,
631 : : int error_code, const char *msg)
632 : : {
633 : 12 : g_rpc_err = 1;
634 : 12 : }
635 : :
636 : : void
637 : 18 : spdk_jsonrpc_send_error_response_fmt(struct spdk_jsonrpc_request *request,
638 : : int error_code, const char *fmt, ...)
639 : : {
640 : 18 : g_rpc_err = 1;
641 : 18 : }
642 : :
643 : : struct spdk_bdev *
644 : 2133 : spdk_bdev_get_by_name(const char *bdev_name)
645 : : {
646 : : struct spdk_bdev *bdev;
647 : :
648 [ + - ]: 2133 : if (!TAILQ_EMPTY(&g_bdev_list)) {
649 [ + + ]: 53553 : TAILQ_FOREACH(bdev, &g_bdev_list, internal.link) {
650 [ + + - + : 53550 : if (strcmp(bdev_name, bdev->name) == 0) {
+ + ]
651 : 2130 : return bdev;
652 : : }
653 : : }
654 : : }
655 : :
656 : 3 : return NULL;
657 : : }
658 : :
659 : : int
660 : 3 : spdk_bdev_quiesce(struct spdk_bdev *bdev, struct spdk_bdev_module *module,
661 : : spdk_bdev_quiesce_cb cb_fn, void *cb_arg)
662 : : {
663 [ + - ]: 3 : if (cb_fn) {
664 : 3 : cb_fn(cb_arg, 0);
665 : : }
666 : :
667 : 3 : return 0;
668 : : }
669 : :
670 : : int
671 : 3 : spdk_bdev_unquiesce(struct spdk_bdev *bdev, struct spdk_bdev_module *module,
672 : : spdk_bdev_quiesce_cb cb_fn, void *cb_arg)
673 : : {
674 [ + - ]: 3 : if (cb_fn) {
675 : 3 : cb_fn(cb_arg, 0);
676 : : }
677 : :
678 : 3 : return 0;
679 : : }
680 : :
681 : : int
682 : 48 : spdk_bdev_quiesce_range(struct spdk_bdev *bdev, struct spdk_bdev_module *module,
683 : : uint64_t offset, uint64_t length,
684 : : spdk_bdev_quiesce_cb cb_fn, void *cb_arg)
685 : : {
686 [ + - ]: 48 : if (cb_fn) {
687 : 48 : cb_fn(cb_arg, 0);
688 : : }
689 : :
690 : 48 : return 0;
691 : : }
692 : :
693 : : int
694 : 48 : spdk_bdev_unquiesce_range(struct spdk_bdev *bdev, struct spdk_bdev_module *module,
695 : : uint64_t offset, uint64_t length,
696 : : spdk_bdev_quiesce_cb cb_fn, void *cb_arg)
697 : : {
698 [ + - ]: 48 : if (cb_fn) {
699 : 48 : cb_fn(cb_arg, 0);
700 : : }
701 : :
702 : 48 : return 0;
703 : : }
704 : :
705 : : static void
706 : 2922 : bdev_io_cleanup(struct spdk_bdev_io *bdev_io)
707 : : {
708 [ + - ]: 2922 : if (bdev_io->u.bdev.iovs) {
709 : : int i;
710 : :
711 [ + + ]: 5853 : for (i = 0; i < bdev_io->u.bdev.iovcnt; i++) {
712 : 2931 : free(bdev_io->u.bdev.iovs[i].iov_base);
713 : : }
714 : 2922 : free(bdev_io->u.bdev.iovs);
715 : : }
716 : 2922 : free(bdev_io);
717 : 2922 : }
718 : :
719 : : static void
720 : 2922 : _bdev_io_initialize(struct spdk_bdev_io *bdev_io, struct spdk_io_channel *ch,
721 : : struct spdk_bdev *bdev, uint64_t lba, uint64_t blocks, int16_t iotype,
722 : : int iovcnt, size_t iov_len)
723 : : {
724 : 2922 : struct spdk_bdev_channel *channel = spdk_io_channel_get_ctx(ch);
725 : : int i;
726 : :
727 : 2922 : bdev_io->bdev = bdev;
728 : 2922 : bdev_io->u.bdev.offset_blocks = lba;
729 : 2922 : bdev_io->u.bdev.num_blocks = blocks;
730 : 2922 : bdev_io->type = iotype;
731 : 2922 : bdev_io->internal.ch = channel;
732 : 2922 : bdev_io->u.bdev.iovcnt = iovcnt;
733 : :
734 [ - + ]: 2922 : if (iovcnt == 0) {
735 : 0 : bdev_io->u.bdev.iovs = NULL;
736 : 0 : return;
737 : : }
738 : :
739 [ - + ]: 2922 : SPDK_CU_ASSERT_FATAL(iov_len * iovcnt == blocks * g_block_len);
740 : :
741 : 2922 : bdev_io->u.bdev.iovs = calloc(iovcnt, sizeof(struct iovec));
742 [ - + ]: 2922 : SPDK_CU_ASSERT_FATAL(bdev_io->u.bdev.iovs != NULL);
743 : :
744 [ + + ]: 5853 : for (i = 0; i < iovcnt; i++) {
745 : 2931 : struct iovec *iov = &bdev_io->u.bdev.iovs[i];
746 : :
747 : 2931 : iov->iov_base = calloc(1, iov_len);
748 [ - + ]: 2931 : SPDK_CU_ASSERT_FATAL(iov->iov_base != NULL);
749 : 2931 : iov->iov_len = iov_len;
750 : : }
751 : : }
752 : :
753 : : static void
754 : 2919 : bdev_io_initialize(struct spdk_bdev_io *bdev_io, struct spdk_io_channel *ch, struct spdk_bdev *bdev,
755 : : uint64_t lba, uint64_t blocks, int16_t iotype)
756 : : {
757 : : int iovcnt;
758 : : size_t iov_len;
759 : :
760 [ + - - + ]: 2919 : if (bdev_io->type == SPDK_BDEV_IO_TYPE_UNMAP || bdev_io->type == SPDK_BDEV_IO_TYPE_FLUSH) {
761 : 0 : iovcnt = 0;
762 : 0 : iov_len = 0;
763 : : } else {
764 : 2919 : iovcnt = 1;
765 : 2919 : iov_len = blocks * g_block_len;
766 : : }
767 : :
768 : 2919 : _bdev_io_initialize(bdev_io, ch, bdev, lba, blocks, iotype, iovcnt, iov_len);
769 : 2919 : }
770 : :
771 : : static void
772 : 3 : verify_reset_io(struct spdk_bdev_io *bdev_io, uint8_t num_base_drives,
773 : : struct raid_bdev_io_channel *ch_ctx, struct raid_bdev *raid_bdev, uint32_t io_status)
774 : : {
775 : 3 : uint8_t index = 0;
776 : : struct io_output *output;
777 : :
778 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(raid_bdev != NULL);
779 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(num_base_drives != 0);
780 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(io_status != INVALID_IO_SUBMIT);
781 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch_ctx->base_channel != NULL);
782 : :
783 : 3 : CU_ASSERT(g_io_output_index == num_base_drives);
784 [ + + ]: 99 : for (index = 0; index < g_io_output_index; index++) {
785 : 96 : output = &g_io_output[index];
786 : 96 : CU_ASSERT(ch_ctx->base_channel[index] == output->ch);
787 : 96 : CU_ASSERT(raid_bdev->base_bdev_info[index].desc == output->desc);
788 : 96 : CU_ASSERT(bdev_io->type == output->iotype);
789 : : }
790 : 3 : CU_ASSERT(g_io_comp_status == io_status);
791 : 3 : }
792 : :
793 : : static void
794 : 24 : verify_io(struct spdk_bdev_io *bdev_io, uint8_t num_base_drives,
795 : : struct raid_bdev_io_channel *ch_ctx, struct raid_bdev *raid_bdev, uint32_t io_status)
796 : : {
797 : 24 : uint32_t strip_shift = spdk_u32log2(g_strip_size);
798 [ - + ]: 24 : uint64_t start_strip = bdev_io->u.bdev.offset_blocks >> strip_shift;
799 [ - + ]: 24 : uint64_t end_strip = (bdev_io->u.bdev.offset_blocks + bdev_io->u.bdev.num_blocks - 1) >>
800 : : strip_shift;
801 : 24 : uint32_t splits_reqd = (end_strip - start_strip + 1);
802 : : uint32_t strip;
803 : : uint64_t pd_strip;
804 : : uint8_t pd_idx;
805 : : uint32_t offset_in_strip;
806 : : uint64_t pd_lba;
807 : : uint64_t pd_blocks;
808 : 24 : uint32_t index = 0;
809 : : struct io_output *output;
810 : :
811 [ + + ]: 24 : if (io_status == INVALID_IO_SUBMIT) {
812 : 3 : CU_ASSERT(g_io_comp_status == false);
813 : 3 : return;
814 : : }
815 [ - + ]: 21 : SPDK_CU_ASSERT_FATAL(raid_bdev != NULL);
816 [ - + ]: 21 : SPDK_CU_ASSERT_FATAL(num_base_drives != 0);
817 : :
818 : 21 : CU_ASSERT(splits_reqd == g_io_output_index);
819 [ + + ]: 42 : for (strip = start_strip; strip <= end_strip; strip++, index++) {
820 [ - + ]: 21 : pd_strip = strip / num_base_drives;
821 [ - + ]: 21 : pd_idx = strip % num_base_drives;
822 [ + - ]: 21 : if (strip == start_strip) {
823 : 21 : offset_in_strip = bdev_io->u.bdev.offset_blocks & (g_strip_size - 1);
824 [ - + ]: 21 : pd_lba = (pd_strip << strip_shift) + offset_in_strip;
825 [ + - ]: 21 : if (strip == end_strip) {
826 : 21 : pd_blocks = bdev_io->u.bdev.num_blocks;
827 : : } else {
828 : 0 : pd_blocks = g_strip_size - offset_in_strip;
829 : : }
830 [ # # ]: 0 : } else if (strip == end_strip) {
831 [ # # ]: 0 : pd_lba = pd_strip << strip_shift;
832 : 0 : pd_blocks = ((bdev_io->u.bdev.offset_blocks + bdev_io->u.bdev.num_blocks - 1) &
833 : 0 : (g_strip_size - 1)) + 1;
834 : : } else {
835 [ # # ]: 0 : pd_lba = pd_strip << raid_bdev->strip_size_shift;
836 : 0 : pd_blocks = raid_bdev->strip_size;
837 : : }
838 : 21 : output = &g_io_output[index];
839 : 21 : CU_ASSERT(pd_lba == output->offset_blocks);
840 : 21 : CU_ASSERT(pd_blocks == output->num_blocks);
841 : 21 : CU_ASSERT(ch_ctx->base_channel[pd_idx] == output->ch);
842 : 21 : CU_ASSERT(raid_bdev->base_bdev_info[pd_idx].desc == output->desc);
843 : 21 : CU_ASSERT(bdev_io->type == output->iotype);
844 : : }
845 : 21 : CU_ASSERT(g_io_comp_status == io_status);
846 : : }
847 : :
848 : : static void
849 : 2889 : verify_io_without_payload(struct spdk_bdev_io *bdev_io, uint8_t num_base_drives,
850 : : struct raid_bdev_io_channel *ch_ctx, struct raid_bdev *raid_bdev,
851 : : uint32_t io_status)
852 : : {
853 : 2889 : uint32_t strip_shift = spdk_u32log2(g_strip_size);
854 [ - + ]: 2889 : uint64_t start_offset_in_strip = bdev_io->u.bdev.offset_blocks % g_strip_size;
855 [ - + ]: 2889 : uint64_t end_offset_in_strip = (bdev_io->u.bdev.offset_blocks + bdev_io->u.bdev.num_blocks - 1) %
856 : : g_strip_size;
857 [ - + ]: 2889 : uint64_t start_strip = bdev_io->u.bdev.offset_blocks >> strip_shift;
858 [ - + ]: 2889 : uint64_t end_strip = (bdev_io->u.bdev.offset_blocks + bdev_io->u.bdev.num_blocks - 1) >>
859 : : strip_shift;
860 : : uint8_t n_disks_involved;
861 : : uint64_t start_strip_disk_idx;
862 : : uint64_t end_strip_disk_idx;
863 : : uint64_t nblocks_in_start_disk;
864 : : uint64_t offset_in_start_disk;
865 : : uint8_t disk_idx;
866 : : uint64_t base_io_idx;
867 : 2889 : uint64_t sum_nblocks = 0;
868 : : struct io_output *output;
869 : :
870 [ - + ]: 2889 : if (io_status == INVALID_IO_SUBMIT) {
871 : 0 : CU_ASSERT(g_io_comp_status == false);
872 : 0 : return;
873 : : }
874 [ - + ]: 2889 : SPDK_CU_ASSERT_FATAL(raid_bdev != NULL);
875 [ - + ]: 2889 : SPDK_CU_ASSERT_FATAL(num_base_drives != 0);
876 [ - + ]: 2889 : SPDK_CU_ASSERT_FATAL(bdev_io->type != SPDK_BDEV_IO_TYPE_READ);
877 [ - + ]: 2889 : SPDK_CU_ASSERT_FATAL(bdev_io->type != SPDK_BDEV_IO_TYPE_WRITE);
878 : :
879 : 2889 : n_disks_involved = spdk_min(end_strip - start_strip + 1, num_base_drives);
880 : 2889 : CU_ASSERT(n_disks_involved == g_io_output_index);
881 : :
882 [ - + ]: 2889 : start_strip_disk_idx = start_strip % num_base_drives;
883 [ - + ]: 2889 : end_strip_disk_idx = end_strip % num_base_drives;
884 : :
885 : 2889 : offset_in_start_disk = g_io_output[0].offset_blocks;
886 : 2889 : nblocks_in_start_disk = g_io_output[0].num_blocks;
887 : :
888 [ + + ]: 55998 : for (base_io_idx = 0, disk_idx = start_strip_disk_idx; base_io_idx < n_disks_involved;
889 : 53109 : base_io_idx++, disk_idx++) {
890 : : uint64_t start_offset_in_disk;
891 : : uint64_t end_offset_in_disk;
892 : :
893 : 53109 : output = &g_io_output[base_io_idx];
894 : :
895 : : /* round disk_idx */
896 [ + + ]: 53109 : if (disk_idx >= num_base_drives) {
897 [ - + ]: 1485 : disk_idx %= num_base_drives;
898 : : }
899 : :
900 : : /* start_offset_in_disk aligned in strip check:
901 : : * The first base io has a same start_offset_in_strip with the whole raid io.
902 : : * Other base io should have aligned start_offset_in_strip which is 0.
903 : : */
904 : 53109 : start_offset_in_disk = output->offset_blocks;
905 [ + + ]: 53109 : if (base_io_idx == 0) {
906 [ - + ]: 2889 : CU_ASSERT(start_offset_in_disk % g_strip_size == start_offset_in_strip);
907 : : } else {
908 [ - + ]: 50220 : CU_ASSERT(start_offset_in_disk % g_strip_size == 0);
909 : : }
910 : :
911 : : /* end_offset_in_disk aligned in strip check:
912 : : * Base io on disk at which end_strip is located, has a same end_offset_in_strip
913 : : * with the whole raid io.
914 : : * Other base io should have aligned end_offset_in_strip.
915 : : */
916 : 53109 : end_offset_in_disk = output->offset_blocks + output->num_blocks - 1;
917 [ + + ]: 53109 : if (disk_idx == end_strip_disk_idx) {
918 [ - + ]: 2889 : CU_ASSERT(end_offset_in_disk % g_strip_size == end_offset_in_strip);
919 : : } else {
920 [ - + ]: 50220 : CU_ASSERT(end_offset_in_disk % g_strip_size == g_strip_size - 1);
921 : : }
922 : :
923 : : /* start_offset_in_disk compared with start_disk.
924 : : * 1. For disk_idx which is larger than start_strip_disk_idx: Its start_offset_in_disk
925 : : * mustn't be larger than the start offset of start_offset_in_disk; And the gap
926 : : * must be less than strip size.
927 : : * 2. For disk_idx which is less than start_strip_disk_idx, Its start_offset_in_disk
928 : : * must be larger than the start offset of start_offset_in_disk; And the gap mustn't
929 : : * be less than strip size.
930 : : */
931 [ + + ]: 53109 : if (disk_idx > start_strip_disk_idx) {
932 : 28080 : CU_ASSERT(start_offset_in_disk <= offset_in_start_disk);
933 : 28080 : CU_ASSERT(offset_in_start_disk - start_offset_in_disk < g_strip_size);
934 [ + + ]: 25029 : } else if (disk_idx < start_strip_disk_idx) {
935 : 22140 : CU_ASSERT(start_offset_in_disk > offset_in_start_disk);
936 : 22140 : CU_ASSERT(output->offset_blocks - offset_in_start_disk <= g_strip_size);
937 : : }
938 : :
939 : : /* nblocks compared with start_disk:
940 : : * The gap between them must be within a strip size.
941 : : */
942 [ + + ]: 53109 : if (output->num_blocks <= nblocks_in_start_disk) {
943 : 21132 : CU_ASSERT(nblocks_in_start_disk - output->num_blocks <= g_strip_size);
944 : : } else {
945 : 31977 : CU_ASSERT(output->num_blocks - nblocks_in_start_disk < g_strip_size);
946 : : }
947 : :
948 : 53109 : sum_nblocks += output->num_blocks;
949 : :
950 : 53109 : CU_ASSERT(ch_ctx->base_channel[disk_idx] == output->ch);
951 : 53109 : CU_ASSERT(raid_bdev->base_bdev_info[disk_idx].desc == output->desc);
952 : 53109 : CU_ASSERT(bdev_io->type == output->iotype);
953 : : }
954 : :
955 : : /* Sum of each nblocks should be same with raid bdev_io */
956 : 2889 : CU_ASSERT(bdev_io->u.bdev.num_blocks == sum_nblocks);
957 : :
958 : 2889 : CU_ASSERT(g_io_comp_status == io_status);
959 : : }
960 : :
961 : : static void
962 : 126 : verify_raid_bdev_present(const char *name, bool presence)
963 : : {
964 : : struct raid_bdev *pbdev;
965 : : bool pbdev_found;
966 : :
967 : 126 : pbdev_found = false;
968 [ + + ]: 150 : TAILQ_FOREACH(pbdev, &g_raid_bdev_list, global_link) {
969 [ + + - + : 36 : if (strcmp(pbdev->bdev.name, name) == 0) {
+ + ]
970 : 12 : pbdev_found = true;
971 : 12 : break;
972 : : }
973 : : }
974 [ + + ]: 126 : if (presence == true) {
975 : 12 : CU_ASSERT(pbdev_found == true);
976 : : } else {
977 : 114 : CU_ASSERT(pbdev_found == false);
978 : : }
979 : 126 : }
980 : :
981 : : static void
982 : 54 : verify_raid_bdev(struct rpc_bdev_raid_create *r, bool presence, uint32_t raid_state)
983 : : {
984 : : struct raid_bdev *pbdev;
985 : : struct raid_base_bdev_info *base_info;
986 : 54 : struct spdk_bdev *bdev = NULL;
987 : : bool pbdev_found;
988 : 54 : uint64_t min_blockcnt = 0xFFFFFFFFFFFFFFFF;
989 : :
990 : 54 : pbdev_found = false;
991 [ + - ]: 60 : TAILQ_FOREACH(pbdev, &g_raid_bdev_list, global_link) {
992 [ + + - + : 60 : if (strcmp(pbdev->bdev.name, r->name) == 0) {
+ + ]
993 : 54 : pbdev_found = true;
994 [ - + ]: 54 : if (presence == false) {
995 : 0 : break;
996 : : }
997 : 54 : CU_ASSERT(pbdev->base_bdev_info != NULL);
998 [ - + ]: 54 : CU_ASSERT(pbdev->strip_size == ((r->strip_size_kb * 1024) / g_block_len));
999 [ - + ]: 54 : CU_ASSERT(pbdev->strip_size_shift == spdk_u32log2(((r->strip_size_kb * 1024) /
1000 : : g_block_len)));
1001 : 54 : CU_ASSERT(pbdev->blocklen_shift == spdk_u32log2(g_block_len));
1002 : 54 : CU_ASSERT((uint32_t)pbdev->state == raid_state);
1003 : 54 : CU_ASSERT(pbdev->num_base_bdevs == r->base_bdevs.num_base_bdevs);
1004 : 54 : CU_ASSERT(pbdev->num_base_bdevs_discovered == r->base_bdevs.num_base_bdevs);
1005 : 54 : CU_ASSERT(pbdev->level == r->level);
1006 : 54 : CU_ASSERT(pbdev->base_bdev_info != NULL);
1007 [ + + ]: 1782 : RAID_FOR_EACH_BASE_BDEV(pbdev, base_info) {
1008 : 1728 : CU_ASSERT(base_info->desc != NULL);
1009 : 1728 : bdev = spdk_bdev_desc_get_bdev(base_info->desc);
1010 : 1728 : CU_ASSERT(bdev != NULL);
1011 [ - + ]: 1728 : CU_ASSERT(base_info->remove_scheduled == false);
1012 [ + + - + : 1728 : CU_ASSERT((pbdev->sb != NULL && base_info->data_offset != 0) ||
+ - + - ]
1013 : : (pbdev->sb == NULL && base_info->data_offset == 0));
1014 : 1728 : CU_ASSERT(base_info->data_offset + base_info->data_size == bdev->blockcnt);
1015 : :
1016 [ + - + + ]: 1728 : if (bdev && base_info->data_size < min_blockcnt) {
1017 : 54 : min_blockcnt = base_info->data_size;
1018 : : }
1019 : : }
1020 [ - + - + : 54 : CU_ASSERT((((min_blockcnt / (r->strip_size_kb * 1024 / g_block_len)) *
- + ]
1021 : : (r->strip_size_kb * 1024 / g_block_len)) *
1022 : : r->base_bdevs.num_base_bdevs) == pbdev->bdev.blockcnt);
1023 [ - + ]: 54 : CU_ASSERT(strcmp(pbdev->bdev.product_name, "Raid Volume") == 0);
1024 : 54 : CU_ASSERT(pbdev->bdev.write_cache == 0);
1025 : 54 : CU_ASSERT(pbdev->bdev.blocklen == g_block_len);
1026 [ + - ]: 54 : if (pbdev->num_base_bdevs > 1) {
1027 : 54 : CU_ASSERT(pbdev->bdev.optimal_io_boundary == pbdev->strip_size);
1028 [ - + ]: 54 : CU_ASSERT(pbdev->bdev.split_on_optimal_io_boundary == true);
1029 : : } else {
1030 : 0 : CU_ASSERT(pbdev->bdev.optimal_io_boundary == 0);
1031 [ # # ]: 0 : CU_ASSERT(pbdev->bdev.split_on_optimal_io_boundary == false);
1032 : : }
1033 : 54 : CU_ASSERT(pbdev->bdev.ctxt == pbdev);
1034 : 54 : CU_ASSERT(pbdev->bdev.fn_table == &g_raid_bdev_fn_table);
1035 : 54 : CU_ASSERT(pbdev->bdev.module == &g_raid_if);
1036 : 54 : break;
1037 : : }
1038 : : }
1039 [ + - ]: 54 : if (presence == true) {
1040 : 54 : CU_ASSERT(pbdev_found == true);
1041 : : } else {
1042 : 0 : CU_ASSERT(pbdev_found == false);
1043 : : }
1044 : 54 : }
1045 : :
1046 : : static void
1047 : 6 : verify_get_raids(struct rpc_bdev_raid_create *construct_req,
1048 : : uint8_t g_max_raids,
1049 : : char **g_get_raids_output, uint32_t g_get_raids_count)
1050 : : {
1051 : : uint8_t i, j;
1052 : : bool found;
1053 : :
1054 : 6 : CU_ASSERT(g_max_raids == g_get_raids_count);
1055 [ + - ]: 6 : if (g_max_raids == g_get_raids_count) {
1056 [ + + ]: 18 : for (i = 0; i < g_max_raids; i++) {
1057 : 12 : found = false;
1058 [ + - ]: 12 : for (j = 0; j < g_max_raids; j++) {
1059 [ + - ]: 12 : if (construct_req[i].name &&
1060 [ + + - + : 12 : strcmp(construct_req[i].name, g_get_raids_output[i]) == 0) {
+ - ]
1061 : 12 : found = true;
1062 : 12 : break;
1063 : : }
1064 : : }
1065 : 12 : CU_ASSERT(found == true);
1066 : : }
1067 : : }
1068 : 6 : }
1069 : :
1070 : : static void
1071 : 60 : create_base_bdevs(uint32_t bbdev_start_idx)
1072 : : {
1073 : : uint8_t i;
1074 : : struct spdk_bdev *base_bdev;
1075 : 60 : char name[16];
1076 : :
1077 [ + + ]: 1980 : for (i = 0; i < g_max_base_drives; i++, bbdev_start_idx++) {
1078 : 1920 : snprintf(name, 16, "%s%u%s", "Nvme", bbdev_start_idx, "n1");
1079 : 1920 : base_bdev = calloc(1, sizeof(struct spdk_bdev));
1080 [ - + ]: 1920 : SPDK_CU_ASSERT_FATAL(base_bdev != NULL);
1081 : 1920 : base_bdev->name = strdup(name);
1082 : 1920 : spdk_uuid_generate(&base_bdev->uuid);
1083 [ - + ]: 1920 : SPDK_CU_ASSERT_FATAL(base_bdev->name != NULL);
1084 : 1920 : base_bdev->blocklen = g_block_len;
1085 : 1920 : base_bdev->blockcnt = BLOCK_CNT;
1086 : 1920 : TAILQ_INSERT_TAIL(&g_bdev_list, base_bdev, internal.link);
1087 : : }
1088 : 60 : }
1089 : :
1090 : : static void
1091 : 78 : create_test_req(struct rpc_bdev_raid_create *r, const char *raid_name,
1092 : : uint8_t bbdev_start_idx, bool create_base_bdev, bool superblock_enabled)
1093 : : {
1094 : : uint8_t i;
1095 : 78 : char name[16];
1096 : 78 : uint8_t bbdev_idx = bbdev_start_idx;
1097 : :
1098 [ - + ]: 78 : r->name = strdup(raid_name);
1099 [ - + ]: 78 : SPDK_CU_ASSERT_FATAL(r->name != NULL);
1100 : 78 : r->strip_size_kb = (g_strip_size * g_block_len) / 1024;
1101 : 78 : r->level = RAID0;
1102 : 78 : r->superblock_enabled = superblock_enabled;
1103 : 78 : r->base_bdevs.num_base_bdevs = g_max_base_drives;
1104 [ + + ]: 2574 : for (i = 0; i < g_max_base_drives; i++, bbdev_idx++) {
1105 : 2496 : snprintf(name, 16, "%s%u%s", "Nvme", bbdev_idx, "n1");
1106 : 2496 : r->base_bdevs.base_bdevs[i] = strdup(name);
1107 [ - + ]: 2496 : SPDK_CU_ASSERT_FATAL(r->base_bdevs.base_bdevs[i] != NULL);
1108 : : }
1109 [ + + ]: 78 : if (create_base_bdev == true) {
1110 : 60 : create_base_bdevs(bbdev_start_idx);
1111 : : }
1112 : 78 : g_rpc_req = r;
1113 : 78 : g_rpc_req_size = sizeof(*r);
1114 : 78 : }
1115 : :
1116 : : static void
1117 : 78 : create_raid_bdev_create_req(struct rpc_bdev_raid_create *r, const char *raid_name,
1118 : : uint8_t bbdev_start_idx, bool create_base_bdev,
1119 : : uint8_t json_decode_obj_err, bool superblock_enabled)
1120 : : {
1121 : 78 : create_test_req(r, raid_name, bbdev_start_idx, create_base_bdev, superblock_enabled);
1122 : :
1123 : 78 : g_rpc_err = 0;
1124 : 78 : g_json_decode_obj_create = 1;
1125 : 78 : g_json_decode_obj_err = json_decode_obj_err;
1126 : 78 : g_config_level_create = 0;
1127 : 78 : g_test_multi_raids = 0;
1128 : 78 : }
1129 : :
1130 : : static void
1131 : 78 : free_test_req(struct rpc_bdev_raid_create *r)
1132 : : {
1133 : : uint8_t i;
1134 : :
1135 : 78 : free(r->name);
1136 [ + + ]: 2574 : for (i = 0; i < r->base_bdevs.num_base_bdevs; i++) {
1137 : 2496 : free(r->base_bdevs.base_bdevs[i]);
1138 : : }
1139 : 78 : }
1140 : :
1141 : : static void
1142 : 63 : create_raid_bdev_delete_req(struct rpc_bdev_raid_delete *r, const char *raid_name,
1143 : : uint8_t json_decode_obj_err)
1144 : : {
1145 [ - + ]: 63 : r->name = strdup(raid_name);
1146 [ - + ]: 63 : SPDK_CU_ASSERT_FATAL(r->name != NULL);
1147 : :
1148 : 63 : g_rpc_req = r;
1149 : 63 : g_rpc_req_size = sizeof(*r);
1150 : 63 : g_rpc_err = 0;
1151 : 63 : g_json_decode_obj_create = 0;
1152 : 63 : g_json_decode_obj_err = json_decode_obj_err;
1153 : 63 : g_config_level_create = 0;
1154 : 63 : g_test_multi_raids = 0;
1155 : 63 : }
1156 : :
1157 : : static void
1158 : 21 : create_get_raids_req(struct rpc_bdev_raid_get_bdevs *r, const char *category,
1159 : : uint8_t json_decode_obj_err)
1160 : : {
1161 [ - + ]: 21 : r->category = strdup(category);
1162 [ - + ]: 21 : SPDK_CU_ASSERT_FATAL(r->category != NULL);
1163 : :
1164 : 21 : g_rpc_req = r;
1165 : 21 : g_rpc_req_size = sizeof(*r);
1166 : 21 : g_rpc_err = 0;
1167 : 21 : g_json_decode_obj_create = 0;
1168 : 21 : g_json_decode_obj_err = json_decode_obj_err;
1169 : 21 : g_config_level_create = 0;
1170 : 21 : g_test_multi_raids = 1;
1171 : 21 : g_get_raids_count = 0;
1172 : 21 : }
1173 : :
1174 : : static void
1175 : 3 : test_create_raid(void)
1176 : : {
1177 : 3 : struct rpc_bdev_raid_create req;
1178 : 3 : struct rpc_bdev_raid_delete delete_req;
1179 : :
1180 : 3 : set_globals();
1181 : 3 : CU_ASSERT(raid_bdev_init() == 0);
1182 : :
1183 : 3 : verify_raid_bdev_present("raid1", false);
1184 : 3 : create_raid_bdev_create_req(&req, "raid1", 0, true, 0, false);
1185 : 3 : rpc_bdev_raid_create(NULL, NULL);
1186 : 3 : CU_ASSERT(g_rpc_err == 0);
1187 : 3 : verify_raid_bdev(&req, true, RAID_BDEV_STATE_ONLINE);
1188 : 3 : free_test_req(&req);
1189 : :
1190 : 3 : create_raid_bdev_delete_req(&delete_req, "raid1", 0);
1191 : 3 : rpc_bdev_raid_delete(NULL, NULL);
1192 : 3 : CU_ASSERT(g_rpc_err == 0);
1193 : 3 : raid_bdev_exit();
1194 : 3 : base_bdevs_cleanup();
1195 : 3 : reset_globals();
1196 : 3 : }
1197 : :
1198 : : static void
1199 : 3 : test_delete_raid(void)
1200 : : {
1201 : 3 : struct rpc_bdev_raid_create construct_req;
1202 : 3 : struct rpc_bdev_raid_delete delete_req;
1203 : :
1204 : 3 : set_globals();
1205 : 3 : CU_ASSERT(raid_bdev_init() == 0);
1206 : :
1207 : 3 : verify_raid_bdev_present("raid1", false);
1208 : 3 : create_raid_bdev_create_req(&construct_req, "raid1", 0, true, 0, false);
1209 : 3 : rpc_bdev_raid_create(NULL, NULL);
1210 : 3 : CU_ASSERT(g_rpc_err == 0);
1211 : 3 : verify_raid_bdev(&construct_req, true, RAID_BDEV_STATE_ONLINE);
1212 : 3 : free_test_req(&construct_req);
1213 : :
1214 : 3 : create_raid_bdev_delete_req(&delete_req, "raid1", 0);
1215 : 3 : rpc_bdev_raid_delete(NULL, NULL);
1216 : 3 : CU_ASSERT(g_rpc_err == 0);
1217 : 3 : verify_raid_bdev_present("raid1", false);
1218 : :
1219 : 3 : raid_bdev_exit();
1220 : 3 : base_bdevs_cleanup();
1221 : 3 : reset_globals();
1222 : 3 : }
1223 : :
1224 : : static void
1225 : 3 : test_create_raid_invalid_args(void)
1226 : : {
1227 : 3 : struct rpc_bdev_raid_create req;
1228 : 3 : struct rpc_bdev_raid_delete destroy_req;
1229 : : struct raid_bdev *raid_bdev;
1230 : :
1231 : 3 : set_globals();
1232 : 3 : CU_ASSERT(raid_bdev_init() == 0);
1233 : :
1234 : 3 : verify_raid_bdev_present("raid1", false);
1235 : 3 : create_raid_bdev_create_req(&req, "raid1", 0, true, 0, false);
1236 : 3 : req.level = INVALID_RAID_LEVEL;
1237 : 3 : rpc_bdev_raid_create(NULL, NULL);
1238 : 3 : CU_ASSERT(g_rpc_err == 1);
1239 : 3 : free_test_req(&req);
1240 : 3 : verify_raid_bdev_present("raid1", false);
1241 : :
1242 : 3 : create_raid_bdev_create_req(&req, "raid1", 0, false, 1, false);
1243 : 3 : rpc_bdev_raid_create(NULL, NULL);
1244 : 3 : CU_ASSERT(g_rpc_err == 1);
1245 : 3 : free_test_req(&req);
1246 : 3 : verify_raid_bdev_present("raid1", false);
1247 : :
1248 : 3 : create_raid_bdev_create_req(&req, "raid1", 0, false, 0, false);
1249 : 3 : req.strip_size_kb = 1231;
1250 : 3 : rpc_bdev_raid_create(NULL, NULL);
1251 : 3 : CU_ASSERT(g_rpc_err == 1);
1252 : 3 : free_test_req(&req);
1253 : 3 : verify_raid_bdev_present("raid1", false);
1254 : :
1255 : 3 : create_raid_bdev_create_req(&req, "raid1", 0, false, 0, false);
1256 : 3 : rpc_bdev_raid_create(NULL, NULL);
1257 : 3 : CU_ASSERT(g_rpc_err == 0);
1258 : 3 : verify_raid_bdev(&req, true, RAID_BDEV_STATE_ONLINE);
1259 : 3 : free_test_req(&req);
1260 : :
1261 : 3 : create_raid_bdev_create_req(&req, "raid1", 0, false, 0, false);
1262 : 3 : rpc_bdev_raid_create(NULL, NULL);
1263 : 3 : CU_ASSERT(g_rpc_err == 1);
1264 : 3 : free_test_req(&req);
1265 : :
1266 : 3 : create_raid_bdev_create_req(&req, "raid2", 0, false, 0, false);
1267 : 3 : rpc_bdev_raid_create(NULL, NULL);
1268 : 3 : CU_ASSERT(g_rpc_err == 1);
1269 : 3 : free_test_req(&req);
1270 : 3 : verify_raid_bdev_present("raid2", false);
1271 : :
1272 : 3 : create_raid_bdev_create_req(&req, "raid2", g_max_base_drives, true, 0, false);
1273 : 3 : free(req.base_bdevs.base_bdevs[g_max_base_drives - 1]);
1274 : 3 : req.base_bdevs.base_bdevs[g_max_base_drives - 1] = strdup("Nvme0n1");
1275 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(req.base_bdevs.base_bdevs[g_max_base_drives - 1] != NULL);
1276 : 3 : rpc_bdev_raid_create(NULL, NULL);
1277 : 3 : CU_ASSERT(g_rpc_err == 1);
1278 : 3 : free_test_req(&req);
1279 : 3 : verify_raid_bdev_present("raid2", false);
1280 : :
1281 : 3 : create_raid_bdev_create_req(&req, "raid2", g_max_base_drives, true, 0, false);
1282 : 3 : free(req.base_bdevs.base_bdevs[g_max_base_drives - 1]);
1283 : 3 : req.base_bdevs.base_bdevs[g_max_base_drives - 1] = strdup("Nvme100000n1");
1284 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(req.base_bdevs.base_bdevs[g_max_base_drives - 1] != NULL);
1285 : 3 : rpc_bdev_raid_create(NULL, NULL);
1286 : 3 : CU_ASSERT(g_rpc_err == 0);
1287 : 3 : free_test_req(&req);
1288 : 3 : verify_raid_bdev_present("raid2", true);
1289 : 3 : raid_bdev = raid_bdev_find_by_name("raid2");
1290 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(raid_bdev != NULL);
1291 : 3 : check_and_remove_raid_bdev(raid_bdev);
1292 : :
1293 : 3 : create_raid_bdev_create_req(&req, "raid2", g_max_base_drives, false, 0, false);
1294 : 3 : rpc_bdev_raid_create(NULL, NULL);
1295 : 3 : CU_ASSERT(g_rpc_err == 0);
1296 : 3 : free_test_req(&req);
1297 : 3 : verify_raid_bdev_present("raid2", true);
1298 : 3 : verify_raid_bdev_present("raid1", true);
1299 : :
1300 : 3 : create_raid_bdev_delete_req(&destroy_req, "raid1", 0);
1301 : 3 : rpc_bdev_raid_delete(NULL, NULL);
1302 : 3 : create_raid_bdev_delete_req(&destroy_req, "raid2", 0);
1303 : 3 : rpc_bdev_raid_delete(NULL, NULL);
1304 : 3 : raid_bdev_exit();
1305 : 3 : base_bdevs_cleanup();
1306 : 3 : reset_globals();
1307 : 3 : }
1308 : :
1309 : : static void
1310 : 3 : test_delete_raid_invalid_args(void)
1311 : : {
1312 : 3 : struct rpc_bdev_raid_create construct_req;
1313 : 3 : struct rpc_bdev_raid_delete destroy_req;
1314 : :
1315 : 3 : set_globals();
1316 : 3 : CU_ASSERT(raid_bdev_init() == 0);
1317 : :
1318 : 3 : verify_raid_bdev_present("raid1", false);
1319 : 3 : create_raid_bdev_create_req(&construct_req, "raid1", 0, true, 0, false);
1320 : 3 : rpc_bdev_raid_create(NULL, NULL);
1321 : 3 : CU_ASSERT(g_rpc_err == 0);
1322 : 3 : verify_raid_bdev(&construct_req, true, RAID_BDEV_STATE_ONLINE);
1323 : 3 : free_test_req(&construct_req);
1324 : :
1325 : 3 : create_raid_bdev_delete_req(&destroy_req, "raid2", 0);
1326 : 3 : rpc_bdev_raid_delete(NULL, NULL);
1327 : 3 : CU_ASSERT(g_rpc_err == 1);
1328 : :
1329 : 3 : create_raid_bdev_delete_req(&destroy_req, "raid1", 1);
1330 : 3 : rpc_bdev_raid_delete(NULL, NULL);
1331 : 3 : CU_ASSERT(g_rpc_err == 1);
1332 : 3 : free(destroy_req.name);
1333 : 3 : verify_raid_bdev_present("raid1", true);
1334 : :
1335 : 3 : create_raid_bdev_delete_req(&destroy_req, "raid1", 0);
1336 : 3 : rpc_bdev_raid_delete(NULL, NULL);
1337 : 3 : CU_ASSERT(g_rpc_err == 0);
1338 : 3 : verify_raid_bdev_present("raid1", false);
1339 : :
1340 : 3 : raid_bdev_exit();
1341 : 3 : base_bdevs_cleanup();
1342 : 3 : reset_globals();
1343 : 3 : }
1344 : :
1345 : : static void
1346 : 3 : test_io_channel(void)
1347 : : {
1348 : 3 : struct rpc_bdev_raid_create req;
1349 : 3 : struct rpc_bdev_raid_delete destroy_req;
1350 : : struct raid_bdev *pbdev;
1351 : : struct spdk_io_channel *ch;
1352 : : struct raid_bdev_io_channel *ch_ctx;
1353 : :
1354 : 3 : set_globals();
1355 : 3 : CU_ASSERT(raid_bdev_init() == 0);
1356 : :
1357 : 3 : create_raid_bdev_create_req(&req, "raid1", 0, true, 0, false);
1358 : 3 : verify_raid_bdev_present("raid1", false);
1359 : 3 : rpc_bdev_raid_create(NULL, NULL);
1360 : 3 : CU_ASSERT(g_rpc_err == 0);
1361 : 3 : verify_raid_bdev(&req, true, RAID_BDEV_STATE_ONLINE);
1362 : :
1363 [ + - ]: 3 : TAILQ_FOREACH(pbdev, &g_raid_bdev_list, global_link) {
1364 [ + + + - ]: 3 : if (strcmp(pbdev->bdev.name, "raid1") == 0) {
1365 : 3 : break;
1366 : : }
1367 : : }
1368 : 3 : CU_ASSERT(pbdev != NULL);
1369 : :
1370 : 3 : ch = spdk_get_io_channel(pbdev);
1371 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch != NULL);
1372 : :
1373 : 3 : ch_ctx = spdk_io_channel_get_ctx(ch);
1374 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch_ctx != NULL);
1375 : :
1376 : 3 : free_test_req(&req);
1377 : :
1378 : 3 : spdk_put_io_channel(ch);
1379 : :
1380 : 3 : create_raid_bdev_delete_req(&destroy_req, "raid1", 0);
1381 : 3 : rpc_bdev_raid_delete(NULL, NULL);
1382 : 3 : CU_ASSERT(g_rpc_err == 0);
1383 : 3 : verify_raid_bdev_present("raid1", false);
1384 : :
1385 : 3 : raid_bdev_exit();
1386 : 3 : base_bdevs_cleanup();
1387 : 3 : reset_globals();
1388 : 3 : }
1389 : :
1390 : : static void
1391 : 3 : test_write_io(void)
1392 : : {
1393 : 3 : struct rpc_bdev_raid_create req;
1394 : 3 : struct rpc_bdev_raid_delete destroy_req;
1395 : : struct raid_bdev *pbdev;
1396 : : struct spdk_io_channel *ch;
1397 : : struct raid_bdev_io_channel *ch_ctx;
1398 : : uint8_t i;
1399 : : struct spdk_bdev_io *bdev_io;
1400 : : uint64_t io_len;
1401 : 3 : uint64_t lba = 0;
1402 : :
1403 : 3 : set_globals();
1404 : 3 : CU_ASSERT(raid_bdev_init() == 0);
1405 : :
1406 : 3 : create_raid_bdev_create_req(&req, "raid1", 0, true, 0, false);
1407 : 3 : verify_raid_bdev_present("raid1", false);
1408 : 3 : rpc_bdev_raid_create(NULL, NULL);
1409 : 3 : CU_ASSERT(g_rpc_err == 0);
1410 : 3 : verify_raid_bdev(&req, true, RAID_BDEV_STATE_ONLINE);
1411 [ + - ]: 3 : TAILQ_FOREACH(pbdev, &g_raid_bdev_list, global_link) {
1412 [ + + + - ]: 3 : if (strcmp(pbdev->bdev.name, "raid1") == 0) {
1413 : 3 : break;
1414 : : }
1415 : : }
1416 : 3 : CU_ASSERT(pbdev != NULL);
1417 : :
1418 : 3 : ch = spdk_get_io_channel(pbdev);
1419 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch != NULL);
1420 : :
1421 : 3 : ch_ctx = spdk_io_channel_get_ctx(ch);
1422 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch_ctx != NULL);
1423 : :
1424 : : /* test 2 IO sizes based on global strip size set earlier */
1425 [ + + ]: 9 : for (i = 0; i < 2; i++) {
1426 : 6 : bdev_io = calloc(1, sizeof(struct spdk_bdev_io) + sizeof(struct raid_bdev_io));
1427 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(bdev_io != NULL);
1428 [ - + ]: 6 : io_len = (g_strip_size / 2) << i;
1429 : 6 : bdev_io_initialize(bdev_io, ch, &pbdev->bdev, lba, io_len, SPDK_BDEV_IO_TYPE_WRITE);
1430 : 6 : lba += g_strip_size;
1431 [ - + - + ]: 6 : memset(g_io_output, 0, ((g_max_io_size / g_strip_size) + 1) * sizeof(struct io_output));
1432 : 6 : g_io_output_index = 0;
1433 : 6 : raid_bdev_submit_request(ch, bdev_io);
1434 [ - + ]: 6 : verify_io(bdev_io, req.base_bdevs.num_base_bdevs, ch_ctx, pbdev,
1435 : : g_child_io_status_flag);
1436 : 6 : bdev_io_cleanup(bdev_io);
1437 : : }
1438 : :
1439 : 3 : free_test_req(&req);
1440 : 3 : spdk_put_io_channel(ch);
1441 : 3 : create_raid_bdev_delete_req(&destroy_req, "raid1", 0);
1442 : 3 : rpc_bdev_raid_delete(NULL, NULL);
1443 : 3 : CU_ASSERT(g_rpc_err == 0);
1444 : 3 : verify_raid_bdev_present("raid1", false);
1445 : :
1446 : 3 : raid_bdev_exit();
1447 : 3 : base_bdevs_cleanup();
1448 : 3 : reset_globals();
1449 : 3 : }
1450 : :
1451 : : static void
1452 : 3 : test_read_io(void)
1453 : : {
1454 : 3 : struct rpc_bdev_raid_create req;
1455 : 3 : struct rpc_bdev_raid_delete destroy_req;
1456 : : struct raid_bdev *pbdev;
1457 : : struct spdk_io_channel *ch;
1458 : : struct raid_bdev_io_channel *ch_ctx;
1459 : : uint8_t i;
1460 : : struct spdk_bdev_io *bdev_io;
1461 : : uint64_t io_len;
1462 : : uint64_t lba;
1463 : :
1464 : 3 : set_globals();
1465 : 3 : CU_ASSERT(raid_bdev_init() == 0);
1466 : :
1467 : 3 : verify_raid_bdev_present("raid1", false);
1468 : 3 : create_raid_bdev_create_req(&req, "raid1", 0, true, 0, false);
1469 : 3 : rpc_bdev_raid_create(NULL, NULL);
1470 : 3 : CU_ASSERT(g_rpc_err == 0);
1471 : 3 : verify_raid_bdev(&req, true, RAID_BDEV_STATE_ONLINE);
1472 [ + - ]: 3 : TAILQ_FOREACH(pbdev, &g_raid_bdev_list, global_link) {
1473 [ + + + - ]: 3 : if (strcmp(pbdev->bdev.name, "raid1") == 0) {
1474 : 3 : break;
1475 : : }
1476 : : }
1477 : 3 : CU_ASSERT(pbdev != NULL);
1478 : :
1479 : 3 : ch = spdk_get_io_channel(pbdev);
1480 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch != NULL);
1481 : :
1482 : 3 : ch_ctx = spdk_io_channel_get_ctx(ch);
1483 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch_ctx != NULL);
1484 : :
1485 : : /* test 2 IO sizes based on global strip size set earlier */
1486 : 3 : lba = 0;
1487 [ + + ]: 9 : for (i = 0; i < 2; i++) {
1488 : 6 : bdev_io = calloc(1, sizeof(struct spdk_bdev_io) + sizeof(struct raid_bdev_io));
1489 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(bdev_io != NULL);
1490 [ - + ]: 6 : io_len = (g_strip_size / 2) << i;
1491 : 6 : bdev_io_initialize(bdev_io, ch, &pbdev->bdev, lba, io_len, SPDK_BDEV_IO_TYPE_READ);
1492 : 6 : lba += g_strip_size;
1493 [ - + - + ]: 6 : memset(g_io_output, 0, ((g_max_io_size / g_strip_size) + 1) * sizeof(struct io_output));
1494 : 6 : g_io_output_index = 0;
1495 : 6 : raid_bdev_submit_request(ch, bdev_io);
1496 [ - + ]: 6 : verify_io(bdev_io, req.base_bdevs.num_base_bdevs, ch_ctx, pbdev,
1497 : : g_child_io_status_flag);
1498 : 6 : bdev_io_cleanup(bdev_io);
1499 : : }
1500 : :
1501 : 3 : free_test_req(&req);
1502 : 3 : spdk_put_io_channel(ch);
1503 : 3 : create_raid_bdev_delete_req(&destroy_req, "raid1", 0);
1504 : 3 : rpc_bdev_raid_delete(NULL, NULL);
1505 : 3 : CU_ASSERT(g_rpc_err == 0);
1506 : 3 : verify_raid_bdev_present("raid1", false);
1507 : :
1508 : 3 : raid_bdev_exit();
1509 : 3 : base_bdevs_cleanup();
1510 : 3 : reset_globals();
1511 : 3 : }
1512 : :
1513 : : static void
1514 : 108 : raid_bdev_io_generate_by_strips(uint64_t n_strips)
1515 : : {
1516 : : uint64_t lba;
1517 : : uint64_t nblocks;
1518 : : uint64_t start_offset;
1519 : : uint64_t end_offset;
1520 : 108 : uint64_t offsets_in_strip[3];
1521 : : uint64_t start_bdev_idx;
1522 : : uint64_t start_bdev_offset;
1523 : 108 : uint64_t start_bdev_idxs[3];
1524 : : int i, j, l;
1525 : :
1526 : : /* 3 different situations of offset in strip */
1527 : 108 : offsets_in_strip[0] = 0;
1528 : 108 : offsets_in_strip[1] = g_strip_size >> 1;
1529 : 108 : offsets_in_strip[2] = g_strip_size - 1;
1530 : :
1531 : : /* 3 different situations of start_bdev_idx */
1532 : 108 : start_bdev_idxs[0] = 0;
1533 : 108 : start_bdev_idxs[1] = g_max_base_drives >> 1;
1534 : 108 : start_bdev_idxs[2] = g_max_base_drives - 1;
1535 : :
1536 : : /* consider different offset in strip */
1537 [ + + ]: 432 : for (i = 0; i < 3; i++) {
1538 : 324 : start_offset = offsets_in_strip[i];
1539 [ + + ]: 1296 : for (j = 0; j < 3; j++) {
1540 : 972 : end_offset = offsets_in_strip[j];
1541 [ + + + + ]: 972 : if (n_strips == 1 && start_offset > end_offset) {
1542 : 9 : continue;
1543 : : }
1544 : :
1545 : : /* consider at which base_bdev lba is started. */
1546 [ + + ]: 3852 : for (l = 0; l < 3; l++) {
1547 : 2889 : start_bdev_idx = start_bdev_idxs[l];
1548 : 2889 : start_bdev_offset = start_bdev_idx * g_strip_size;
1549 : 2889 : lba = g_lba_offset + start_bdev_offset + start_offset;
1550 : 2889 : nblocks = (n_strips - 1) * g_strip_size + end_offset - start_offset + 1;
1551 : :
1552 : 2889 : g_io_ranges[g_io_range_idx].lba = lba;
1553 : 2889 : g_io_ranges[g_io_range_idx].nblocks = nblocks;
1554 : :
1555 [ - + ]: 2889 : SPDK_CU_ASSERT_FATAL(g_io_range_idx < MAX_TEST_IO_RANGE);
1556 : 2889 : g_io_range_idx++;
1557 : : }
1558 : : }
1559 : : }
1560 : 108 : }
1561 : :
1562 : : static void
1563 : 3 : raid_bdev_io_generate(void)
1564 : : {
1565 : : uint64_t n_strips;
1566 : 3 : uint64_t n_strips_span = g_max_base_drives;
1567 : 3 : uint64_t n_strips_times[5] = {g_max_base_drives + 1, g_max_base_drives * 2 - 1,
1568 : 3 : g_max_base_drives * 2, g_max_base_drives * 3,
1569 : 3 : g_max_base_drives * 4
1570 : : };
1571 : : uint32_t i;
1572 : :
1573 : 3 : g_io_range_idx = 0;
1574 : :
1575 : : /* consider different number of strips from 1 to strips spanned base bdevs,
1576 : : * and even to times of strips spanned base bdevs
1577 : : */
1578 [ + + ]: 96 : for (n_strips = 1; n_strips < n_strips_span; n_strips++) {
1579 : 93 : raid_bdev_io_generate_by_strips(n_strips);
1580 : : }
1581 : :
1582 [ + + ]: 18 : for (i = 0; i < SPDK_COUNTOF(n_strips_times); i++) {
1583 : 15 : n_strips = n_strips_times[i];
1584 : 15 : raid_bdev_io_generate_by_strips(n_strips);
1585 : : }
1586 : 3 : }
1587 : :
1588 : : static void
1589 : 3 : test_unmap_io(void)
1590 : : {
1591 : 3 : struct rpc_bdev_raid_create req;
1592 : 3 : struct rpc_bdev_raid_delete destroy_req;
1593 : : struct raid_bdev *pbdev;
1594 : : struct spdk_io_channel *ch;
1595 : : struct raid_bdev_io_channel *ch_ctx;
1596 : : struct spdk_bdev_io *bdev_io;
1597 : : uint32_t count;
1598 : : uint64_t io_len;
1599 : : uint64_t lba;
1600 : :
1601 : 3 : set_globals();
1602 : 3 : CU_ASSERT(raid_bdev_init() == 0);
1603 : :
1604 : 3 : verify_raid_bdev_present("raid1", false);
1605 : 3 : create_raid_bdev_create_req(&req, "raid1", 0, true, 0, false);
1606 : 3 : rpc_bdev_raid_create(NULL, NULL);
1607 : 3 : CU_ASSERT(g_rpc_err == 0);
1608 : 3 : verify_raid_bdev(&req, true, RAID_BDEV_STATE_ONLINE);
1609 [ + - ]: 3 : TAILQ_FOREACH(pbdev, &g_raid_bdev_list, global_link) {
1610 [ + + + - ]: 3 : if (strcmp(pbdev->bdev.name, "raid1") == 0) {
1611 : 3 : break;
1612 : : }
1613 : : }
1614 : 3 : CU_ASSERT(pbdev != NULL);
1615 : :
1616 : 3 : ch = spdk_get_io_channel(pbdev);
1617 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch != NULL);
1618 : :
1619 : 3 : ch_ctx = spdk_io_channel_get_ctx(ch);
1620 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch_ctx != NULL);
1621 : :
1622 : 3 : CU_ASSERT(raid_bdev_io_type_supported(pbdev, SPDK_BDEV_IO_TYPE_UNMAP) == true);
1623 : 3 : CU_ASSERT(raid_bdev_io_type_supported(pbdev, SPDK_BDEV_IO_TYPE_FLUSH) == true);
1624 : :
1625 : 3 : raid_bdev_io_generate();
1626 [ + + ]: 2892 : for (count = 0; count < g_io_range_idx; count++) {
1627 : 2889 : bdev_io = calloc(1, sizeof(struct spdk_bdev_io) + sizeof(struct raid_bdev_io));
1628 [ - + ]: 2889 : SPDK_CU_ASSERT_FATAL(bdev_io != NULL);
1629 : 2889 : io_len = g_io_ranges[count].nblocks;
1630 : 2889 : lba = g_io_ranges[count].lba;
1631 : 2889 : bdev_io_initialize(bdev_io, ch, &pbdev->bdev, lba, io_len, SPDK_BDEV_IO_TYPE_UNMAP);
1632 [ - + ]: 2889 : memset(g_io_output, 0, g_max_base_drives * sizeof(struct io_output));
1633 : 2889 : g_io_output_index = 0;
1634 : 2889 : raid_bdev_submit_request(ch, bdev_io);
1635 [ - + ]: 2889 : verify_io_without_payload(bdev_io, req.base_bdevs.num_base_bdevs, ch_ctx, pbdev,
1636 : : g_child_io_status_flag);
1637 : 2889 : bdev_io_cleanup(bdev_io);
1638 : : }
1639 : :
1640 : 3 : free_test_req(&req);
1641 : 3 : spdk_put_io_channel(ch);
1642 : 3 : create_raid_bdev_delete_req(&destroy_req, "raid1", 0);
1643 : 3 : rpc_bdev_raid_delete(NULL, NULL);
1644 : 3 : CU_ASSERT(g_rpc_err == 0);
1645 : 3 : verify_raid_bdev_present("raid1", false);
1646 : :
1647 : 3 : raid_bdev_exit();
1648 : 3 : base_bdevs_cleanup();
1649 : 3 : reset_globals();
1650 : 3 : }
1651 : :
1652 : : /* Test IO failures */
1653 : : static void
1654 : 3 : test_io_failure(void)
1655 : : {
1656 : 3 : struct rpc_bdev_raid_create req;
1657 : 3 : struct rpc_bdev_raid_delete destroy_req;
1658 : : struct raid_bdev *pbdev;
1659 : : struct spdk_io_channel *ch;
1660 : : struct raid_bdev_io_channel *ch_ctx;
1661 : : struct spdk_bdev_io *bdev_io;
1662 : : uint32_t count;
1663 : : uint64_t io_len;
1664 : : uint64_t lba;
1665 : :
1666 : 3 : set_globals();
1667 : 3 : CU_ASSERT(raid_bdev_init() == 0);
1668 : :
1669 : 3 : verify_raid_bdev_present("raid1", false);
1670 : 3 : create_raid_bdev_create_req(&req, "raid1", 0, true, 0, false);
1671 : 3 : rpc_bdev_raid_create(NULL, NULL);
1672 : 3 : CU_ASSERT(g_rpc_err == 0);
1673 : 3 : verify_raid_bdev(&req, true, RAID_BDEV_STATE_ONLINE);
1674 [ + - ]: 3 : TAILQ_FOREACH(pbdev, &g_raid_bdev_list, global_link) {
1675 [ + + - + : 3 : if (strcmp(pbdev->bdev.name, req.name) == 0) {
+ - ]
1676 : 3 : break;
1677 : : }
1678 : : }
1679 : 3 : CU_ASSERT(pbdev != NULL);
1680 : :
1681 : 3 : ch = spdk_get_io_channel(pbdev);
1682 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch != NULL);
1683 : :
1684 : 3 : ch_ctx = spdk_io_channel_get_ctx(ch);
1685 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch_ctx != NULL);
1686 : :
1687 : 3 : lba = 0;
1688 [ + + ]: 6 : for (count = 0; count < 1; count++) {
1689 : 3 : bdev_io = calloc(1, sizeof(struct spdk_bdev_io) + sizeof(struct raid_bdev_io));
1690 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bdev_io != NULL);
1691 [ - + ]: 3 : io_len = (g_strip_size / 2) << count;
1692 : 3 : bdev_io_initialize(bdev_io, ch, &pbdev->bdev, lba, io_len, SPDK_BDEV_IO_TYPE_INVALID);
1693 : 3 : lba += g_strip_size;
1694 [ - + - + ]: 3 : memset(g_io_output, 0, ((g_max_io_size / g_strip_size) + 1) * sizeof(struct io_output));
1695 : 3 : g_io_output_index = 0;
1696 : 3 : raid_bdev_submit_request(ch, bdev_io);
1697 : 3 : verify_io(bdev_io, req.base_bdevs.num_base_bdevs, ch_ctx, pbdev,
1698 : : INVALID_IO_SUBMIT);
1699 : 3 : bdev_io_cleanup(bdev_io);
1700 : : }
1701 : :
1702 : :
1703 : 3 : lba = 0;
1704 : 3 : g_child_io_status_flag = false;
1705 [ + + ]: 6 : for (count = 0; count < 1; count++) {
1706 : 3 : bdev_io = calloc(1, sizeof(struct spdk_bdev_io) + sizeof(struct raid_bdev_io));
1707 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bdev_io != NULL);
1708 [ - + ]: 3 : io_len = (g_strip_size / 2) << count;
1709 : 3 : bdev_io_initialize(bdev_io, ch, &pbdev->bdev, lba, io_len, SPDK_BDEV_IO_TYPE_WRITE);
1710 : 3 : lba += g_strip_size;
1711 [ - + - + ]: 3 : memset(g_io_output, 0, ((g_max_io_size / g_strip_size) + 1) * sizeof(struct io_output));
1712 : 3 : g_io_output_index = 0;
1713 : 3 : raid_bdev_submit_request(ch, bdev_io);
1714 [ - + ]: 3 : verify_io(bdev_io, req.base_bdevs.num_base_bdevs, ch_ctx, pbdev,
1715 : : g_child_io_status_flag);
1716 : 3 : bdev_io_cleanup(bdev_io);
1717 : : }
1718 : :
1719 : 3 : free_test_req(&req);
1720 : 3 : spdk_put_io_channel(ch);
1721 : 3 : create_raid_bdev_delete_req(&destroy_req, "raid1", 0);
1722 : 3 : rpc_bdev_raid_delete(NULL, NULL);
1723 : 3 : CU_ASSERT(g_rpc_err == 0);
1724 : 3 : verify_raid_bdev_present("raid1", false);
1725 : :
1726 : 3 : raid_bdev_exit();
1727 : 3 : base_bdevs_cleanup();
1728 : 3 : reset_globals();
1729 : 3 : }
1730 : :
1731 : : /* Test reset IO */
1732 : : static void
1733 : 3 : test_reset_io(void)
1734 : : {
1735 : 3 : struct rpc_bdev_raid_create req;
1736 : 3 : struct rpc_bdev_raid_delete destroy_req;
1737 : : struct raid_bdev *pbdev;
1738 : : struct spdk_io_channel *ch;
1739 : : struct raid_bdev_io_channel *ch_ctx;
1740 : : struct spdk_bdev_io *bdev_io;
1741 : :
1742 : 3 : set_globals();
1743 : 3 : CU_ASSERT(raid_bdev_init() == 0);
1744 : :
1745 : 3 : verify_raid_bdev_present("raid1", false);
1746 : 3 : create_raid_bdev_create_req(&req, "raid1", 0, true, 0, false);
1747 : 3 : rpc_bdev_raid_create(NULL, NULL);
1748 : 3 : CU_ASSERT(g_rpc_err == 0);
1749 : 3 : verify_raid_bdev(&req, true, RAID_BDEV_STATE_ONLINE);
1750 [ + - ]: 3 : TAILQ_FOREACH(pbdev, &g_raid_bdev_list, global_link) {
1751 [ + + + - ]: 3 : if (strcmp(pbdev->bdev.name, "raid1") == 0) {
1752 : 3 : break;
1753 : : }
1754 : : }
1755 : 3 : CU_ASSERT(pbdev != NULL);
1756 : :
1757 : 3 : ch = spdk_get_io_channel(pbdev);
1758 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch != NULL);
1759 : :
1760 : 3 : ch_ctx = spdk_io_channel_get_ctx(ch);
1761 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch_ctx != NULL);
1762 : :
1763 : 3 : g_bdev_io_submit_status = 0;
1764 : 3 : g_child_io_status_flag = true;
1765 : :
1766 : 3 : CU_ASSERT(raid_bdev_io_type_supported(pbdev, SPDK_BDEV_IO_TYPE_RESET) == true);
1767 : :
1768 : 3 : bdev_io = calloc(1, sizeof(struct spdk_bdev_io) + sizeof(struct raid_bdev_io));
1769 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bdev_io != NULL);
1770 : 3 : bdev_io_initialize(bdev_io, ch, &pbdev->bdev, 0, 1, SPDK_BDEV_IO_TYPE_RESET);
1771 [ - + ]: 3 : memset(g_io_output, 0, g_max_base_drives * sizeof(struct io_output));
1772 : 3 : g_io_output_index = 0;
1773 : 3 : raid_bdev_submit_request(ch, bdev_io);
1774 : 3 : verify_reset_io(bdev_io, req.base_bdevs.num_base_bdevs, ch_ctx, pbdev,
1775 : : true);
1776 : 3 : bdev_io_cleanup(bdev_io);
1777 : :
1778 : 3 : free_test_req(&req);
1779 : 3 : spdk_put_io_channel(ch);
1780 : 3 : create_raid_bdev_delete_req(&destroy_req, "raid1", 0);
1781 : 3 : rpc_bdev_raid_delete(NULL, NULL);
1782 : 3 : CU_ASSERT(g_rpc_err == 0);
1783 : 3 : verify_raid_bdev_present("raid1", false);
1784 : :
1785 : 3 : raid_bdev_exit();
1786 : 3 : base_bdevs_cleanup();
1787 : 3 : reset_globals();
1788 : 3 : }
1789 : :
1790 : : /* Create multiple raids, destroy raids without IO, get_raids related tests */
1791 : : static void
1792 : 3 : test_multi_raid_no_io(void)
1793 : : {
1794 : : struct rpc_bdev_raid_create *construct_req;
1795 : 3 : struct rpc_bdev_raid_delete destroy_req;
1796 : 3 : struct rpc_bdev_raid_get_bdevs get_raids_req;
1797 : : uint8_t i;
1798 : 3 : char name[16];
1799 : 3 : uint8_t bbdev_idx = 0;
1800 : :
1801 : 3 : set_globals();
1802 : 3 : construct_req = calloc(MAX_RAIDS, sizeof(struct rpc_bdev_raid_create));
1803 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(construct_req != NULL);
1804 : 3 : CU_ASSERT(raid_bdev_init() == 0);
1805 [ + + ]: 9 : for (i = 0; i < g_max_raids; i++) {
1806 : 6 : snprintf(name, 16, "%s%u", "raid", i);
1807 : 6 : verify_raid_bdev_present(name, false);
1808 : 6 : create_raid_bdev_create_req(&construct_req[i], name, bbdev_idx, true, 0, false);
1809 : 6 : bbdev_idx += g_max_base_drives;
1810 : 6 : rpc_bdev_raid_create(NULL, NULL);
1811 : 6 : CU_ASSERT(g_rpc_err == 0);
1812 : 6 : verify_raid_bdev(&construct_req[i], true, RAID_BDEV_STATE_ONLINE);
1813 : : }
1814 : :
1815 : 3 : create_get_raids_req(&get_raids_req, "all", 0);
1816 : 3 : rpc_bdev_raid_get_bdevs(NULL, NULL);
1817 : 3 : CU_ASSERT(g_rpc_err == 0);
1818 : 3 : verify_get_raids(construct_req, g_max_raids, g_get_raids_output, g_get_raids_count);
1819 [ + + ]: 9 : for (i = 0; i < g_get_raids_count; i++) {
1820 : 6 : free(g_get_raids_output[i]);
1821 : : }
1822 : :
1823 : 3 : create_get_raids_req(&get_raids_req, "online", 0);
1824 : 3 : rpc_bdev_raid_get_bdevs(NULL, NULL);
1825 : 3 : CU_ASSERT(g_rpc_err == 0);
1826 : 3 : verify_get_raids(construct_req, g_max_raids, g_get_raids_output, g_get_raids_count);
1827 [ + + ]: 9 : for (i = 0; i < g_get_raids_count; i++) {
1828 : 6 : free(g_get_raids_output[i]);
1829 : : }
1830 : :
1831 : 3 : create_get_raids_req(&get_raids_req, "configuring", 0);
1832 : 3 : rpc_bdev_raid_get_bdevs(NULL, NULL);
1833 : 3 : CU_ASSERT(g_rpc_err == 0);
1834 : 3 : CU_ASSERT(g_get_raids_count == 0);
1835 : :
1836 : 3 : create_get_raids_req(&get_raids_req, "offline", 0);
1837 : 3 : rpc_bdev_raid_get_bdevs(NULL, NULL);
1838 : 3 : CU_ASSERT(g_rpc_err == 0);
1839 : 3 : CU_ASSERT(g_get_raids_count == 0);
1840 : :
1841 : 3 : create_get_raids_req(&get_raids_req, "invalid_category", 0);
1842 : 3 : rpc_bdev_raid_get_bdevs(NULL, NULL);
1843 : 3 : CU_ASSERT(g_rpc_err == 1);
1844 : 3 : CU_ASSERT(g_get_raids_count == 0);
1845 : :
1846 : 3 : create_get_raids_req(&get_raids_req, "all", 1);
1847 : 3 : rpc_bdev_raid_get_bdevs(NULL, NULL);
1848 : 3 : CU_ASSERT(g_rpc_err == 1);
1849 : 3 : free(get_raids_req.category);
1850 : 3 : CU_ASSERT(g_get_raids_count == 0);
1851 : :
1852 : 3 : create_get_raids_req(&get_raids_req, "all", 0);
1853 : 3 : rpc_bdev_raid_get_bdevs(NULL, NULL);
1854 : 3 : CU_ASSERT(g_rpc_err == 0);
1855 : 3 : CU_ASSERT(g_get_raids_count == g_max_raids);
1856 [ + + ]: 9 : for (i = 0; i < g_get_raids_count; i++) {
1857 : 6 : free(g_get_raids_output[i]);
1858 : : }
1859 : :
1860 [ + + ]: 9 : for (i = 0; i < g_max_raids; i++) {
1861 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(construct_req[i].name != NULL);
1862 : 6 : snprintf(name, 16, "%s", construct_req[i].name);
1863 : 6 : create_raid_bdev_delete_req(&destroy_req, name, 0);
1864 : 6 : rpc_bdev_raid_delete(NULL, NULL);
1865 : 6 : CU_ASSERT(g_rpc_err == 0);
1866 : 6 : verify_raid_bdev_present(name, false);
1867 : : }
1868 : 3 : raid_bdev_exit();
1869 [ + + ]: 9 : for (i = 0; i < g_max_raids; i++) {
1870 : 6 : free_test_req(&construct_req[i]);
1871 : : }
1872 : 3 : free(construct_req);
1873 : 3 : base_bdevs_cleanup();
1874 : 3 : reset_globals();
1875 : 3 : }
1876 : :
1877 : : /* Create multiple raids, fire IOs on raids */
1878 : : static void
1879 : 3 : test_multi_raid_with_io(void)
1880 : : {
1881 : : struct rpc_bdev_raid_create *construct_req;
1882 : 3 : struct rpc_bdev_raid_delete destroy_req;
1883 : : uint8_t i;
1884 : 3 : char name[16];
1885 : 3 : uint8_t bbdev_idx = 0;
1886 : : struct raid_bdev *pbdev;
1887 : : struct spdk_io_channel **channels;
1888 : : struct spdk_bdev_io *bdev_io;
1889 : : uint64_t io_len;
1890 : 3 : uint64_t lba = 0;
1891 : : int16_t iotype;
1892 : :
1893 : 3 : set_globals();
1894 : 3 : construct_req = calloc(g_max_raids, sizeof(struct rpc_bdev_raid_create));
1895 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(construct_req != NULL);
1896 : 3 : CU_ASSERT(raid_bdev_init() == 0);
1897 : 3 : channels = calloc(g_max_raids, sizeof(*channels));
1898 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(channels != NULL);
1899 : :
1900 [ + + ]: 9 : for (i = 0; i < g_max_raids; i++) {
1901 : 6 : snprintf(name, 16, "%s%u", "raid", i);
1902 : 6 : verify_raid_bdev_present(name, false);
1903 : 6 : create_raid_bdev_create_req(&construct_req[i], name, bbdev_idx, true, 0, false);
1904 : 6 : bbdev_idx += g_max_base_drives;
1905 : 6 : rpc_bdev_raid_create(NULL, NULL);
1906 : 6 : CU_ASSERT(g_rpc_err == 0);
1907 : 6 : verify_raid_bdev(&construct_req[i], true, RAID_BDEV_STATE_ONLINE);
1908 [ + - ]: 9 : TAILQ_FOREACH(pbdev, &g_raid_bdev_list, global_link) {
1909 [ + + - + : 9 : if (strcmp(pbdev->bdev.name, construct_req[i].name) == 0) {
+ + ]
1910 : 6 : break;
1911 : : }
1912 : : }
1913 : 6 : CU_ASSERT(pbdev != NULL);
1914 : :
1915 : 6 : channels[i] = spdk_get_io_channel(pbdev);
1916 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(channels[i] != NULL);
1917 : : }
1918 : :
1919 : : /* This will perform a write on the first raid and a read on the second. It can be
1920 : : * expanded in the future to perform r/w on each raid device in the event that
1921 : : * multiple raid levels are supported.
1922 : : */
1923 [ + + ]: 9 : for (i = 0; i < g_max_raids; i++) {
1924 : 6 : struct spdk_io_channel *ch = channels[i];
1925 : 6 : struct raid_bdev_io_channel *ch_ctx = spdk_io_channel_get_ctx(ch);
1926 : :
1927 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(ch_ctx != NULL);
1928 : 6 : bdev_io = calloc(1, sizeof(struct spdk_bdev_io) + sizeof(struct raid_bdev_io));
1929 [ - + ]: 6 : SPDK_CU_ASSERT_FATAL(bdev_io != NULL);
1930 : 6 : io_len = g_strip_size;
1931 [ + + ]: 6 : iotype = (i) ? SPDK_BDEV_IO_TYPE_WRITE : SPDK_BDEV_IO_TYPE_READ;
1932 [ - + - + ]: 6 : memset(g_io_output, 0, ((g_max_io_size / g_strip_size) + 1) * sizeof(struct io_output));
1933 : 6 : g_io_output_index = 0;
1934 [ + - ]: 9 : TAILQ_FOREACH(pbdev, &g_raid_bdev_list, global_link) {
1935 [ + + - + : 9 : if (strcmp(pbdev->bdev.name, construct_req[i].name) == 0) {
+ + ]
1936 : 6 : break;
1937 : : }
1938 : : }
1939 : 6 : bdev_io_initialize(bdev_io, ch, &pbdev->bdev, lba, io_len, iotype);
1940 : 6 : CU_ASSERT(pbdev != NULL);
1941 : 6 : raid_bdev_submit_request(ch, bdev_io);
1942 [ - + ]: 6 : verify_io(bdev_io, g_max_base_drives, ch_ctx, pbdev,
1943 : : g_child_io_status_flag);
1944 : 6 : bdev_io_cleanup(bdev_io);
1945 : : }
1946 : :
1947 [ + + ]: 9 : for (i = 0; i < g_max_raids; i++) {
1948 : 6 : spdk_put_io_channel(channels[i]);
1949 : 6 : snprintf(name, 16, "%s", construct_req[i].name);
1950 : 6 : create_raid_bdev_delete_req(&destroy_req, name, 0);
1951 : 6 : rpc_bdev_raid_delete(NULL, NULL);
1952 : 6 : CU_ASSERT(g_rpc_err == 0);
1953 : 6 : verify_raid_bdev_present(name, false);
1954 : : }
1955 : 3 : raid_bdev_exit();
1956 [ + + ]: 9 : for (i = 0; i < g_max_raids; i++) {
1957 : 6 : free_test_req(&construct_req[i]);
1958 : : }
1959 : 3 : free(construct_req);
1960 : 3 : free(channels);
1961 : 3 : base_bdevs_cleanup();
1962 : 3 : reset_globals();
1963 : 3 : }
1964 : :
1965 : : static void
1966 : 3 : test_io_type_supported(void)
1967 : : {
1968 : 3 : CU_ASSERT(raid_bdev_io_type_supported(NULL, SPDK_BDEV_IO_TYPE_READ) == true);
1969 : 3 : CU_ASSERT(raid_bdev_io_type_supported(NULL, SPDK_BDEV_IO_TYPE_WRITE) == true);
1970 : 3 : CU_ASSERT(raid_bdev_io_type_supported(NULL, SPDK_BDEV_IO_TYPE_INVALID) == false);
1971 : 3 : }
1972 : :
1973 : : static void
1974 : 3 : test_raid_json_dump_info(void)
1975 : : {
1976 : 3 : struct rpc_bdev_raid_create req;
1977 : 3 : struct rpc_bdev_raid_delete destroy_req;
1978 : : struct raid_bdev *pbdev;
1979 : :
1980 : 3 : set_globals();
1981 : 3 : CU_ASSERT(raid_bdev_init() == 0);
1982 : :
1983 : 3 : verify_raid_bdev_present("raid1", false);
1984 : 3 : create_raid_bdev_create_req(&req, "raid1", 0, true, 0, false);
1985 : 3 : rpc_bdev_raid_create(NULL, NULL);
1986 : 3 : CU_ASSERT(g_rpc_err == 0);
1987 : 3 : verify_raid_bdev(&req, true, RAID_BDEV_STATE_ONLINE);
1988 : :
1989 [ + - ]: 3 : TAILQ_FOREACH(pbdev, &g_raid_bdev_list, global_link) {
1990 [ + + + - ]: 3 : if (strcmp(pbdev->bdev.name, "raid1") == 0) {
1991 : 3 : break;
1992 : : }
1993 : : }
1994 : 3 : CU_ASSERT(pbdev != NULL);
1995 : :
1996 : 3 : CU_ASSERT(raid_bdev_dump_info_json(pbdev, NULL) == 0);
1997 : :
1998 : 3 : free_test_req(&req);
1999 : :
2000 : 3 : create_raid_bdev_delete_req(&destroy_req, "raid1", 0);
2001 : 3 : rpc_bdev_raid_delete(NULL, NULL);
2002 : 3 : CU_ASSERT(g_rpc_err == 0);
2003 : 3 : verify_raid_bdev_present("raid1", false);
2004 : :
2005 : 3 : raid_bdev_exit();
2006 : 3 : base_bdevs_cleanup();
2007 : 3 : reset_globals();
2008 : 3 : }
2009 : :
2010 : : static void
2011 : 3 : test_context_size(void)
2012 : : {
2013 : 3 : CU_ASSERT(raid_bdev_get_ctx_size() == sizeof(struct raid_bdev_io));
2014 : 3 : }
2015 : :
2016 : : static void
2017 : 3 : test_raid_level_conversions(void)
2018 : : {
2019 : : const char *raid_str;
2020 : :
2021 : 3 : CU_ASSERT(raid_bdev_str_to_level("abcd123") == INVALID_RAID_LEVEL);
2022 : 3 : CU_ASSERT(raid_bdev_str_to_level("0") == RAID0);
2023 : 3 : CU_ASSERT(raid_bdev_str_to_level("raid0") == RAID0);
2024 : 3 : CU_ASSERT(raid_bdev_str_to_level("RAID0") == RAID0);
2025 : :
2026 : 3 : raid_str = raid_bdev_level_to_str(INVALID_RAID_LEVEL);
2027 [ + - + - ]: 3 : CU_ASSERT(raid_str != NULL && strlen(raid_str) == 0);
2028 : 3 : raid_str = raid_bdev_level_to_str(1234);
2029 [ + - + - ]: 3 : CU_ASSERT(raid_str != NULL && strlen(raid_str) == 0);
2030 : 3 : raid_str = raid_bdev_level_to_str(RAID0);
2031 [ + - + + : 3 : CU_ASSERT(raid_str != NULL && strcmp(raid_str, "raid0") == 0);
+ - ]
2032 : 3 : }
2033 : :
2034 : : static void
2035 : 3 : test_create_raid_superblock(void)
2036 : : {
2037 : 3 : struct rpc_bdev_raid_create req;
2038 : 3 : struct rpc_bdev_raid_delete delete_req;
2039 : :
2040 : 3 : set_globals();
2041 : 3 : CU_ASSERT(raid_bdev_init() == 0);
2042 : :
2043 : 3 : verify_raid_bdev_present("raid1", false);
2044 : 3 : create_raid_bdev_create_req(&req, "raid1", 0, true, 0, true);
2045 : 3 : rpc_bdev_raid_create(NULL, NULL);
2046 : 3 : CU_ASSERT(g_rpc_err == 0);
2047 : 3 : verify_raid_bdev(&req, true, RAID_BDEV_STATE_ONLINE);
2048 : 3 : free_test_req(&req);
2049 : :
2050 : 3 : create_raid_bdev_delete_req(&delete_req, "raid1", 0);
2051 : 3 : rpc_bdev_raid_delete(NULL, NULL);
2052 : 3 : CU_ASSERT(g_rpc_err == 0);
2053 : 3 : raid_bdev_exit();
2054 : 3 : base_bdevs_cleanup();
2055 : 3 : reset_globals();
2056 : 3 : }
2057 : :
2058 : : static void
2059 : 48 : complete_process_request(void *ctx)
2060 : : {
2061 : 48 : struct raid_bdev_process_request *process_req = ctx;
2062 : :
2063 : 48 : raid_bdev_process_request_complete(process_req, 0);
2064 : 48 : }
2065 : :
2066 : : static int
2067 : 48 : submit_process_request(struct raid_bdev_process_request *process_req,
2068 : : struct raid_bdev_io_channel *raid_ch)
2069 : : {
2070 : 48 : struct raid_bdev *raid_bdev = spdk_io_channel_get_io_device(spdk_io_channel_from_ctx(raid_ch));
2071 : :
2072 : 48 : *(uint64_t *)raid_bdev->module_private += process_req->num_blocks;
2073 : :
2074 : 48 : spdk_thread_send_msg(spdk_get_thread(), complete_process_request, process_req);
2075 : :
2076 : 48 : return process_req->num_blocks;
2077 : : }
2078 : :
2079 : : static void
2080 : 3 : test_raid_process(void)
2081 : : {
2082 : 3 : struct rpc_bdev_raid_create req;
2083 : 3 : struct rpc_bdev_raid_delete destroy_req;
2084 : : struct raid_bdev *pbdev;
2085 : : struct spdk_bdev *base_bdev;
2086 : : struct spdk_thread *process_thread;
2087 : 3 : uint64_t num_blocks_processed = 0;
2088 : :
2089 : 3 : set_globals();
2090 : 3 : CU_ASSERT(raid_bdev_init() == 0);
2091 : :
2092 : 3 : create_raid_bdev_create_req(&req, "raid1", 0, true, 0, false);
2093 : 3 : verify_raid_bdev_present("raid1", false);
2094 [ + + ]: 99 : TAILQ_FOREACH(base_bdev, &g_bdev_list, internal.link) {
2095 : 96 : base_bdev->blockcnt = 128;
2096 : : }
2097 : 3 : rpc_bdev_raid_create(NULL, NULL);
2098 : 3 : CU_ASSERT(g_rpc_err == 0);
2099 : 3 : verify_raid_bdev(&req, true, RAID_BDEV_STATE_ONLINE);
2100 : 3 : free_test_req(&req);
2101 : :
2102 [ + - ]: 3 : TAILQ_FOREACH(pbdev, &g_raid_bdev_list, global_link) {
2103 [ + + + - ]: 3 : if (strcmp(pbdev->bdev.name, "raid1") == 0) {
2104 : 3 : break;
2105 : : }
2106 : : }
2107 : 3 : CU_ASSERT(pbdev != NULL);
2108 : :
2109 : 3 : pbdev->module->submit_process_request = submit_process_request;
2110 : 3 : pbdev->module_private = &num_blocks_processed;
2111 : :
2112 : 3 : CU_ASSERT(raid_bdev_start_rebuild(&pbdev->base_bdev_info[0]) == 0);
2113 : 3 : poll_threads();
2114 : :
2115 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(pbdev->process != NULL);
2116 : :
2117 : 3 : process_thread = spdk_thread_get_by_id(spdk_thread_get_id(spdk_get_thread()) + 1);
2118 : :
2119 [ + + ]: 162 : while (spdk_thread_poll(process_thread, 0, 0) > 0) {
2120 : 159 : poll_threads();
2121 : : }
2122 : :
2123 : 3 : CU_ASSERT(pbdev->process == NULL);
2124 : 3 : CU_ASSERT(num_blocks_processed == pbdev->bdev.blockcnt);
2125 : :
2126 : 3 : poll_threads();
2127 : :
2128 : 3 : create_raid_bdev_delete_req(&destroy_req, "raid1", 0);
2129 : 3 : rpc_bdev_raid_delete(NULL, NULL);
2130 : 3 : CU_ASSERT(g_rpc_err == 0);
2131 : 3 : verify_raid_bdev_present("raid1", false);
2132 : :
2133 : 3 : raid_bdev_exit();
2134 : 3 : base_bdevs_cleanup();
2135 : 3 : reset_globals();
2136 : 3 : }
2137 : :
2138 : : static void
2139 : 3 : test_raid_io_split(void)
2140 : : {
2141 : 3 : struct rpc_bdev_raid_create req;
2142 : 3 : struct rpc_bdev_raid_delete destroy_req;
2143 : : struct raid_bdev *pbdev;
2144 : : struct spdk_io_channel *ch;
2145 : : struct raid_bdev_io_channel *raid_ch;
2146 : : struct spdk_bdev_io *bdev_io;
2147 : : struct raid_bdev_io *raid_io;
2148 : : uint64_t split_offset;
2149 : 3 : struct iovec iovs_orig[4];
2150 : 3 : struct raid_bdev_process process = { };
2151 : :
2152 : 3 : set_globals();
2153 : 3 : CU_ASSERT(raid_bdev_init() == 0);
2154 : :
2155 : 3 : verify_raid_bdev_present("raid1", false);
2156 : 3 : create_raid_bdev_create_req(&req, "raid1", 0, true, 0, false);
2157 : 3 : rpc_bdev_raid_create(NULL, NULL);
2158 : 3 : CU_ASSERT(g_rpc_err == 0);
2159 : 3 : verify_raid_bdev(&req, true, RAID_BDEV_STATE_ONLINE);
2160 : :
2161 [ + - ]: 3 : TAILQ_FOREACH(pbdev, &g_raid_bdev_list, global_link) {
2162 [ + + + - ]: 3 : if (strcmp(pbdev->bdev.name, "raid1") == 0) {
2163 : 3 : break;
2164 : : }
2165 : : }
2166 : 3 : CU_ASSERT(pbdev != NULL);
2167 : 3 : pbdev->bdev.md_len = 8;
2168 : :
2169 : 3 : process.raid_bdev = pbdev;
2170 : 3 : process.target = &pbdev->base_bdev_info[0];
2171 : 3 : pbdev->process = &process;
2172 : 3 : ch = spdk_get_io_channel(pbdev);
2173 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(ch != NULL);
2174 : 3 : raid_ch = spdk_io_channel_get_ctx(ch);
2175 : 3 : g_bdev_io_defer_completion = true;
2176 : :
2177 : : /* test split of bdev_io with 1 iovec */
2178 : 3 : bdev_io = calloc(1, sizeof(struct spdk_bdev_io) + sizeof(struct raid_bdev_io));
2179 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bdev_io != NULL);
2180 : 3 : raid_io = (struct raid_bdev_io *)bdev_io->driver_ctx;
2181 : 3 : bdev_io_initialize(bdev_io, ch, &pbdev->bdev, 0, g_strip_size, SPDK_BDEV_IO_TYPE_WRITE);
2182 [ - + ]: 3 : memcpy(iovs_orig, bdev_io->u.bdev.iovs, sizeof(*iovs_orig) * bdev_io->u.bdev.iovcnt);
2183 [ - + - + ]: 3 : memset(g_io_output, 0, ((g_max_io_size / g_strip_size) + 1) * sizeof(struct io_output));
2184 : 3 : bdev_io->u.bdev.md_buf = (void *)0x1000000;
2185 : 3 : g_io_output_index = 0;
2186 : :
2187 : 3 : split_offset = 1;
2188 : 3 : raid_ch->process.offset = split_offset;
2189 : 3 : raid_bdev_submit_request(ch, bdev_io);
2190 : 3 : CU_ASSERT(raid_io->num_blocks == g_strip_size - split_offset);
2191 : 3 : CU_ASSERT(raid_io->offset_blocks == split_offset);
2192 : 3 : CU_ASSERT(raid_io->iovcnt == 1);
2193 : 3 : CU_ASSERT(raid_io->iovs == bdev_io->u.bdev.iovs);
2194 : 3 : CU_ASSERT(raid_io->iovs == raid_io->split.iov);
2195 : 3 : CU_ASSERT(raid_io->iovs[0].iov_base == iovs_orig->iov_base + split_offset * g_block_len);
2196 : 3 : CU_ASSERT(raid_io->iovs[0].iov_len == iovs_orig->iov_len - split_offset * g_block_len);
2197 : 3 : CU_ASSERT(raid_io->md_buf == bdev_io->u.bdev.md_buf + split_offset * pbdev->bdev.md_len);
2198 : 3 : complete_deferred_ios();
2199 : 3 : CU_ASSERT(raid_io->num_blocks == split_offset);
2200 : 3 : CU_ASSERT(raid_io->offset_blocks == 0);
2201 : 3 : CU_ASSERT(raid_io->iovcnt == 1);
2202 : 3 : CU_ASSERT(raid_io->iovs[0].iov_base == iovs_orig->iov_base);
2203 : 3 : CU_ASSERT(raid_io->iovs[0].iov_len == split_offset * g_block_len);
2204 : 3 : CU_ASSERT(raid_io->md_buf == bdev_io->u.bdev.md_buf);
2205 : 3 : complete_deferred_ios();
2206 : 3 : CU_ASSERT(raid_io->num_blocks == g_strip_size);
2207 : 3 : CU_ASSERT(raid_io->offset_blocks == 0);
2208 : 3 : CU_ASSERT(raid_io->iovcnt == 1);
2209 : 3 : CU_ASSERT(raid_io->iovs[0].iov_base == iovs_orig->iov_base);
2210 : 3 : CU_ASSERT(raid_io->iovs[0].iov_len == iovs_orig->iov_len);
2211 : 3 : CU_ASSERT(raid_io->md_buf == bdev_io->u.bdev.md_buf);
2212 : :
2213 [ - + ]: 3 : CU_ASSERT(g_io_comp_status == g_child_io_status_flag);
2214 : 3 : CU_ASSERT(g_io_output_index == 2);
2215 : 3 : CU_ASSERT(g_io_output[0].offset_blocks == split_offset);
2216 : 3 : CU_ASSERT(g_io_output[0].num_blocks == g_strip_size - split_offset);
2217 : 3 : CU_ASSERT(g_io_output[1].offset_blocks == 0);
2218 : 3 : CU_ASSERT(g_io_output[1].num_blocks == split_offset);
2219 : 3 : bdev_io_cleanup(bdev_io);
2220 : :
2221 : : /* test split of bdev_io with 4 iovecs */
2222 : 3 : bdev_io = calloc(1, sizeof(struct spdk_bdev_io) + sizeof(struct raid_bdev_io));
2223 [ - + ]: 3 : SPDK_CU_ASSERT_FATAL(bdev_io != NULL);
2224 : 3 : raid_io = (struct raid_bdev_io *)bdev_io->driver_ctx;
2225 : 3 : _bdev_io_initialize(bdev_io, ch, &pbdev->bdev, 0, g_strip_size, SPDK_BDEV_IO_TYPE_WRITE,
2226 : 3 : 4, g_strip_size / 4 * g_block_len);
2227 [ - + ]: 3 : memcpy(iovs_orig, bdev_io->u.bdev.iovs, sizeof(*iovs_orig) * bdev_io->u.bdev.iovcnt);
2228 [ - + - + ]: 3 : memset(g_io_output, 0, ((g_max_io_size / g_strip_size) + 1) * sizeof(struct io_output));
2229 : 3 : bdev_io->u.bdev.md_buf = (void *)0x1000000;
2230 : 3 : g_io_output_index = 0;
2231 : :
2232 : 3 : split_offset = 1; /* split at the first iovec */
2233 : 3 : raid_ch->process.offset = split_offset;
2234 : 3 : raid_bdev_submit_request(ch, bdev_io);
2235 : 3 : CU_ASSERT(raid_io->num_blocks == g_strip_size - split_offset);
2236 : 3 : CU_ASSERT(raid_io->offset_blocks == split_offset);
2237 : 3 : CU_ASSERT(raid_io->iovcnt == 4);
2238 : 3 : CU_ASSERT(raid_io->split.iov == &bdev_io->u.bdev.iovs[0]);
2239 : 3 : CU_ASSERT(raid_io->iovs == &bdev_io->u.bdev.iovs[0]);
2240 : 3 : CU_ASSERT(raid_io->iovs[0].iov_base == iovs_orig[0].iov_base + g_block_len);
2241 : 3 : CU_ASSERT(raid_io->iovs[0].iov_len == iovs_orig[0].iov_len - g_block_len);
2242 [ - + - + ]: 3 : CU_ASSERT(memcmp(raid_io->iovs + 1, iovs_orig + 1, sizeof(*iovs_orig) * 3) == 0);
2243 : 3 : CU_ASSERT(raid_io->md_buf == bdev_io->u.bdev.md_buf + split_offset * pbdev->bdev.md_len);
2244 : 3 : complete_deferred_ios();
2245 : 3 : CU_ASSERT(raid_io->num_blocks == split_offset);
2246 : 3 : CU_ASSERT(raid_io->offset_blocks == 0);
2247 : 3 : CU_ASSERT(raid_io->iovcnt == 1);
2248 : 3 : CU_ASSERT(raid_io->iovs == bdev_io->u.bdev.iovs);
2249 : 3 : CU_ASSERT(raid_io->iovs[0].iov_base == iovs_orig[0].iov_base);
2250 : 3 : CU_ASSERT(raid_io->iovs[0].iov_len == g_block_len);
2251 : 3 : CU_ASSERT(raid_io->md_buf == bdev_io->u.bdev.md_buf);
2252 : 3 : complete_deferred_ios();
2253 : 3 : CU_ASSERT(raid_io->num_blocks == g_strip_size);
2254 : 3 : CU_ASSERT(raid_io->offset_blocks == 0);
2255 : 3 : CU_ASSERT(raid_io->iovcnt == 4);
2256 : 3 : CU_ASSERT(raid_io->iovs == bdev_io->u.bdev.iovs);
2257 [ - + ]: 3 : CU_ASSERT(memcmp(raid_io->iovs, iovs_orig, sizeof(*iovs_orig) * raid_io->iovcnt) == 0);
2258 : 3 : CU_ASSERT(raid_io->md_buf == bdev_io->u.bdev.md_buf);
2259 : :
2260 [ - + ]: 3 : CU_ASSERT(g_io_comp_status == g_child_io_status_flag);
2261 : 3 : CU_ASSERT(g_io_output_index == 2);
2262 : 3 : CU_ASSERT(g_io_output[0].offset_blocks == split_offset);
2263 : 3 : CU_ASSERT(g_io_output[0].num_blocks == g_strip_size - split_offset);
2264 : 3 : CU_ASSERT(g_io_output[1].offset_blocks == 0);
2265 : 3 : CU_ASSERT(g_io_output[1].num_blocks == split_offset);
2266 : :
2267 [ - + - + ]: 3 : memset(g_io_output, 0, ((g_max_io_size / g_strip_size) + 1) * sizeof(struct io_output));
2268 : 3 : g_io_output_index = 0;
2269 : :
2270 : 3 : split_offset = g_strip_size / 2; /* split exactly between second and third iovec */
2271 : 3 : raid_ch->process.offset = split_offset;
2272 : 3 : raid_bdev_submit_request(ch, bdev_io);
2273 : 3 : CU_ASSERT(raid_io->num_blocks == g_strip_size - split_offset);
2274 : 3 : CU_ASSERT(raid_io->offset_blocks == split_offset);
2275 : 3 : CU_ASSERT(raid_io->iovcnt == 2);
2276 : 3 : CU_ASSERT(raid_io->split.iov == NULL);
2277 : 3 : CU_ASSERT(raid_io->iovs == &bdev_io->u.bdev.iovs[2]);
2278 [ - + - + ]: 3 : CU_ASSERT(memcmp(raid_io->iovs, iovs_orig + 2, sizeof(*iovs_orig) * raid_io->iovcnt) == 0);
2279 : 3 : CU_ASSERT(raid_io->md_buf == bdev_io->u.bdev.md_buf + split_offset * pbdev->bdev.md_len);
2280 : 3 : complete_deferred_ios();
2281 : 3 : CU_ASSERT(raid_io->num_blocks == split_offset);
2282 : 3 : CU_ASSERT(raid_io->offset_blocks == 0);
2283 : 3 : CU_ASSERT(raid_io->iovcnt == 2);
2284 : 3 : CU_ASSERT(raid_io->iovs == bdev_io->u.bdev.iovs);
2285 [ - + ]: 3 : CU_ASSERT(memcmp(raid_io->iovs, iovs_orig, sizeof(*iovs_orig) * raid_io->iovcnt) == 0);
2286 : 3 : CU_ASSERT(raid_io->md_buf == bdev_io->u.bdev.md_buf);
2287 : 3 : complete_deferred_ios();
2288 : 3 : CU_ASSERT(raid_io->num_blocks == g_strip_size);
2289 : 3 : CU_ASSERT(raid_io->offset_blocks == 0);
2290 : 3 : CU_ASSERT(raid_io->iovcnt == 4);
2291 : 3 : CU_ASSERT(raid_io->iovs == bdev_io->u.bdev.iovs);
2292 [ - + ]: 3 : CU_ASSERT(memcmp(raid_io->iovs, iovs_orig, sizeof(*iovs_orig) * raid_io->iovcnt) == 0);
2293 : 3 : CU_ASSERT(raid_io->md_buf == bdev_io->u.bdev.md_buf);
2294 : :
2295 [ - + ]: 3 : CU_ASSERT(g_io_comp_status == g_child_io_status_flag);
2296 : 3 : CU_ASSERT(g_io_output_index == 2);
2297 : 3 : CU_ASSERT(g_io_output[0].offset_blocks == split_offset);
2298 : 3 : CU_ASSERT(g_io_output[0].num_blocks == g_strip_size - split_offset);
2299 : 3 : CU_ASSERT(g_io_output[1].offset_blocks == 0);
2300 : 3 : CU_ASSERT(g_io_output[1].num_blocks == split_offset);
2301 : :
2302 [ - + - + ]: 3 : memset(g_io_output, 0, ((g_max_io_size / g_strip_size) + 1) * sizeof(struct io_output));
2303 : 3 : g_io_output_index = 0;
2304 : :
2305 : 3 : split_offset = g_strip_size / 2 + 1; /* split at the third iovec */
2306 : 3 : raid_ch->process.offset = split_offset;
2307 : 3 : raid_bdev_submit_request(ch, bdev_io);
2308 : 3 : CU_ASSERT(raid_io->num_blocks == g_strip_size - split_offset);
2309 : 3 : CU_ASSERT(raid_io->offset_blocks == split_offset);
2310 : 3 : CU_ASSERT(raid_io->iovcnt == 2);
2311 : 3 : CU_ASSERT(raid_io->split.iov == &bdev_io->u.bdev.iovs[2]);
2312 : 3 : CU_ASSERT(raid_io->iovs == &bdev_io->u.bdev.iovs[2]);
2313 : 3 : CU_ASSERT(raid_io->iovs[0].iov_base == iovs_orig[2].iov_base + g_block_len);
2314 : 3 : CU_ASSERT(raid_io->iovs[0].iov_len == iovs_orig[2].iov_len - g_block_len);
2315 : 3 : CU_ASSERT(raid_io->iovs[1].iov_base == iovs_orig[3].iov_base);
2316 : 3 : CU_ASSERT(raid_io->iovs[1].iov_len == iovs_orig[3].iov_len);
2317 : 3 : CU_ASSERT(raid_io->md_buf == bdev_io->u.bdev.md_buf + split_offset * pbdev->bdev.md_len);
2318 : 3 : complete_deferred_ios();
2319 : 3 : CU_ASSERT(raid_io->num_blocks == split_offset);
2320 : 3 : CU_ASSERT(raid_io->offset_blocks == 0);
2321 : 3 : CU_ASSERT(raid_io->iovcnt == 3);
2322 : 3 : CU_ASSERT(raid_io->iovs == bdev_io->u.bdev.iovs);
2323 [ - + ]: 3 : CU_ASSERT(memcmp(raid_io->iovs, iovs_orig, sizeof(*iovs_orig) * 2) == 0);
2324 : 3 : CU_ASSERT(raid_io->iovs[2].iov_base == iovs_orig[2].iov_base);
2325 : 3 : CU_ASSERT(raid_io->iovs[2].iov_len == g_block_len);
2326 : 3 : CU_ASSERT(raid_io->md_buf == bdev_io->u.bdev.md_buf);
2327 : 3 : complete_deferred_ios();
2328 : 3 : CU_ASSERT(raid_io->num_blocks == g_strip_size);
2329 : 3 : CU_ASSERT(raid_io->offset_blocks == 0);
2330 : 3 : CU_ASSERT(raid_io->iovcnt == 4);
2331 : 3 : CU_ASSERT(raid_io->iovs == bdev_io->u.bdev.iovs);
2332 [ - + ]: 3 : CU_ASSERT(memcmp(raid_io->iovs, iovs_orig, sizeof(*iovs_orig) * raid_io->iovcnt) == 0);
2333 : 3 : CU_ASSERT(raid_io->md_buf == bdev_io->u.bdev.md_buf);
2334 : :
2335 [ - + ]: 3 : CU_ASSERT(g_io_comp_status == g_child_io_status_flag);
2336 : 3 : CU_ASSERT(g_io_output_index == 2);
2337 : 3 : CU_ASSERT(g_io_output[0].offset_blocks == split_offset);
2338 : 3 : CU_ASSERT(g_io_output[0].num_blocks == g_strip_size - split_offset);
2339 : 3 : CU_ASSERT(g_io_output[1].offset_blocks == 0);
2340 : 3 : CU_ASSERT(g_io_output[1].num_blocks == split_offset);
2341 : :
2342 [ - + - + ]: 3 : memset(g_io_output, 0, ((g_max_io_size / g_strip_size) + 1) * sizeof(struct io_output));
2343 : 3 : g_io_output_index = 0;
2344 : :
2345 : 3 : split_offset = g_strip_size - 1; /* split at the last iovec */
2346 : 3 : raid_ch->process.offset = split_offset;
2347 : 3 : raid_bdev_submit_request(ch, bdev_io);
2348 : 3 : CU_ASSERT(raid_io->num_blocks == g_strip_size - split_offset);
2349 : 3 : CU_ASSERT(raid_io->offset_blocks == split_offset);
2350 : 3 : CU_ASSERT(raid_io->iovcnt == 1);
2351 : 3 : CU_ASSERT(raid_io->split.iov == &bdev_io->u.bdev.iovs[3]);
2352 : 3 : CU_ASSERT(raid_io->iovs == &bdev_io->u.bdev.iovs[3]);
2353 : 3 : CU_ASSERT(raid_io->iovs[0].iov_base == iovs_orig[3].iov_base + iovs_orig[3].iov_len - g_block_len);
2354 : 3 : CU_ASSERT(raid_io->iovs[0].iov_len == g_block_len);
2355 : 3 : CU_ASSERT(raid_io->md_buf == bdev_io->u.bdev.md_buf + split_offset * pbdev->bdev.md_len);
2356 : 3 : complete_deferred_ios();
2357 : 3 : CU_ASSERT(raid_io->num_blocks == split_offset);
2358 : 3 : CU_ASSERT(raid_io->offset_blocks == 0);
2359 : 3 : CU_ASSERT(raid_io->iovcnt == 4);
2360 : 3 : CU_ASSERT(raid_io->iovs == bdev_io->u.bdev.iovs);
2361 [ - + ]: 3 : CU_ASSERT(memcmp(raid_io->iovs, iovs_orig, sizeof(*iovs_orig) * 3) == 0);
2362 : 3 : CU_ASSERT(raid_io->iovs[3].iov_base == iovs_orig[3].iov_base);
2363 : 3 : CU_ASSERT(raid_io->iovs[3].iov_len == iovs_orig[3].iov_len - g_block_len);
2364 : 3 : CU_ASSERT(raid_io->md_buf == bdev_io->u.bdev.md_buf);
2365 : 3 : complete_deferred_ios();
2366 : 3 : CU_ASSERT(raid_io->num_blocks == g_strip_size);
2367 : 3 : CU_ASSERT(raid_io->offset_blocks == 0);
2368 : 3 : CU_ASSERT(raid_io->iovcnt == 4);
2369 : 3 : CU_ASSERT(raid_io->iovs == bdev_io->u.bdev.iovs);
2370 [ - + ]: 3 : CU_ASSERT(memcmp(raid_io->iovs, iovs_orig, sizeof(*iovs_orig) * raid_io->iovcnt) == 0);
2371 : 3 : CU_ASSERT(raid_io->md_buf == bdev_io->u.bdev.md_buf);
2372 : :
2373 [ - + ]: 3 : CU_ASSERT(g_io_comp_status == g_child_io_status_flag);
2374 : 3 : CU_ASSERT(g_io_output_index == 2);
2375 : 3 : CU_ASSERT(g_io_output[0].offset_blocks == split_offset);
2376 : 3 : CU_ASSERT(g_io_output[0].num_blocks == g_strip_size - split_offset);
2377 : 3 : CU_ASSERT(g_io_output[1].offset_blocks == 0);
2378 : 3 : CU_ASSERT(g_io_output[1].num_blocks == split_offset);
2379 : 3 : bdev_io_cleanup(bdev_io);
2380 : :
2381 : 3 : spdk_put_io_channel(ch);
2382 : 3 : free_test_req(&req);
2383 : 3 : pbdev->process = NULL;
2384 : :
2385 : 3 : create_raid_bdev_delete_req(&destroy_req, "raid1", 0);
2386 : 3 : rpc_bdev_raid_delete(NULL, NULL);
2387 : 3 : CU_ASSERT(g_rpc_err == 0);
2388 : 3 : verify_raid_bdev_present("raid1", false);
2389 : :
2390 : 3 : raid_bdev_exit();
2391 : 3 : base_bdevs_cleanup();
2392 : 3 : reset_globals();
2393 : 3 : }
2394 : :
2395 : : static int
2396 : 51 : test_bdev_ioch_create(void *io_device, void *ctx_buf)
2397 : : {
2398 : 51 : return 0;
2399 : : }
2400 : :
2401 : : static void
2402 : 51 : test_bdev_ioch_destroy(void *io_device, void *ctx_buf)
2403 : : {
2404 : 51 : }
2405 : :
2406 : : int
2407 : 3 : main(int argc, char **argv)
2408 : : {
2409 : 3 : CU_pSuite suite = NULL;
2410 : : unsigned int num_failures;
2411 : :
2412 : 3 : CU_initialize_registry();
2413 : :
2414 : 3 : suite = CU_add_suite("raid", NULL, NULL);
2415 : :
2416 : 3 : CU_ADD_TEST(suite, test_create_raid);
2417 : 3 : CU_ADD_TEST(suite, test_create_raid_superblock);
2418 : 3 : CU_ADD_TEST(suite, test_delete_raid);
2419 : 3 : CU_ADD_TEST(suite, test_create_raid_invalid_args);
2420 : 3 : CU_ADD_TEST(suite, test_delete_raid_invalid_args);
2421 : 3 : CU_ADD_TEST(suite, test_io_channel);
2422 : 3 : CU_ADD_TEST(suite, test_reset_io);
2423 : 3 : CU_ADD_TEST(suite, test_write_io);
2424 : 3 : CU_ADD_TEST(suite, test_read_io);
2425 : 3 : CU_ADD_TEST(suite, test_unmap_io);
2426 : 3 : CU_ADD_TEST(suite, test_io_failure);
2427 : 3 : CU_ADD_TEST(suite, test_multi_raid_no_io);
2428 : 3 : CU_ADD_TEST(suite, test_multi_raid_with_io);
2429 : 3 : CU_ADD_TEST(suite, test_io_type_supported);
2430 : 3 : CU_ADD_TEST(suite, test_raid_json_dump_info);
2431 : 3 : CU_ADD_TEST(suite, test_context_size);
2432 : 3 : CU_ADD_TEST(suite, test_raid_level_conversions);
2433 : 3 : CU_ADD_TEST(suite, test_raid_process);
2434 : 3 : CU_ADD_TEST(suite, test_raid_io_split);
2435 : :
2436 : 3 : allocate_threads(1);
2437 : 3 : set_thread(0);
2438 : 3 : spdk_io_device_register(&g_bdev_ch_io_device, test_bdev_ioch_create, test_bdev_ioch_destroy, 0,
2439 : : NULL);
2440 : :
2441 : 3 : set_test_opts();
2442 : 3 : num_failures = spdk_ut_run_tests(argc, argv, NULL);
2443 : 3 : CU_cleanup_registry();
2444 : :
2445 : 3 : spdk_io_device_unregister(&g_bdev_ch_io_device, NULL);
2446 : 3 : free_threads();
2447 : :
2448 : 3 : return num_failures;
2449 : : }
|