1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2022 Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk_internal/cunit.h" 7 #include "spdk/stdinc.h" 8 #include "bdev/raid/bdev_raid.h" 9 10 struct spdk_bdev_desc { 11 struct spdk_bdev *bdev; 12 }; 13 14 enum raid_params_md_type { 15 RAID_PARAMS_MD_NONE, 16 RAID_PARAMS_MD_SEPARATE, 17 RAID_PARAMS_MD_INTERLEAVED, 18 }; 19 20 struct raid_params { 21 uint8_t num_base_bdevs; 22 uint64_t base_bdev_blockcnt; 23 uint32_t base_bdev_blocklen; 24 uint32_t strip_size; 25 enum raid_params_md_type md_type; 26 }; 27 28 struct raid_params *g_params; 29 size_t g_params_count; 30 size_t g_params_size; 31 32 #define ARRAY_FOR_EACH(a, e) \ 33 for (e = a; e < a + SPDK_COUNTOF(a); e++) 34 35 #define RAID_PARAMS_FOR_EACH(p) \ 36 for (p = g_params; p < g_params + g_params_count; p++) 37 38 struct spdk_bdev * 39 spdk_bdev_desc_get_bdev(struct spdk_bdev_desc *desc) 40 { 41 return desc->bdev; 42 } 43 44 static int 45 raid_test_params_alloc(size_t count) 46 { 47 assert(g_params == NULL); 48 49 g_params_size = count; 50 g_params_count = 0; 51 g_params = calloc(count, sizeof(*g_params)); 52 53 return g_params ? 0 : -ENOMEM; 54 } 55 56 static void 57 raid_test_params_free(void) 58 { 59 g_params_count = 0; 60 g_params_size = 0; 61 free(g_params); 62 } 63 64 static void 65 raid_test_params_add(struct raid_params *params) 66 { 67 assert(g_params_count < g_params_size); 68 69 memcpy(g_params + g_params_count, params, sizeof(*params)); 70 g_params_count++; 71 } 72 73 static struct raid_bdev * 74 raid_test_create_raid_bdev(struct raid_params *params, struct raid_bdev_module *module) 75 { 76 struct raid_bdev *raid_bdev; 77 struct raid_base_bdev_info *base_info; 78 79 SPDK_CU_ASSERT_FATAL(spdk_u32_is_pow2(params->base_bdev_blocklen)); 80 81 raid_bdev = calloc(1, sizeof(*raid_bdev)); 82 SPDK_CU_ASSERT_FATAL(raid_bdev != NULL); 83 84 raid_bdev->module = module; 85 raid_bdev->level = module->level; 86 raid_bdev->num_base_bdevs = params->num_base_bdevs; 87 88 switch (raid_bdev->module->base_bdevs_constraint.type) { 89 case CONSTRAINT_MAX_BASE_BDEVS_REMOVED: 90 raid_bdev->min_base_bdevs_operational = raid_bdev->num_base_bdevs - 91 raid_bdev->module->base_bdevs_constraint.value; 92 break; 93 case CONSTRAINT_MIN_BASE_BDEVS_OPERATIONAL: 94 raid_bdev->min_base_bdevs_operational = raid_bdev->module->base_bdevs_constraint.value; 95 break; 96 case CONSTRAINT_UNSET: 97 raid_bdev->min_base_bdevs_operational = raid_bdev->num_base_bdevs; 98 break; 99 default: 100 CU_FAIL_FATAL("unsupported raid constraint type"); 101 }; 102 103 raid_bdev->bdev.blocklen = params->base_bdev_blocklen; 104 raid_bdev->bdev.md_len = (params->md_type == RAID_PARAMS_MD_NONE ? 0 : 16); 105 raid_bdev->bdev.md_interleave = (params->md_type == RAID_PARAMS_MD_INTERLEAVED); 106 if (raid_bdev->bdev.md_interleave) { 107 raid_bdev->bdev.blocklen += raid_bdev->bdev.md_len; 108 } 109 110 raid_bdev->strip_size = params->strip_size; 111 raid_bdev->strip_size_kb = params->strip_size * params->base_bdev_blocklen / 1024; 112 raid_bdev->strip_size_shift = spdk_u32log2(raid_bdev->strip_size); 113 raid_bdev->blocklen_shift = spdk_u32log2(params->base_bdev_blocklen); 114 115 raid_bdev->base_bdev_info = calloc(raid_bdev->num_base_bdevs, 116 sizeof(struct raid_base_bdev_info)); 117 SPDK_CU_ASSERT_FATAL(raid_bdev->base_bdev_info != NULL); 118 119 RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) { 120 struct spdk_bdev *bdev; 121 struct spdk_bdev_desc *desc; 122 123 bdev = calloc(1, sizeof(*bdev)); 124 SPDK_CU_ASSERT_FATAL(bdev != NULL); 125 bdev->blockcnt = params->base_bdev_blockcnt; 126 bdev->blocklen = raid_bdev->bdev.blocklen; 127 bdev->md_len = raid_bdev->bdev.md_len; 128 bdev->md_interleave = raid_bdev->bdev.md_interleave; 129 130 desc = calloc(1, sizeof(*desc)); 131 SPDK_CU_ASSERT_FATAL(desc != NULL); 132 desc->bdev = bdev; 133 134 base_info->desc = desc; 135 base_info->data_offset = 0; 136 base_info->data_size = bdev->blockcnt; 137 } 138 139 return raid_bdev; 140 } 141 142 static void 143 raid_test_delete_raid_bdev(struct raid_bdev *raid_bdev) 144 { 145 struct raid_base_bdev_info *base_info; 146 147 RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) { 148 free(base_info->desc->bdev); 149 free(base_info->desc); 150 } 151 free(raid_bdev->base_bdev_info); 152 free(raid_bdev); 153 } 154 155 struct raid_bdev_io_channel { 156 struct spdk_io_channel **_base_channels; 157 struct spdk_io_channel *_module_channel; 158 }; 159 160 struct spdk_io_channel * 161 raid_bdev_channel_get_base_channel(struct raid_bdev_io_channel *raid_ch, uint8_t idx) 162 { 163 return raid_ch->_base_channels[idx]; 164 } 165 166 void * 167 raid_bdev_channel_get_module_ctx(struct raid_bdev_io_channel *raid_ch) 168 { 169 return spdk_io_channel_get_ctx(raid_ch->_module_channel); 170 } 171 172 static struct raid_bdev_io_channel * 173 raid_test_create_io_channel(struct raid_bdev *raid_bdev) 174 { 175 struct raid_bdev_io_channel *raid_ch; 176 uint8_t i; 177 178 raid_ch = calloc(1, sizeof(*raid_ch)); 179 SPDK_CU_ASSERT_FATAL(raid_ch != NULL); 180 181 raid_ch->_base_channels = calloc(raid_bdev->num_base_bdevs, sizeof(struct spdk_io_channel *)); 182 SPDK_CU_ASSERT_FATAL(raid_ch->_base_channels != NULL); 183 184 for (i = 0; i < raid_bdev->num_base_bdevs; i++) { 185 raid_ch->_base_channels[i] = (void *)1; 186 } 187 188 if (raid_bdev->module->get_io_channel) { 189 raid_ch->_module_channel = raid_bdev->module->get_io_channel(raid_bdev); 190 SPDK_CU_ASSERT_FATAL(raid_ch->_module_channel != NULL); 191 } 192 193 return raid_ch; 194 } 195 196 static void 197 raid_test_destroy_io_channel(struct raid_bdev_io_channel *raid_ch) 198 { 199 free(raid_ch->_base_channels); 200 201 if (raid_ch->_module_channel) { 202 spdk_put_io_channel(raid_ch->_module_channel); 203 poll_threads(); 204 } 205 206 free(raid_ch); 207 } 208 209 static void 210 raid_test_bdev_io_init(struct raid_bdev_io *raid_io, struct raid_bdev *raid_bdev, 211 struct raid_bdev_io_channel *raid_ch, 212 enum spdk_bdev_io_type type, uint64_t offset_blocks, 213 uint64_t num_blocks, struct iovec *iovs, int iovcnt, void *md_buf) 214 { 215 memset(raid_io, 0, sizeof(*raid_io)); 216 217 raid_io->raid_bdev = raid_bdev; 218 raid_io->raid_ch = raid_ch; 219 220 raid_io->type = type; 221 raid_io->offset_blocks = offset_blocks; 222 raid_io->num_blocks = num_blocks; 223 raid_io->iovs = iovs; 224 raid_io->iovcnt = iovcnt; 225 raid_io->md_buf = md_buf; 226 227 raid_io->base_bdev_io_status = SPDK_BDEV_IO_STATUS_SUCCESS; 228 } 229 230 /* needs to be implemented in module unit test files */ 231 static void raid_test_bdev_io_complete(struct raid_bdev_io *raid_io, 232 enum spdk_bdev_io_status status); 233 234 void 235 raid_bdev_io_complete(struct raid_bdev_io *raid_io, enum spdk_bdev_io_status status) 236 { 237 if (raid_io->completion_cb != NULL) { 238 raid_io->completion_cb(raid_io, status); 239 } else { 240 raid_test_bdev_io_complete(raid_io, status); 241 } 242 } 243 244 bool 245 raid_bdev_io_complete_part(struct raid_bdev_io *raid_io, uint64_t completed, 246 enum spdk_bdev_io_status status) 247 { 248 SPDK_CU_ASSERT_FATAL(raid_io->base_bdev_io_remaining >= completed); 249 raid_io->base_bdev_io_remaining -= completed; 250 251 if (status != SPDK_BDEV_IO_STATUS_SUCCESS) { 252 raid_io->base_bdev_io_status = status; 253 } 254 255 if (raid_io->base_bdev_io_remaining == 0) { 256 raid_bdev_io_complete(raid_io, raid_io->base_bdev_io_status); 257 return true; 258 } else { 259 return false; 260 } 261 } 262 263 int 264 raid_bdev_readv_blocks_ext(struct raid_base_bdev_info *base_info, struct spdk_io_channel *ch, 265 struct iovec *iov, int iovcnt, uint64_t offset_blocks, 266 uint64_t num_blocks, spdk_bdev_io_completion_cb cb, void *cb_arg, 267 struct spdk_bdev_ext_io_opts *opts) 268 { 269 return spdk_bdev_readv_blocks_ext(base_info->desc, ch, iov, iovcnt, 270 base_info->data_offset + offset_blocks, num_blocks, cb, cb_arg, opts); 271 } 272 273 int 274 raid_bdev_writev_blocks_ext(struct raid_base_bdev_info *base_info, struct spdk_io_channel *ch, 275 struct iovec *iov, int iovcnt, uint64_t offset_blocks, 276 uint64_t num_blocks, spdk_bdev_io_completion_cb cb, void *cb_arg, 277 struct spdk_bdev_ext_io_opts *opts) 278 { 279 return spdk_bdev_writev_blocks_ext(base_info->desc, ch, iov, iovcnt, 280 base_info->data_offset + offset_blocks, num_blocks, cb, cb_arg, opts); 281 } 282