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 114 raid_bdev->base_bdev_info = calloc(raid_bdev->num_base_bdevs, 115 sizeof(struct raid_base_bdev_info)); 116 SPDK_CU_ASSERT_FATAL(raid_bdev->base_bdev_info != NULL); 117 118 RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) { 119 struct spdk_bdev *bdev; 120 struct spdk_bdev_desc *desc; 121 122 bdev = calloc(1, sizeof(*bdev)); 123 SPDK_CU_ASSERT_FATAL(bdev != NULL); 124 bdev->blockcnt = params->base_bdev_blockcnt; 125 bdev->blocklen = raid_bdev->bdev.blocklen; 126 bdev->md_len = raid_bdev->bdev.md_len; 127 bdev->md_interleave = raid_bdev->bdev.md_interleave; 128 129 desc = calloc(1, sizeof(*desc)); 130 SPDK_CU_ASSERT_FATAL(desc != NULL); 131 desc->bdev = bdev; 132 133 base_info->desc = desc; 134 base_info->data_offset = 0; 135 base_info->data_size = bdev->blockcnt; 136 } 137 138 return raid_bdev; 139 } 140 141 static void 142 raid_test_delete_raid_bdev(struct raid_bdev *raid_bdev) 143 { 144 struct raid_base_bdev_info *base_info; 145 146 RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) { 147 free(base_info->desc->bdev); 148 free(base_info->desc); 149 } 150 free(raid_bdev->base_bdev_info); 151 free(raid_bdev); 152 } 153 154 struct raid_bdev_io_channel { 155 struct spdk_io_channel **_base_channels; 156 struct spdk_io_channel *_module_channel; 157 }; 158 159 struct spdk_io_channel * 160 raid_bdev_channel_get_base_channel(struct raid_bdev_io_channel *raid_ch, uint8_t idx) 161 { 162 return raid_ch->_base_channels[idx]; 163 } 164 165 void * 166 raid_bdev_channel_get_module_ctx(struct raid_bdev_io_channel *raid_ch) 167 { 168 return spdk_io_channel_get_ctx(raid_ch->_module_channel); 169 } 170 171 static struct raid_bdev_io_channel * 172 raid_test_create_io_channel(struct raid_bdev *raid_bdev) 173 { 174 struct raid_bdev_io_channel *raid_ch; 175 uint8_t i; 176 177 raid_ch = calloc(1, sizeof(*raid_ch)); 178 SPDK_CU_ASSERT_FATAL(raid_ch != NULL); 179 180 raid_ch->_base_channels = calloc(raid_bdev->num_base_bdevs, sizeof(struct spdk_io_channel *)); 181 SPDK_CU_ASSERT_FATAL(raid_ch->_base_channels != NULL); 182 183 for (i = 0; i < raid_bdev->num_base_bdevs; i++) { 184 raid_ch->_base_channels[i] = (void *)1; 185 } 186 187 if (raid_bdev->module->get_io_channel) { 188 raid_ch->_module_channel = raid_bdev->module->get_io_channel(raid_bdev); 189 SPDK_CU_ASSERT_FATAL(raid_ch->_module_channel != NULL); 190 } 191 192 return raid_ch; 193 } 194 195 static void 196 raid_test_destroy_io_channel(struct raid_bdev_io_channel *raid_ch) 197 { 198 free(raid_ch->_base_channels); 199 200 if (raid_ch->_module_channel) { 201 spdk_put_io_channel(raid_ch->_module_channel); 202 poll_threads(); 203 } 204 205 free(raid_ch); 206 } 207 208 static void 209 raid_test_bdev_io_init(struct raid_bdev_io *raid_io, struct raid_bdev *raid_bdev, 210 struct raid_bdev_io_channel *raid_ch, 211 enum spdk_bdev_io_type type, uint64_t offset_blocks, 212 uint64_t num_blocks, struct iovec *iovs, int iovcnt, void *md_buf) 213 { 214 memset(raid_io, 0, sizeof(*raid_io)); 215 216 raid_io->raid_bdev = raid_bdev; 217 raid_io->raid_ch = raid_ch; 218 219 raid_io->type = type; 220 raid_io->offset_blocks = offset_blocks; 221 raid_io->num_blocks = num_blocks; 222 raid_io->iovs = iovs; 223 raid_io->iovcnt = iovcnt; 224 raid_io->md_buf = md_buf; 225 226 raid_io->base_bdev_io_status = SPDK_BDEV_IO_STATUS_SUCCESS; 227 } 228 229 /* needs to be implemented in module unit test files */ 230 static void raid_test_bdev_io_complete(struct raid_bdev_io *raid_io, 231 enum spdk_bdev_io_status status); 232 233 void 234 raid_bdev_io_complete(struct raid_bdev_io *raid_io, enum spdk_bdev_io_status status) 235 { 236 if (raid_io->completion_cb != NULL) { 237 raid_io->completion_cb(raid_io, status); 238 } else { 239 raid_test_bdev_io_complete(raid_io, status); 240 } 241 } 242 243 bool 244 raid_bdev_io_complete_part(struct raid_bdev_io *raid_io, uint64_t completed, 245 enum spdk_bdev_io_status status) 246 { 247 SPDK_CU_ASSERT_FATAL(raid_io->base_bdev_io_remaining >= completed); 248 raid_io->base_bdev_io_remaining -= completed; 249 250 if (status != SPDK_BDEV_IO_STATUS_SUCCESS) { 251 raid_io->base_bdev_io_status = status; 252 } 253 254 if (raid_io->base_bdev_io_remaining == 0) { 255 raid_bdev_io_complete(raid_io, raid_io->base_bdev_io_status); 256 return true; 257 } else { 258 return false; 259 } 260 } 261 262 int 263 raid_bdev_readv_blocks_ext(struct raid_base_bdev_info *base_info, struct spdk_io_channel *ch, 264 struct iovec *iov, int iovcnt, uint64_t offset_blocks, 265 uint64_t num_blocks, spdk_bdev_io_completion_cb cb, void *cb_arg, 266 struct spdk_bdev_ext_io_opts *opts) 267 { 268 return spdk_bdev_readv_blocks_ext(base_info->desc, ch, iov, iovcnt, 269 base_info->data_offset + offset_blocks, num_blocks, cb, cb_arg, opts); 270 } 271 272 int 273 raid_bdev_writev_blocks_ext(struct raid_base_bdev_info *base_info, struct spdk_io_channel *ch, 274 struct iovec *iov, int iovcnt, uint64_t offset_blocks, 275 uint64_t num_blocks, spdk_bdev_io_completion_cb cb, void *cb_arg, 276 struct spdk_bdev_ext_io_opts *opts) 277 { 278 return spdk_bdev_writev_blocks_ext(base_info->desc, ch, iov, iovcnt, 279 base_info->data_offset + offset_blocks, num_blocks, cb, cb_arg, opts); 280 } 281