xref: /spdk/test/unit/lib/bdev/raid/raid1.c/raid1_ut.c (revision 3b9baa5f8af96f31278fc8f7e34f2ab7444787f7)
169038a94SKrzysztof Smolinski /*   SPDX-License-Identifier: BSD-3-Clause
269038a94SKrzysztof Smolinski  *   Copyright (C) 2022 Intel Corporation.
369038a94SKrzysztof Smolinski  *   All rights reserved.
469038a94SKrzysztof Smolinski  */
569038a94SKrzysztof Smolinski 
669038a94SKrzysztof Smolinski #include "spdk/stdinc.h"
7ae431e31SKonrad Sztyber #include "spdk_internal/cunit.h"
869038a94SKrzysztof Smolinski #include "spdk/env.h"
9a73acd9fSKrzysztof Smolinski 
10a73acd9fSKrzysztof Smolinski #include "common/lib/ut_multithread.c"
1169038a94SKrzysztof Smolinski 
1269038a94SKrzysztof Smolinski #include "bdev/raid/raid1.c"
1369038a94SKrzysztof Smolinski #include "../common.c"
1469038a94SKrzysztof Smolinski 
15b0b0889eSArtur Paszkiewicz static enum spdk_bdev_io_status g_io_status;
16cc94f303SArtur Paszkiewicz static struct spdk_bdev_desc *g_last_io_desc;
17cc94f303SArtur Paszkiewicz static spdk_bdev_io_completion_cb g_last_io_cb;
18b0b0889eSArtur Paszkiewicz 
1969038a94SKrzysztof Smolinski DEFINE_STUB_V(raid_bdev_module_list_add, (struct raid_bdev_module *raid_module));
20a73acd9fSKrzysztof Smolinski DEFINE_STUB_V(raid_bdev_module_stop_done, (struct raid_bdev *raid_bdev));
2169038a94SKrzysztof Smolinski DEFINE_STUB_V(spdk_bdev_free_io, (struct spdk_bdev_io *bdev_io));
2269038a94SKrzysztof Smolinski DEFINE_STUB_V(raid_bdev_queue_io_wait, (struct raid_bdev_io *raid_io, struct spdk_bdev *bdev,
2369038a94SKrzysztof Smolinski 					struct spdk_io_channel *ch, spdk_bdev_io_wait_cb cb_fn));
24aefa99f1SArtur Paszkiewicz DEFINE_STUB_V(raid_bdev_process_request_complete, (struct raid_bdev_process_request *process_req,
25aefa99f1SArtur Paszkiewicz 		int status));
26aefa99f1SArtur Paszkiewicz DEFINE_STUB_V(raid_bdev_io_init, (struct raid_bdev_io *raid_io,
27aefa99f1SArtur Paszkiewicz 				  struct raid_bdev_io_channel *raid_ch,
28aefa99f1SArtur Paszkiewicz 				  enum spdk_bdev_io_type type, uint64_t offset_blocks,
29aefa99f1SArtur Paszkiewicz 				  uint64_t num_blocks, struct iovec *iovs, int iovcnt, void *md_buf,
30aefa99f1SArtur Paszkiewicz 				  struct spdk_memory_domain *memory_domain, void *memory_domain_ctx));
311b9c5629SArtur Paszkiewicz DEFINE_STUB(raid_bdev_remap_dix_reftag, int, (void *md_buf, uint64_t num_blocks,
321b9c5629SArtur Paszkiewicz 		struct spdk_bdev *bdev, uint32_t remapped_offset), -1);
33*3b9baa5fSLoïc Yavercovski DEFINE_STUB(spdk_bdev_notify_blockcnt_change, int, (struct spdk_bdev *bdev, uint64_t size), 0);
3469038a94SKrzysztof Smolinski 
35cc94f303SArtur Paszkiewicz int
36cc94f303SArtur Paszkiewicz spdk_bdev_readv_blocks_ext(struct spdk_bdev_desc *desc,
37cc94f303SArtur Paszkiewicz 			   struct spdk_io_channel *ch,
38cc94f303SArtur Paszkiewicz 			   struct iovec *iov, int iovcnt, uint64_t offset_blocks, uint64_t num_blocks,
39cc94f303SArtur Paszkiewicz 			   spdk_bdev_io_completion_cb cb, void *cb_arg, struct spdk_bdev_ext_io_opts *opts)
40cc94f303SArtur Paszkiewicz {
41cc94f303SArtur Paszkiewicz 	g_last_io_desc = desc;
42cc94f303SArtur Paszkiewicz 	g_last_io_cb = cb;
43cc94f303SArtur Paszkiewicz 
44cc94f303SArtur Paszkiewicz 	return 0;
45cc94f303SArtur Paszkiewicz }
46cc94f303SArtur Paszkiewicz 
47cc94f303SArtur Paszkiewicz int
48cc94f303SArtur Paszkiewicz spdk_bdev_writev_blocks_ext(struct spdk_bdev_desc *desc,
49cc94f303SArtur Paszkiewicz 			    struct spdk_io_channel *ch,
50cc94f303SArtur Paszkiewicz 			    struct iovec *iov, int iovcnt, uint64_t offset_blocks, uint64_t num_blocks,
51cc94f303SArtur Paszkiewicz 			    spdk_bdev_io_completion_cb cb, void *cb_arg, struct spdk_bdev_ext_io_opts *opts)
52cc94f303SArtur Paszkiewicz {
53cc94f303SArtur Paszkiewicz 	g_last_io_desc = desc;
54cc94f303SArtur Paszkiewicz 	g_last_io_cb = cb;
55cc94f303SArtur Paszkiewicz 
56cc94f303SArtur Paszkiewicz 	return 0;
57cc94f303SArtur Paszkiewicz }
58cc94f303SArtur Paszkiewicz 
59b0b0889eSArtur Paszkiewicz void
60b0b0889eSArtur Paszkiewicz raid_bdev_fail_base_bdev(struct raid_base_bdev_info *base_info)
61b0b0889eSArtur Paszkiewicz {
62b0b0889eSArtur Paszkiewicz 	base_info->is_failed = true;
63b0b0889eSArtur Paszkiewicz }
64b0b0889eSArtur Paszkiewicz 
6569038a94SKrzysztof Smolinski static int
6669038a94SKrzysztof Smolinski test_setup(void)
6769038a94SKrzysztof Smolinski {
6869038a94SKrzysztof Smolinski 	uint8_t num_base_bdevs_values[] = { 2, 3 };
6969038a94SKrzysztof Smolinski 	uint64_t base_bdev_blockcnt_values[] = { 1, 1024, 1024 * 1024 };
7069038a94SKrzysztof Smolinski 	uint32_t base_bdev_blocklen_values[] = { 512, 4096 };
7169038a94SKrzysztof Smolinski 	uint8_t *num_base_bdevs;
7269038a94SKrzysztof Smolinski 	uint64_t *base_bdev_blockcnt;
7369038a94SKrzysztof Smolinski 	uint32_t *base_bdev_blocklen;
7469038a94SKrzysztof Smolinski 	uint64_t params_count;
7569038a94SKrzysztof Smolinski 	int rc;
7669038a94SKrzysztof Smolinski 
7769038a94SKrzysztof Smolinski 	params_count = SPDK_COUNTOF(num_base_bdevs_values) *
7869038a94SKrzysztof Smolinski 		       SPDK_COUNTOF(base_bdev_blockcnt_values) *
7969038a94SKrzysztof Smolinski 		       SPDK_COUNTOF(base_bdev_blocklen_values);
8069038a94SKrzysztof Smolinski 	rc = raid_test_params_alloc(params_count);
8169038a94SKrzysztof Smolinski 	if (rc) {
8269038a94SKrzysztof Smolinski 		return rc;
8369038a94SKrzysztof Smolinski 	}
8469038a94SKrzysztof Smolinski 
8569038a94SKrzysztof Smolinski 	ARRAY_FOR_EACH(num_base_bdevs_values, num_base_bdevs) {
8669038a94SKrzysztof Smolinski 		ARRAY_FOR_EACH(base_bdev_blockcnt_values, base_bdev_blockcnt) {
8769038a94SKrzysztof Smolinski 			ARRAY_FOR_EACH(base_bdev_blocklen_values, base_bdev_blocklen) {
8899537401SArtur Paszkiewicz 				struct raid_params params = {
8999537401SArtur Paszkiewicz 					.num_base_bdevs = *num_base_bdevs,
9099537401SArtur Paszkiewicz 					.base_bdev_blockcnt = *base_bdev_blockcnt,
9199537401SArtur Paszkiewicz 					.base_bdev_blocklen = *base_bdev_blocklen,
9299537401SArtur Paszkiewicz 				};
9369038a94SKrzysztof Smolinski 				raid_test_params_add(&params);
9469038a94SKrzysztof Smolinski 			}
9569038a94SKrzysztof Smolinski 		}
9669038a94SKrzysztof Smolinski 	}
9769038a94SKrzysztof Smolinski 
9869038a94SKrzysztof Smolinski 	return 0;
9969038a94SKrzysztof Smolinski }
10069038a94SKrzysztof Smolinski 
10169038a94SKrzysztof Smolinski static int
10269038a94SKrzysztof Smolinski test_cleanup(void)
10369038a94SKrzysztof Smolinski {
10469038a94SKrzysztof Smolinski 	raid_test_params_free();
10569038a94SKrzysztof Smolinski 	return 0;
10669038a94SKrzysztof Smolinski }
10769038a94SKrzysztof Smolinski 
10869038a94SKrzysztof Smolinski static struct raid1_info *
10969038a94SKrzysztof Smolinski create_raid1(struct raid_params *params)
11069038a94SKrzysztof Smolinski {
11169038a94SKrzysztof Smolinski 	struct raid_bdev *raid_bdev = raid_test_create_raid_bdev(params, &g_raid1_module);
11269038a94SKrzysztof Smolinski 
11369038a94SKrzysztof Smolinski 	SPDK_CU_ASSERT_FATAL(raid1_start(raid_bdev) == 0);
11469038a94SKrzysztof Smolinski 
11569038a94SKrzysztof Smolinski 	return raid_bdev->module_private;
11669038a94SKrzysztof Smolinski }
11769038a94SKrzysztof Smolinski 
11869038a94SKrzysztof Smolinski static void
11969038a94SKrzysztof Smolinski delete_raid1(struct raid1_info *r1_info)
12069038a94SKrzysztof Smolinski {
12169038a94SKrzysztof Smolinski 	struct raid_bdev *raid_bdev = r1_info->raid_bdev;
12269038a94SKrzysztof Smolinski 
12369038a94SKrzysztof Smolinski 	raid1_stop(raid_bdev);
12469038a94SKrzysztof Smolinski 
12569038a94SKrzysztof Smolinski 	raid_test_delete_raid_bdev(raid_bdev);
12669038a94SKrzysztof Smolinski }
12769038a94SKrzysztof Smolinski 
12869038a94SKrzysztof Smolinski static void
12969038a94SKrzysztof Smolinski test_raid1_start(void)
13069038a94SKrzysztof Smolinski {
13169038a94SKrzysztof Smolinski 	struct raid_params *params;
13269038a94SKrzysztof Smolinski 
13369038a94SKrzysztof Smolinski 	RAID_PARAMS_FOR_EACH(params) {
13469038a94SKrzysztof Smolinski 		struct raid1_info *r1_info;
13569038a94SKrzysztof Smolinski 
13669038a94SKrzysztof Smolinski 		r1_info = create_raid1(params);
13769038a94SKrzysztof Smolinski 
13869038a94SKrzysztof Smolinski 		SPDK_CU_ASSERT_FATAL(r1_info != NULL);
13969038a94SKrzysztof Smolinski 
14069038a94SKrzysztof Smolinski 		CU_ASSERT_EQUAL(r1_info->raid_bdev->level, RAID1);
14169038a94SKrzysztof Smolinski 		CU_ASSERT_EQUAL(r1_info->raid_bdev->bdev.blockcnt, params->base_bdev_blockcnt);
14269038a94SKrzysztof Smolinski 		CU_ASSERT_PTR_EQUAL(r1_info->raid_bdev->module, &g_raid1_module);
14369038a94SKrzysztof Smolinski 
14469038a94SKrzysztof Smolinski 		delete_raid1(r1_info);
14569038a94SKrzysztof Smolinski 	}
14669038a94SKrzysztof Smolinski }
14769038a94SKrzysztof Smolinski 
1485da1742bSKrzysztof Smolinski static struct raid_bdev_io *
1495da1742bSKrzysztof Smolinski get_raid_io(struct raid1_info *r1_info, struct raid_bdev_io_channel *raid_ch,
1505da1742bSKrzysztof Smolinski 	    enum spdk_bdev_io_type io_type, uint64_t num_blocks)
1515da1742bSKrzysztof Smolinski {
1525da1742bSKrzysztof Smolinski 	struct raid_bdev_io *raid_io;
1535da1742bSKrzysztof Smolinski 
154a4e1703eSArtur Paszkiewicz 	raid_io = calloc(1, sizeof(*raid_io));
155a4e1703eSArtur Paszkiewicz 	SPDK_CU_ASSERT_FATAL(raid_io != NULL);
1565da1742bSKrzysztof Smolinski 
157a4e1703eSArtur Paszkiewicz 	raid_test_bdev_io_init(raid_io, r1_info->raid_bdev, raid_ch, io_type, 0, num_blocks, NULL, 0, NULL);
1585da1742bSKrzysztof Smolinski 
1595da1742bSKrzysztof Smolinski 	return raid_io;
1605da1742bSKrzysztof Smolinski }
1615da1742bSKrzysztof Smolinski 
1625da1742bSKrzysztof Smolinski static void
1635da1742bSKrzysztof Smolinski put_raid_io(struct raid_bdev_io *raid_io)
1645da1742bSKrzysztof Smolinski {
165a4e1703eSArtur Paszkiewicz 	free(raid_io);
166a4e1703eSArtur Paszkiewicz }
167a4e1703eSArtur Paszkiewicz 
168fc3c9b37SArtur Paszkiewicz void
169a4e1703eSArtur Paszkiewicz raid_test_bdev_io_complete(struct raid_bdev_io *raid_io, enum spdk_bdev_io_status status)
170a4e1703eSArtur Paszkiewicz {
171b0b0889eSArtur Paszkiewicz 	g_io_status = status;
172a4e1703eSArtur Paszkiewicz 
173a4e1703eSArtur Paszkiewicz 	put_raid_io(raid_io);
1745da1742bSKrzysztof Smolinski }
1755da1742bSKrzysztof Smolinski 
1765da1742bSKrzysztof Smolinski static void
1775da1742bSKrzysztof Smolinski run_for_each_raid1_config(void (*test_fn)(struct raid_bdev *raid_bdev,
1785da1742bSKrzysztof Smolinski 			  struct raid_bdev_io_channel *raid_ch))
1795da1742bSKrzysztof Smolinski {
1805da1742bSKrzysztof Smolinski 	struct raid_params *params;
1815da1742bSKrzysztof Smolinski 
1825da1742bSKrzysztof Smolinski 	RAID_PARAMS_FOR_EACH(params) {
1835da1742bSKrzysztof Smolinski 		struct raid1_info *r1_info;
18459d79ec5SArtur Paszkiewicz 		struct raid_bdev_io_channel *raid_ch;
1855da1742bSKrzysztof Smolinski 
1865da1742bSKrzysztof Smolinski 		r1_info = create_raid1(params);
18759d79ec5SArtur Paszkiewicz 		raid_ch = raid_test_create_io_channel(r1_info->raid_bdev);
1885da1742bSKrzysztof Smolinski 
18959d79ec5SArtur Paszkiewicz 		test_fn(r1_info->raid_bdev, raid_ch);
1905da1742bSKrzysztof Smolinski 
19159d79ec5SArtur Paszkiewicz 		raid_test_destroy_io_channel(raid_ch);
1925da1742bSKrzysztof Smolinski 		delete_raid1(r1_info);
1935da1742bSKrzysztof Smolinski 	}
1945da1742bSKrzysztof Smolinski }
1955da1742bSKrzysztof Smolinski 
1965da1742bSKrzysztof Smolinski static void
1975da1742bSKrzysztof Smolinski _test_raid1_read_balancing(struct raid_bdev *raid_bdev, struct raid_bdev_io_channel *raid_ch)
1985da1742bSKrzysztof Smolinski {
1995da1742bSKrzysztof Smolinski 	struct raid1_info *r1_info = raid_bdev->module_private;
2006e03e49bSArtur Paszkiewicz 	struct raid1_io_channel *raid1_ch = raid_bdev_channel_get_module_ctx(raid_ch);
2015da1742bSKrzysztof Smolinski 	uint8_t big_io_base_bdev_idx;
2025da1742bSKrzysztof Smolinski 	const uint64_t big_io_blocks = 256;
2035da1742bSKrzysztof Smolinski 	const uint64_t small_io_blocks = 4;
2045da1742bSKrzysztof Smolinski 	uint64_t blocks_remaining;
2055da1742bSKrzysztof Smolinski 	struct raid_bdev_io *raid_io;
2065da1742bSKrzysztof Smolinski 	uint8_t i;
2075da1742bSKrzysztof Smolinski 	int n;
2085da1742bSKrzysztof Smolinski 
2095da1742bSKrzysztof Smolinski 	/* same sized IOs should be be spread evenly across all base bdevs */
2105da1742bSKrzysztof Smolinski 	for (n = 0; n < 3; n++) {
2115da1742bSKrzysztof Smolinski 		for (i = 0; i < raid_bdev->num_base_bdevs; i++) {
2125da1742bSKrzysztof Smolinski 			raid_io = get_raid_io(r1_info, raid_ch, SPDK_BDEV_IO_TYPE_READ, small_io_blocks);
2135da1742bSKrzysztof Smolinski 			raid1_submit_read_request(raid_io);
2145da1742bSKrzysztof Smolinski 			CU_ASSERT(raid_io->base_bdev_io_submitted == i);
2155da1742bSKrzysztof Smolinski 			put_raid_io(raid_io);
2165da1742bSKrzysztof Smolinski 		}
2175da1742bSKrzysztof Smolinski 	}
2185da1742bSKrzysztof Smolinski 
2195da1742bSKrzysztof Smolinski 	for (i = 0; i < raid_bdev->num_base_bdevs; i++) {
2205da1742bSKrzysztof Smolinski 		CU_ASSERT(raid1_ch->read_blocks_outstanding[i] == n * small_io_blocks);
2215da1742bSKrzysztof Smolinski 		raid1_ch->read_blocks_outstanding[i] = 0;
2225da1742bSKrzysztof Smolinski 	}
2235da1742bSKrzysztof Smolinski 
2245da1742bSKrzysztof Smolinski 	/*
2255da1742bSKrzysztof Smolinski 	 * Submit one big and many small IOs. The small IOs should not land on the same base bdev
2265da1742bSKrzysztof Smolinski 	 * as the big until the submitted block count is matched.
2275da1742bSKrzysztof Smolinski 	 */
2285da1742bSKrzysztof Smolinski 	raid_io = get_raid_io(r1_info, raid_ch, SPDK_BDEV_IO_TYPE_READ, big_io_blocks);
2295da1742bSKrzysztof Smolinski 	raid1_submit_read_request(raid_io);
2305da1742bSKrzysztof Smolinski 	big_io_base_bdev_idx = raid_io->base_bdev_io_submitted;
2315da1742bSKrzysztof Smolinski 	put_raid_io(raid_io);
2325da1742bSKrzysztof Smolinski 
2335da1742bSKrzysztof Smolinski 	blocks_remaining = big_io_blocks * (raid_bdev->num_base_bdevs - 1);
2345da1742bSKrzysztof Smolinski 	while (blocks_remaining > 0) {
2355da1742bSKrzysztof Smolinski 		raid_io = get_raid_io(r1_info, raid_ch, SPDK_BDEV_IO_TYPE_READ, small_io_blocks);
2365da1742bSKrzysztof Smolinski 		raid1_submit_read_request(raid_io);
2375da1742bSKrzysztof Smolinski 		CU_ASSERT(raid_io->base_bdev_io_submitted != big_io_base_bdev_idx);
2385da1742bSKrzysztof Smolinski 		put_raid_io(raid_io);
2395da1742bSKrzysztof Smolinski 		blocks_remaining -= small_io_blocks;
2405da1742bSKrzysztof Smolinski 	}
2415da1742bSKrzysztof Smolinski 
2425da1742bSKrzysztof Smolinski 	for (i = 0; i < raid_bdev->num_base_bdevs; i++) {
2435da1742bSKrzysztof Smolinski 		CU_ASSERT(raid1_ch->read_blocks_outstanding[i] == big_io_blocks);
2445da1742bSKrzysztof Smolinski 	}
2455da1742bSKrzysztof Smolinski 
2465da1742bSKrzysztof Smolinski 	raid_io = get_raid_io(r1_info, raid_ch, SPDK_BDEV_IO_TYPE_READ, small_io_blocks);
2475da1742bSKrzysztof Smolinski 	raid1_submit_read_request(raid_io);
2485da1742bSKrzysztof Smolinski 	CU_ASSERT(raid_io->base_bdev_io_submitted == big_io_base_bdev_idx);
2495da1742bSKrzysztof Smolinski 	put_raid_io(raid_io);
2505da1742bSKrzysztof Smolinski }
2515da1742bSKrzysztof Smolinski 
2525da1742bSKrzysztof Smolinski static void
2535da1742bSKrzysztof Smolinski test_raid1_read_balancing(void)
2545da1742bSKrzysztof Smolinski {
2555da1742bSKrzysztof Smolinski 	run_for_each_raid1_config(_test_raid1_read_balancing);
2565da1742bSKrzysztof Smolinski }
2575da1742bSKrzysztof Smolinski 
258b0b0889eSArtur Paszkiewicz static void
259b0b0889eSArtur Paszkiewicz _test_raid1_write_error(struct raid_bdev *raid_bdev, struct raid_bdev_io_channel *raid_ch)
260b0b0889eSArtur Paszkiewicz {
261b0b0889eSArtur Paszkiewicz 	struct raid1_info *r1_info = raid_bdev->module_private;
262b0b0889eSArtur Paszkiewicz 	struct raid_bdev_io *raid_io;
263b0b0889eSArtur Paszkiewicz 	struct raid_base_bdev_info *base_info;
264b0b0889eSArtur Paszkiewicz 	struct spdk_bdev_io bdev_io = {};
265b0b0889eSArtur Paszkiewicz 	bool bdev_io_success;
266b0b0889eSArtur Paszkiewicz 
267b0b0889eSArtur Paszkiewicz 	/* first completion failed */
268b0b0889eSArtur Paszkiewicz 	g_io_status = SPDK_BDEV_IO_STATUS_PENDING;
269b0b0889eSArtur Paszkiewicz 	raid_io = get_raid_io(r1_info, raid_ch, SPDK_BDEV_IO_TYPE_WRITE, 64);
270b0b0889eSArtur Paszkiewicz 	raid1_submit_write_request(raid_io);
271b0b0889eSArtur Paszkiewicz 
272b0b0889eSArtur Paszkiewicz 	RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
273b0b0889eSArtur Paszkiewicz 		base_info->is_failed = false;
274b0b0889eSArtur Paszkiewicz 		if (raid_bdev_base_bdev_slot(base_info) == 0) {
275b0b0889eSArtur Paszkiewicz 			bdev_io_success = false;
276b0b0889eSArtur Paszkiewicz 		} else {
277b0b0889eSArtur Paszkiewicz 			bdev_io_success = true;
278b0b0889eSArtur Paszkiewicz 		}
279b0b0889eSArtur Paszkiewicz 		bdev_io.bdev = base_info->desc->bdev;
280b0b0889eSArtur Paszkiewicz 		raid1_write_bdev_io_completion(&bdev_io, bdev_io_success, raid_io);
281b0b0889eSArtur Paszkiewicz 		CU_ASSERT(base_info->is_failed == !bdev_io_success);
282b0b0889eSArtur Paszkiewicz 	}
283b0b0889eSArtur Paszkiewicz 	CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS);
284b0b0889eSArtur Paszkiewicz 
285b0b0889eSArtur Paszkiewicz 	/* all except first completion failed */
286b0b0889eSArtur Paszkiewicz 	g_io_status = SPDK_BDEV_IO_STATUS_PENDING;
287b0b0889eSArtur Paszkiewicz 	raid_io = get_raid_io(r1_info, raid_ch, SPDK_BDEV_IO_TYPE_WRITE, 64);
288b0b0889eSArtur Paszkiewicz 	raid1_submit_write_request(raid_io);
289b0b0889eSArtur Paszkiewicz 
290b0b0889eSArtur Paszkiewicz 	RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
291b0b0889eSArtur Paszkiewicz 		base_info->is_failed = false;
292b0b0889eSArtur Paszkiewicz 		if (raid_bdev_base_bdev_slot(base_info) != 0) {
293b0b0889eSArtur Paszkiewicz 			bdev_io_success = false;
294b0b0889eSArtur Paszkiewicz 		} else {
295b0b0889eSArtur Paszkiewicz 			bdev_io_success = true;
296b0b0889eSArtur Paszkiewicz 		}
297b0b0889eSArtur Paszkiewicz 		bdev_io.bdev = base_info->desc->bdev;
298b0b0889eSArtur Paszkiewicz 		raid1_write_bdev_io_completion(&bdev_io, bdev_io_success, raid_io);
299b0b0889eSArtur Paszkiewicz 		CU_ASSERT(base_info->is_failed == !bdev_io_success);
300b0b0889eSArtur Paszkiewicz 	}
301b0b0889eSArtur Paszkiewicz 	CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS);
302b0b0889eSArtur Paszkiewicz 
303b0b0889eSArtur Paszkiewicz 	/* all completions failed */
304b0b0889eSArtur Paszkiewicz 	g_io_status = SPDK_BDEV_IO_STATUS_PENDING;
305b0b0889eSArtur Paszkiewicz 	raid_io = get_raid_io(r1_info, raid_ch, SPDK_BDEV_IO_TYPE_WRITE, 64);
306b0b0889eSArtur Paszkiewicz 	raid1_submit_write_request(raid_io);
307b0b0889eSArtur Paszkiewicz 
308b0b0889eSArtur Paszkiewicz 	bdev_io_success = false;
309b0b0889eSArtur Paszkiewicz 	RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) {
310b0b0889eSArtur Paszkiewicz 		base_info->is_failed = false;
311b0b0889eSArtur Paszkiewicz 		bdev_io.bdev = base_info->desc->bdev;
312b0b0889eSArtur Paszkiewicz 		raid1_write_bdev_io_completion(&bdev_io, bdev_io_success, raid_io);
313b0b0889eSArtur Paszkiewicz 		CU_ASSERT(base_info->is_failed == !bdev_io_success);
314b0b0889eSArtur Paszkiewicz 	}
315b0b0889eSArtur Paszkiewicz 	CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_FAILED);
316b0b0889eSArtur Paszkiewicz }
317b0b0889eSArtur Paszkiewicz 
318b0b0889eSArtur Paszkiewicz static void
319b0b0889eSArtur Paszkiewicz test_raid1_write_error(void)
320b0b0889eSArtur Paszkiewicz {
321b0b0889eSArtur Paszkiewicz 	run_for_each_raid1_config(_test_raid1_write_error);
322b0b0889eSArtur Paszkiewicz }
323b0b0889eSArtur Paszkiewicz 
324cc94f303SArtur Paszkiewicz static void
325cc94f303SArtur Paszkiewicz _test_raid1_read_error(struct raid_bdev *raid_bdev, struct raid_bdev_io_channel *raid_ch)
326cc94f303SArtur Paszkiewicz {
327cc94f303SArtur Paszkiewicz 	struct raid1_info *r1_info = raid_bdev->module_private;
328cc94f303SArtur Paszkiewicz 	struct raid_base_bdev_info *base_info = &raid_bdev->base_bdev_info[0];
329cc94f303SArtur Paszkiewicz 	struct raid1_io_channel *raid1_ch = raid_bdev_channel_get_module_ctx(raid_ch);
330cc94f303SArtur Paszkiewicz 	struct raid_bdev_io *raid_io;
331cc94f303SArtur Paszkiewicz 	struct spdk_bdev_io bdev_io = {};
332cc94f303SArtur Paszkiewicz 
333cc94f303SArtur Paszkiewicz 	/* first read fails, the second succeeds */
334cc94f303SArtur Paszkiewicz 	base_info->is_failed = false;
335cc94f303SArtur Paszkiewicz 	g_io_status = SPDK_BDEV_IO_STATUS_PENDING;
336cc94f303SArtur Paszkiewicz 	raid_io = get_raid_io(r1_info, raid_ch, SPDK_BDEV_IO_TYPE_READ, 64);
337cc94f303SArtur Paszkiewicz 	raid1_submit_read_request(raid_io);
338cc94f303SArtur Paszkiewicz 	CU_ASSERT(raid_io->base_bdev_io_submitted == 0);
339cc94f303SArtur Paszkiewicz 	CU_ASSERT(raid_io->base_bdev_io_remaining == 0);
340cc94f303SArtur Paszkiewicz 
341cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_desc == base_info->desc);
342cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_cb == raid1_read_bdev_io_completion);
343cc94f303SArtur Paszkiewicz 	raid1_read_bdev_io_completion(&bdev_io, false, raid_io);
344cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_PENDING);
345cc94f303SArtur Paszkiewicz 	CU_ASSERT((uint8_t)raid_io->base_bdev_io_remaining == (raid_bdev->num_base_bdevs - 1));
346cc94f303SArtur Paszkiewicz 
347cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_desc == raid_bdev->base_bdev_info[1].desc);
348cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_cb == raid1_read_other_completion);
349cc94f303SArtur Paszkiewicz 	raid1_read_other_completion(&bdev_io, true, raid_io);
350cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_PENDING);
351cc94f303SArtur Paszkiewicz 
352cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_desc == base_info->desc);
353cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_cb == raid1_correct_read_error_completion);
354cc94f303SArtur Paszkiewicz 	raid1_correct_read_error_completion(&bdev_io, true, raid_io);
355cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS);
356cc94f303SArtur Paszkiewicz 	CU_ASSERT(base_info->is_failed == false);
357cc94f303SArtur Paszkiewicz 
358cc94f303SArtur Paszkiewicz 	/* rewrite fails */
359cc94f303SArtur Paszkiewicz 	base_info->is_failed = false;
360cc94f303SArtur Paszkiewicz 	g_io_status = SPDK_BDEV_IO_STATUS_PENDING;
361cc94f303SArtur Paszkiewicz 	raid_io = get_raid_io(r1_info, raid_ch, SPDK_BDEV_IO_TYPE_READ, 64);
362cc94f303SArtur Paszkiewicz 	raid1_submit_read_request(raid_io);
363cc94f303SArtur Paszkiewicz 	CU_ASSERT(raid_io->base_bdev_io_submitted == 0);
364cc94f303SArtur Paszkiewicz 	CU_ASSERT(raid_io->base_bdev_io_remaining == 0);
365cc94f303SArtur Paszkiewicz 
366cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_desc == base_info->desc);
367cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_cb == raid1_read_bdev_io_completion);
368cc94f303SArtur Paszkiewicz 	raid1_read_bdev_io_completion(&bdev_io, false, raid_io);
369cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_PENDING);
370cc94f303SArtur Paszkiewicz 	CU_ASSERT((uint8_t)raid_io->base_bdev_io_remaining == (raid_bdev->num_base_bdevs - 1));
371cc94f303SArtur Paszkiewicz 
372cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_desc == raid_bdev->base_bdev_info[1].desc);
373cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_cb == raid1_read_other_completion);
374cc94f303SArtur Paszkiewicz 	raid1_read_other_completion(&bdev_io, true, raid_io);
375cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_PENDING);
376cc94f303SArtur Paszkiewicz 
377cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_desc == base_info->desc);
378cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_cb == raid1_correct_read_error_completion);
379cc94f303SArtur Paszkiewicz 	raid1_correct_read_error_completion(&bdev_io, false, raid_io);
380cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS);
381cc94f303SArtur Paszkiewicz 	CU_ASSERT(base_info->is_failed == true);
382cc94f303SArtur Paszkiewicz 
383cc94f303SArtur Paszkiewicz 	/* only the last read succeeds */
384cc94f303SArtur Paszkiewicz 	base_info->is_failed = false;
385cc94f303SArtur Paszkiewicz 	g_io_status = SPDK_BDEV_IO_STATUS_PENDING;
386cc94f303SArtur Paszkiewicz 	raid_io = get_raid_io(r1_info, raid_ch, SPDK_BDEV_IO_TYPE_READ, 64);
387cc94f303SArtur Paszkiewicz 	raid1_submit_read_request(raid_io);
388cc94f303SArtur Paszkiewicz 	CU_ASSERT(raid_io->base_bdev_io_submitted == 0);
389cc94f303SArtur Paszkiewicz 	CU_ASSERT(raid_io->base_bdev_io_remaining == 0);
390cc94f303SArtur Paszkiewicz 
391cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_desc == base_info->desc);
392cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_cb == raid1_read_bdev_io_completion);
393cc94f303SArtur Paszkiewicz 	raid1_read_bdev_io_completion(&bdev_io, false, raid_io);
394cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_PENDING);
395cc94f303SArtur Paszkiewicz 	CU_ASSERT((uint8_t)raid_io->base_bdev_io_remaining == (raid_bdev->num_base_bdevs - 1));
396cc94f303SArtur Paszkiewicz 
397cc94f303SArtur Paszkiewicz 	while (raid_io->base_bdev_io_remaining > 1) {
398cc94f303SArtur Paszkiewicz 		CU_ASSERT(g_last_io_cb == raid1_read_other_completion);
399cc94f303SArtur Paszkiewicz 		raid1_read_other_completion(&bdev_io, false, raid_io);
400cc94f303SArtur Paszkiewicz 		CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_PENDING);
401cc94f303SArtur Paszkiewicz 	}
402cc94f303SArtur Paszkiewicz 
403cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_desc == raid_bdev->base_bdev_info[raid_bdev->num_base_bdevs - 1].desc);
404cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_cb == raid1_read_other_completion);
405cc94f303SArtur Paszkiewicz 	raid1_read_other_completion(&bdev_io, true, raid_io);
406cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_PENDING);
407cc94f303SArtur Paszkiewicz 
408cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_desc == base_info->desc);
409cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_cb == raid1_correct_read_error_completion);
410cc94f303SArtur Paszkiewicz 	raid1_correct_read_error_completion(&bdev_io, true, raid_io);
411cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS);
412cc94f303SArtur Paszkiewicz 	CU_ASSERT(base_info->is_failed == false);
413cc94f303SArtur Paszkiewicz 
414cc94f303SArtur Paszkiewicz 	/* all reads fail */
415cc94f303SArtur Paszkiewicz 	base_info->is_failed = false;
416cc94f303SArtur Paszkiewicz 	g_io_status = SPDK_BDEV_IO_STATUS_PENDING;
417cc94f303SArtur Paszkiewicz 	raid_io = get_raid_io(r1_info, raid_ch, SPDK_BDEV_IO_TYPE_READ, 64);
418cc94f303SArtur Paszkiewicz 	raid1_submit_read_request(raid_io);
419cc94f303SArtur Paszkiewicz 	CU_ASSERT(raid_io->base_bdev_io_submitted == 0);
420cc94f303SArtur Paszkiewicz 	CU_ASSERT(raid_io->base_bdev_io_remaining == 0);
421cc94f303SArtur Paszkiewicz 
422cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_desc == base_info->desc);
423cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_cb == raid1_read_bdev_io_completion);
424cc94f303SArtur Paszkiewicz 	raid1_read_bdev_io_completion(&bdev_io, false, raid_io);
425cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_PENDING);
426cc94f303SArtur Paszkiewicz 	CU_ASSERT((uint8_t)raid_io->base_bdev_io_remaining == (raid_bdev->num_base_bdevs - 1));
427cc94f303SArtur Paszkiewicz 
428cc94f303SArtur Paszkiewicz 	while (raid_io->base_bdev_io_remaining > 1) {
429cc94f303SArtur Paszkiewicz 		CU_ASSERT(g_last_io_cb == raid1_read_other_completion);
430cc94f303SArtur Paszkiewicz 		raid1_read_other_completion(&bdev_io, false, raid_io);
431cc94f303SArtur Paszkiewicz 		CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_PENDING);
432cc94f303SArtur Paszkiewicz 	}
433cc94f303SArtur Paszkiewicz 
434cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_desc == raid_bdev->base_bdev_info[raid_bdev->num_base_bdevs - 1].desc);
435cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_cb == raid1_read_other_completion);
436cc94f303SArtur Paszkiewicz 	raid1_read_other_completion(&bdev_io, false, raid_io);
437cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_FAILED);
438cc94f303SArtur Paszkiewicz 	CU_ASSERT(base_info->is_failed == true);
439cc94f303SArtur Paszkiewicz 
440cc94f303SArtur Paszkiewicz 	/* read from base bdev #1 fails, read from #0 succeeds */
441cc94f303SArtur Paszkiewicz 	base_info->is_failed = false;
442cc94f303SArtur Paszkiewicz 	base_info = &raid_bdev->base_bdev_info[1];
443cc94f303SArtur Paszkiewicz 	raid1_ch->read_blocks_outstanding[0] = 123;
444cc94f303SArtur Paszkiewicz 	g_io_status = SPDK_BDEV_IO_STATUS_PENDING;
445cc94f303SArtur Paszkiewicz 	raid_io = get_raid_io(r1_info, raid_ch, SPDK_BDEV_IO_TYPE_READ, 64);
446cc94f303SArtur Paszkiewicz 	raid1_submit_read_request(raid_io);
447cc94f303SArtur Paszkiewicz 	CU_ASSERT(raid_io->base_bdev_io_submitted == 1);
448cc94f303SArtur Paszkiewicz 	CU_ASSERT(raid_io->base_bdev_io_remaining == 0);
449cc94f303SArtur Paszkiewicz 
450cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_desc == base_info->desc);
451cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_cb == raid1_read_bdev_io_completion);
452cc94f303SArtur Paszkiewicz 	raid1_read_bdev_io_completion(&bdev_io, false, raid_io);
453cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_PENDING);
454cc94f303SArtur Paszkiewicz 	CU_ASSERT((uint8_t)raid_io->base_bdev_io_remaining == raid_bdev->num_base_bdevs);
455cc94f303SArtur Paszkiewicz 
456cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_desc == raid_bdev->base_bdev_info[0].desc);
457cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_cb == raid1_read_other_completion);
458cc94f303SArtur Paszkiewicz 	raid1_read_other_completion(&bdev_io, true, raid_io);
459cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_PENDING);
460cc94f303SArtur Paszkiewicz 
461cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_desc == base_info->desc);
462cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_cb == raid1_correct_read_error_completion);
463cc94f303SArtur Paszkiewicz 	raid1_correct_read_error_completion(&bdev_io, true, raid_io);
464cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS);
465cc94f303SArtur Paszkiewicz 	CU_ASSERT(base_info->is_failed == false);
466cc94f303SArtur Paszkiewicz 
467cc94f303SArtur Paszkiewicz 	/* base bdev #0 is failed, read from #1 fails, read from next succeeds if N > 2 */
468cc94f303SArtur Paszkiewicz 	base_info->is_failed = false;
469cc94f303SArtur Paszkiewicz 	raid_ch->_base_channels[0] = NULL;
470cc94f303SArtur Paszkiewicz 	g_io_status = SPDK_BDEV_IO_STATUS_PENDING;
471cc94f303SArtur Paszkiewicz 	raid_io = get_raid_io(r1_info, raid_ch, SPDK_BDEV_IO_TYPE_READ, 64);
472cc94f303SArtur Paszkiewicz 	raid1_submit_read_request(raid_io);
473cc94f303SArtur Paszkiewicz 	CU_ASSERT(raid_io->base_bdev_io_submitted == 1);
474cc94f303SArtur Paszkiewicz 	CU_ASSERT(raid_io->base_bdev_io_remaining == 0);
475cc94f303SArtur Paszkiewicz 
476cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_desc == base_info->desc);
477cc94f303SArtur Paszkiewicz 	CU_ASSERT(g_last_io_cb == raid1_read_bdev_io_completion);
478cc94f303SArtur Paszkiewicz 	raid1_read_bdev_io_completion(&bdev_io, false, raid_io);
479cc94f303SArtur Paszkiewicz 	if (raid_bdev->num_base_bdevs > 2) {
480cc94f303SArtur Paszkiewicz 		CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_PENDING);
481cc94f303SArtur Paszkiewicz 		CU_ASSERT((uint8_t)raid_io->base_bdev_io_remaining == (raid_bdev->num_base_bdevs - 2));
482cc94f303SArtur Paszkiewicz 
483cc94f303SArtur Paszkiewicz 		CU_ASSERT(g_last_io_desc == raid_bdev->base_bdev_info[2].desc);
484cc94f303SArtur Paszkiewicz 		CU_ASSERT(g_last_io_cb == raid1_read_other_completion);
485cc94f303SArtur Paszkiewicz 		raid1_read_other_completion(&bdev_io, true, raid_io);
486cc94f303SArtur Paszkiewicz 		CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_PENDING);
487cc94f303SArtur Paszkiewicz 
488cc94f303SArtur Paszkiewicz 		CU_ASSERT(g_last_io_desc == base_info->desc);
489cc94f303SArtur Paszkiewicz 		CU_ASSERT(g_last_io_cb == raid1_correct_read_error_completion);
490cc94f303SArtur Paszkiewicz 		raid1_correct_read_error_completion(&bdev_io, true, raid_io);
491cc94f303SArtur Paszkiewicz 		CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_SUCCESS);
492cc94f303SArtur Paszkiewicz 		CU_ASSERT(base_info->is_failed == false);
493cc94f303SArtur Paszkiewicz 	} else {
494cc94f303SArtur Paszkiewicz 		CU_ASSERT(g_io_status == SPDK_BDEV_IO_STATUS_FAILED);
495cc94f303SArtur Paszkiewicz 		CU_ASSERT(base_info->is_failed == true);
496cc94f303SArtur Paszkiewicz 	}
497cc94f303SArtur Paszkiewicz }
498cc94f303SArtur Paszkiewicz 
499cc94f303SArtur Paszkiewicz static void
500cc94f303SArtur Paszkiewicz test_raid1_read_error(void)
501cc94f303SArtur Paszkiewicz {
502cc94f303SArtur Paszkiewicz 	run_for_each_raid1_config(_test_raid1_read_error);
503cc94f303SArtur Paszkiewicz }
504cc94f303SArtur Paszkiewicz 
50569038a94SKrzysztof Smolinski int
50669038a94SKrzysztof Smolinski main(int argc, char **argv)
50769038a94SKrzysztof Smolinski {
50869038a94SKrzysztof Smolinski 	CU_pSuite suite = NULL;
50969038a94SKrzysztof Smolinski 	unsigned int num_failures;
51069038a94SKrzysztof Smolinski 
51169038a94SKrzysztof Smolinski 	CU_initialize_registry();
51269038a94SKrzysztof Smolinski 
51369038a94SKrzysztof Smolinski 	suite = CU_add_suite("raid1", test_setup, test_cleanup);
51469038a94SKrzysztof Smolinski 	CU_ADD_TEST(suite, test_raid1_start);
5155da1742bSKrzysztof Smolinski 	CU_ADD_TEST(suite, test_raid1_read_balancing);
516b0b0889eSArtur Paszkiewicz 	CU_ADD_TEST(suite, test_raid1_write_error);
517cc94f303SArtur Paszkiewicz 	CU_ADD_TEST(suite, test_raid1_read_error);
51869038a94SKrzysztof Smolinski 
519a73acd9fSKrzysztof Smolinski 	allocate_threads(1);
520a73acd9fSKrzysztof Smolinski 	set_thread(0);
521a73acd9fSKrzysztof Smolinski 
522ea941caeSKonrad Sztyber 	num_failures = spdk_ut_run_tests(argc, argv, NULL);
52369038a94SKrzysztof Smolinski 	CU_cleanup_registry();
52459d79ec5SArtur Paszkiewicz 
52559d79ec5SArtur Paszkiewicz 	free_threads();
52659d79ec5SArtur Paszkiewicz 
52769038a94SKrzysztof Smolinski 	return num_failures;
52869038a94SKrzysztof Smolinski }
529