1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2022 Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/stdinc.h" 7 #include "spdk_internal/cunit.h" 8 #include "spdk/env.h" 9 10 #include "common/lib/ut_multithread.c" 11 12 #include "bdev/raid/raid1.c" 13 #include "../common.c" 14 15 DEFINE_STUB_V(raid_bdev_module_list_add, (struct raid_bdev_module *raid_module)); 16 DEFINE_STUB_V(raid_bdev_module_stop_done, (struct raid_bdev *raid_bdev)); 17 DEFINE_STUB_V(spdk_bdev_free_io, (struct spdk_bdev_io *bdev_io)); 18 DEFINE_STUB_V(raid_bdev_queue_io_wait, (struct raid_bdev_io *raid_io, struct spdk_bdev *bdev, 19 struct spdk_io_channel *ch, spdk_bdev_io_wait_cb cb_fn)); 20 DEFINE_STUB(spdk_bdev_readv_blocks_with_md, int, (struct spdk_bdev_desc *desc, 21 struct spdk_io_channel *ch, 22 struct iovec *iov, int iovcnt, void *md, 23 uint64_t offset_blocks, uint64_t num_blocks, 24 spdk_bdev_io_completion_cb cb, void *cb_arg), 0); 25 DEFINE_STUB(spdk_bdev_writev_blocks_with_md, int, (struct spdk_bdev_desc *desc, 26 struct spdk_io_channel *ch, 27 struct iovec *iov, int iovcnt, void *md, 28 uint64_t offset_blocks, uint64_t num_blocks, 29 spdk_bdev_io_completion_cb cb, void *cb_arg), 0); 30 DEFINE_STUB(spdk_bdev_readv_blocks_ext, int, (struct spdk_bdev_desc *desc, 31 struct spdk_io_channel *ch, 32 struct iovec *iov, int iovcnt, uint64_t offset_blocks, uint64_t num_blocks, 33 spdk_bdev_io_completion_cb cb, void *cb_arg, struct spdk_bdev_ext_io_opts *opts), 0); 34 DEFINE_STUB(spdk_bdev_writev_blocks_ext, int, (struct spdk_bdev_desc *desc, 35 struct spdk_io_channel *ch, 36 struct iovec *iov, int iovcnt, uint64_t offset_blocks, uint64_t num_blocks, 37 spdk_bdev_io_completion_cb cb, void *cb_arg, struct spdk_bdev_ext_io_opts *opts), 0); 38 39 static int 40 test_setup(void) 41 { 42 uint8_t num_base_bdevs_values[] = { 2, 3 }; 43 uint64_t base_bdev_blockcnt_values[] = { 1, 1024, 1024 * 1024 }; 44 uint32_t base_bdev_blocklen_values[] = { 512, 4096 }; 45 uint8_t *num_base_bdevs; 46 uint64_t *base_bdev_blockcnt; 47 uint32_t *base_bdev_blocklen; 48 struct raid_params params; 49 uint64_t params_count; 50 int rc; 51 52 params_count = SPDK_COUNTOF(num_base_bdevs_values) * 53 SPDK_COUNTOF(base_bdev_blockcnt_values) * 54 SPDK_COUNTOF(base_bdev_blocklen_values); 55 rc = raid_test_params_alloc(params_count); 56 if (rc) { 57 return rc; 58 } 59 60 ARRAY_FOR_EACH(num_base_bdevs_values, num_base_bdevs) { 61 ARRAY_FOR_EACH(base_bdev_blockcnt_values, base_bdev_blockcnt) { 62 ARRAY_FOR_EACH(base_bdev_blocklen_values, base_bdev_blocklen) { 63 params.num_base_bdevs = *num_base_bdevs; 64 params.base_bdev_blockcnt = *base_bdev_blockcnt; 65 params.base_bdev_blocklen = *base_bdev_blocklen; 66 params.strip_size = 0; 67 params.md_len = 0; 68 raid_test_params_add(¶ms); 69 } 70 } 71 } 72 73 return 0; 74 } 75 76 static int 77 test_cleanup(void) 78 { 79 raid_test_params_free(); 80 return 0; 81 } 82 83 static struct raid1_info * 84 create_raid1(struct raid_params *params) 85 { 86 struct raid_bdev *raid_bdev = raid_test_create_raid_bdev(params, &g_raid1_module); 87 88 SPDK_CU_ASSERT_FATAL(raid1_start(raid_bdev) == 0); 89 90 return raid_bdev->module_private; 91 } 92 93 static void 94 delete_raid1(struct raid1_info *r1_info) 95 { 96 struct raid_bdev *raid_bdev = r1_info->raid_bdev; 97 98 raid1_stop(raid_bdev); 99 100 raid_test_delete_raid_bdev(raid_bdev); 101 } 102 103 static void 104 test_raid1_start(void) 105 { 106 struct raid_params *params; 107 108 RAID_PARAMS_FOR_EACH(params) { 109 struct raid1_info *r1_info; 110 111 r1_info = create_raid1(params); 112 113 SPDK_CU_ASSERT_FATAL(r1_info != NULL); 114 115 CU_ASSERT_EQUAL(r1_info->raid_bdev->level, RAID1); 116 CU_ASSERT_EQUAL(r1_info->raid_bdev->bdev.blockcnt, params->base_bdev_blockcnt); 117 CU_ASSERT_PTR_EQUAL(r1_info->raid_bdev->module, &g_raid1_module); 118 119 delete_raid1(r1_info); 120 } 121 } 122 123 static struct raid_bdev_io * 124 get_raid_io(struct raid1_info *r1_info, struct raid_bdev_io_channel *raid_ch, 125 enum spdk_bdev_io_type io_type, uint64_t num_blocks) 126 { 127 struct raid_bdev_io *raid_io; 128 129 raid_io = calloc(1, sizeof(*raid_io)); 130 SPDK_CU_ASSERT_FATAL(raid_io != NULL); 131 132 raid_test_bdev_io_init(raid_io, r1_info->raid_bdev, raid_ch, io_type, 0, num_blocks, NULL, 0, NULL); 133 134 return raid_io; 135 } 136 137 static void 138 put_raid_io(struct raid_bdev_io *raid_io) 139 { 140 free(raid_io); 141 } 142 143 static void 144 raid_test_bdev_io_complete(struct raid_bdev_io *raid_io, enum spdk_bdev_io_status status) 145 { 146 CU_ASSERT(status == SPDK_BDEV_IO_STATUS_SUCCESS); 147 148 put_raid_io(raid_io); 149 } 150 151 static void 152 run_for_each_raid1_config(void (*test_fn)(struct raid_bdev *raid_bdev, 153 struct raid_bdev_io_channel *raid_ch)) 154 { 155 struct raid_params *params; 156 157 RAID_PARAMS_FOR_EACH(params) { 158 struct raid1_info *r1_info; 159 struct raid_bdev_io_channel *raid_ch; 160 161 r1_info = create_raid1(params); 162 raid_ch = raid_test_create_io_channel(r1_info->raid_bdev); 163 164 test_fn(r1_info->raid_bdev, raid_ch); 165 166 raid_test_destroy_io_channel(raid_ch); 167 delete_raid1(r1_info); 168 } 169 } 170 171 static void 172 _test_raid1_read_balancing(struct raid_bdev *raid_bdev, struct raid_bdev_io_channel *raid_ch) 173 { 174 struct raid1_info *r1_info = raid_bdev->module_private; 175 struct raid1_io_channel *raid1_ch = raid_bdev_channel_get_module_ctx(raid_ch); 176 uint8_t big_io_base_bdev_idx; 177 const uint64_t big_io_blocks = 256; 178 const uint64_t small_io_blocks = 4; 179 uint64_t blocks_remaining; 180 struct raid_bdev_io *raid_io; 181 uint8_t i; 182 int n; 183 184 /* same sized IOs should be be spread evenly across all base bdevs */ 185 for (n = 0; n < 3; n++) { 186 for (i = 0; i < raid_bdev->num_base_bdevs; i++) { 187 raid_io = get_raid_io(r1_info, raid_ch, SPDK_BDEV_IO_TYPE_READ, small_io_blocks); 188 raid1_submit_read_request(raid_io); 189 CU_ASSERT(raid_io->base_bdev_io_submitted == i); 190 put_raid_io(raid_io); 191 } 192 } 193 194 for (i = 0; i < raid_bdev->num_base_bdevs; i++) { 195 CU_ASSERT(raid1_ch->read_blocks_outstanding[i] == n * small_io_blocks); 196 raid1_ch->read_blocks_outstanding[i] = 0; 197 } 198 199 /* 200 * Submit one big and many small IOs. The small IOs should not land on the same base bdev 201 * as the big until the submitted block count is matched. 202 */ 203 raid_io = get_raid_io(r1_info, raid_ch, SPDK_BDEV_IO_TYPE_READ, big_io_blocks); 204 raid1_submit_read_request(raid_io); 205 big_io_base_bdev_idx = raid_io->base_bdev_io_submitted; 206 put_raid_io(raid_io); 207 208 blocks_remaining = big_io_blocks * (raid_bdev->num_base_bdevs - 1); 209 while (blocks_remaining > 0) { 210 raid_io = get_raid_io(r1_info, raid_ch, SPDK_BDEV_IO_TYPE_READ, small_io_blocks); 211 raid1_submit_read_request(raid_io); 212 CU_ASSERT(raid_io->base_bdev_io_submitted != big_io_base_bdev_idx); 213 put_raid_io(raid_io); 214 blocks_remaining -= small_io_blocks; 215 } 216 217 for (i = 0; i < raid_bdev->num_base_bdevs; i++) { 218 CU_ASSERT(raid1_ch->read_blocks_outstanding[i] == big_io_blocks); 219 } 220 221 raid_io = get_raid_io(r1_info, raid_ch, SPDK_BDEV_IO_TYPE_READ, small_io_blocks); 222 raid1_submit_read_request(raid_io); 223 CU_ASSERT(raid_io->base_bdev_io_submitted == big_io_base_bdev_idx); 224 put_raid_io(raid_io); 225 } 226 227 static void 228 test_raid1_read_balancing(void) 229 { 230 run_for_each_raid1_config(_test_raid1_read_balancing); 231 } 232 233 int 234 main(int argc, char **argv) 235 { 236 CU_pSuite suite = NULL; 237 unsigned int num_failures; 238 239 CU_initialize_registry(); 240 241 suite = CU_add_suite("raid1", test_setup, test_cleanup); 242 CU_ADD_TEST(suite, test_raid1_start); 243 CU_ADD_TEST(suite, test_raid1_read_balancing); 244 245 allocate_threads(1); 246 set_thread(0); 247 248 num_failures = spdk_ut_run_tests(argc, argv, NULL); 249 CU_cleanup_registry(); 250 251 free_threads(); 252 253 return num_failures; 254 } 255