1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2022 Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/bdev_module.h" 7 #include "spdk/crc32.h" 8 #include "spdk/env.h" 9 #include "spdk/log.h" 10 #include "spdk/string.h" 11 #include "spdk/util.h" 12 13 #include "bdev_raid.h" 14 15 struct raid_bdev_write_sb_ctx { 16 struct raid_bdev *raid_bdev; 17 int status; 18 uint8_t submitted; 19 uint8_t remaining; 20 raid_bdev_write_sb_cb cb; 21 void *cb_ctx; 22 struct spdk_bdev_io_wait_entry wait_entry; 23 }; 24 25 struct raid_bdev_read_sb_ctx { 26 struct spdk_bdev_desc *desc; 27 struct spdk_io_channel *ch; 28 raid_bdev_load_sb_cb cb; 29 void *cb_ctx; 30 void *buf; 31 uint32_t buf_size; 32 }; 33 34 int 35 raid_bdev_alloc_superblock(struct raid_bdev *raid_bdev, uint32_t block_size) 36 { 37 struct raid_bdev_superblock *sb; 38 39 assert(raid_bdev->sb == NULL); 40 41 sb = spdk_dma_zmalloc(SPDK_ALIGN_CEIL(RAID_BDEV_SB_MAX_LENGTH, block_size), 0x1000, NULL); 42 if (!sb) { 43 SPDK_ERRLOG("Failed to allocate raid bdev sb buffer\n"); 44 return -ENOMEM; 45 } 46 47 raid_bdev->sb = sb; 48 49 return 0; 50 } 51 52 void 53 raid_bdev_free_superblock(struct raid_bdev *raid_bdev) 54 { 55 if (raid_bdev->sb_io_buf != NULL && raid_bdev->sb_io_buf != raid_bdev->sb) { 56 assert(spdk_bdev_is_md_interleaved(&raid_bdev->bdev)); 57 spdk_dma_free(raid_bdev->sb_io_buf); 58 raid_bdev->sb_io_buf = NULL; 59 } 60 spdk_dma_free(raid_bdev->sb); 61 raid_bdev->sb = NULL; 62 } 63 64 void 65 raid_bdev_init_superblock(struct raid_bdev *raid_bdev) 66 { 67 struct raid_bdev_superblock *sb = raid_bdev->sb; 68 struct raid_base_bdev_info *base_info; 69 struct raid_bdev_sb_base_bdev *sb_base_bdev; 70 71 memcpy(&sb->signature, RAID_BDEV_SB_SIG, sizeof(sb->signature)); 72 sb->version.major = RAID_BDEV_SB_VERSION_MAJOR; 73 sb->version.minor = RAID_BDEV_SB_VERSION_MINOR; 74 spdk_uuid_copy(&sb->uuid, &raid_bdev->bdev.uuid); 75 snprintf(sb->name, RAID_BDEV_SB_NAME_SIZE, "%s", raid_bdev->bdev.name); 76 sb->raid_size = raid_bdev->bdev.blockcnt; 77 sb->block_size = spdk_bdev_get_data_block_size(&raid_bdev->bdev); 78 sb->level = raid_bdev->level; 79 sb->strip_size = raid_bdev->strip_size; 80 /* TODO: sb->state */ 81 sb->num_base_bdevs = sb->base_bdevs_size = raid_bdev->num_base_bdevs; 82 sb->length = sizeof(*sb) + sizeof(*sb_base_bdev) * sb->base_bdevs_size; 83 84 sb_base_bdev = &sb->base_bdevs[0]; 85 RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) { 86 spdk_uuid_copy(&sb_base_bdev->uuid, &base_info->uuid); 87 sb_base_bdev->data_offset = base_info->data_offset; 88 sb_base_bdev->data_size = base_info->data_size; 89 sb_base_bdev->state = RAID_SB_BASE_BDEV_CONFIGURED; 90 sb_base_bdev->slot = raid_bdev_base_bdev_slot(base_info); 91 sb_base_bdev++; 92 } 93 } 94 95 static int 96 raid_bdev_alloc_sb_io_buf(struct raid_bdev *raid_bdev) 97 { 98 struct raid_bdev_superblock *sb = raid_bdev->sb; 99 100 if (spdk_bdev_is_md_interleaved(&raid_bdev->bdev)) { 101 raid_bdev->sb_io_buf_size = spdk_divide_round_up(sb->length, 102 sb->block_size) * raid_bdev->bdev.blocklen; 103 raid_bdev->sb_io_buf = spdk_dma_zmalloc(raid_bdev->sb_io_buf_size, 0x1000, NULL); 104 if (!raid_bdev->sb_io_buf) { 105 SPDK_ERRLOG("Failed to allocate raid bdev sb io buffer\n"); 106 return -ENOMEM; 107 } 108 } else { 109 raid_bdev->sb_io_buf_size = SPDK_ALIGN_CEIL(sb->length, raid_bdev->bdev.blocklen); 110 raid_bdev->sb_io_buf = raid_bdev->sb; 111 } 112 113 return 0; 114 } 115 116 static void 117 raid_bdev_sb_update_crc(struct raid_bdev_superblock *sb) 118 { 119 sb->crc = 0; 120 sb->crc = spdk_crc32c_update(sb, sb->length, 0); 121 } 122 123 static bool 124 raid_bdev_sb_check_crc(struct raid_bdev_superblock *sb) 125 { 126 uint32_t crc, prev = sb->crc; 127 128 raid_bdev_sb_update_crc(sb); 129 crc = sb->crc; 130 sb->crc = prev; 131 132 return crc == prev; 133 } 134 135 static int 136 raid_bdev_parse_superblock(struct raid_bdev_read_sb_ctx *ctx) 137 { 138 struct raid_bdev_superblock *sb = ctx->buf; 139 struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(ctx->desc); 140 141 if (memcmp(sb->signature, RAID_BDEV_SB_SIG, sizeof(sb->signature))) { 142 SPDK_DEBUGLOG(bdev_raid_sb, "invalid signature\n"); 143 return -EINVAL; 144 } 145 146 if (spdk_divide_round_up(sb->length, spdk_bdev_get_data_block_size(bdev)) > 147 spdk_divide_round_up(ctx->buf_size, bdev->blocklen)) { 148 if (sb->length > RAID_BDEV_SB_MAX_LENGTH) { 149 SPDK_WARNLOG("Incorrect superblock length on bdev %s\n", 150 spdk_bdev_get_name(bdev)); 151 return -EINVAL; 152 } 153 154 return -EAGAIN; 155 } 156 157 if (!raid_bdev_sb_check_crc(sb)) { 158 SPDK_WARNLOG("Incorrect superblock crc on bdev %s\n", spdk_bdev_get_name(bdev)); 159 return -EINVAL; 160 } 161 162 if (sb->version.major != RAID_BDEV_SB_VERSION_MAJOR) { 163 SPDK_ERRLOG("Not supported superblock major version %d on bdev %s\n", 164 sb->version.major, spdk_bdev_get_name(bdev)); 165 return -EINVAL; 166 } 167 168 if (sb->version.minor > RAID_BDEV_SB_VERSION_MINOR) { 169 SPDK_WARNLOG("Superblock minor version %d on bdev %s is higher than the currently supported: %d\n", 170 sb->version.minor, spdk_bdev_get_name(bdev), RAID_BDEV_SB_VERSION_MINOR); 171 } 172 173 return 0; 174 } 175 176 static void 177 raid_bdev_read_sb_ctx_free(struct raid_bdev_read_sb_ctx *ctx) 178 { 179 spdk_dma_free(ctx->buf); 180 181 free(ctx); 182 } 183 184 static void raid_bdev_read_sb_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg); 185 186 static int 187 raid_bdev_read_sb_remainder(struct raid_bdev_read_sb_ctx *ctx) 188 { 189 struct raid_bdev_superblock *sb = ctx->buf; 190 struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(ctx->desc); 191 uint32_t buf_size_prev; 192 void *buf; 193 int rc; 194 195 buf_size_prev = ctx->buf_size; 196 ctx->buf_size = spdk_divide_round_up(spdk_min(sb->length, RAID_BDEV_SB_MAX_LENGTH), 197 spdk_bdev_get_data_block_size(bdev)) * bdev->blocklen; 198 buf = spdk_dma_realloc(ctx->buf, ctx->buf_size, spdk_bdev_get_buf_align(bdev), NULL); 199 if (buf == NULL) { 200 SPDK_ERRLOG("Failed to reallocate buffer\n"); 201 return -ENOMEM; 202 } 203 ctx->buf = buf; 204 205 rc = spdk_bdev_read(ctx->desc, ctx->ch, ctx->buf + buf_size_prev, buf_size_prev, 206 ctx->buf_size - buf_size_prev, raid_bdev_read_sb_cb, ctx); 207 if (rc != 0) { 208 SPDK_ERRLOG("Failed to read bdev %s superblock remainder: %s\n", 209 spdk_bdev_get_name(bdev), spdk_strerror(-rc)); 210 return rc; 211 } 212 213 return 0; 214 } 215 216 static void 217 raid_bdev_read_sb_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) 218 { 219 struct spdk_bdev *bdev = bdev_io->bdev; 220 struct raid_bdev_read_sb_ctx *ctx = cb_arg; 221 struct raid_bdev_superblock *sb = NULL; 222 int status; 223 224 if (spdk_bdev_is_md_interleaved(bdev_io->bdev) && ctx->buf_size > bdev->blocklen) { 225 const uint32_t data_block_size = spdk_bdev_get_data_block_size(bdev); 226 uint32_t i; 227 228 for (i = 1; i < ctx->buf_size / bdev->blocklen; i++) { 229 memmove(ctx->buf + (i * data_block_size), 230 ctx->buf + (i * bdev->blocklen), 231 data_block_size); 232 } 233 } 234 235 spdk_bdev_free_io(bdev_io); 236 237 if (!success) { 238 status = -EIO; 239 goto out; 240 } 241 242 status = raid_bdev_parse_superblock(ctx); 243 if (status == -EAGAIN) { 244 status = raid_bdev_read_sb_remainder(ctx); 245 if (status == 0) { 246 return; 247 } 248 } else if (status != 0) { 249 SPDK_DEBUGLOG(bdev_raid_sb, "failed to parse bdev %s superblock\n", 250 spdk_bdev_get_name(spdk_bdev_desc_get_bdev(ctx->desc))); 251 } else { 252 sb = ctx->buf; 253 } 254 out: 255 ctx->cb(sb, status, ctx->cb_ctx); 256 257 raid_bdev_read_sb_ctx_free(ctx); 258 } 259 260 int 261 raid_bdev_load_base_bdev_superblock(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, 262 raid_bdev_load_sb_cb cb, void *cb_ctx) 263 { 264 struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(desc); 265 struct raid_bdev_read_sb_ctx *ctx; 266 int rc; 267 268 assert(cb != NULL); 269 270 ctx = calloc(1, sizeof(*ctx)); 271 if (!ctx) { 272 return -ENOMEM; 273 } 274 275 ctx->desc = desc; 276 ctx->ch = ch; 277 ctx->cb = cb; 278 ctx->cb_ctx = cb_ctx; 279 ctx->buf_size = spdk_divide_round_up(sizeof(struct raid_bdev_superblock), 280 spdk_bdev_get_data_block_size(bdev)) * bdev->blocklen; 281 ctx->buf = spdk_dma_malloc(ctx->buf_size, spdk_bdev_get_buf_align(bdev), NULL); 282 if (!ctx->buf) { 283 rc = -ENOMEM; 284 goto err; 285 } 286 287 rc = spdk_bdev_read(desc, ch, ctx->buf, 0, ctx->buf_size, raid_bdev_read_sb_cb, ctx); 288 if (rc) { 289 goto err; 290 } 291 292 return 0; 293 err: 294 raid_bdev_read_sb_ctx_free(ctx); 295 296 return rc; 297 } 298 299 static void 300 raid_bdev_write_sb_base_bdev_done(int status, struct raid_bdev_write_sb_ctx *ctx) 301 { 302 if (status != 0) { 303 ctx->status = status; 304 } 305 306 if (--ctx->remaining == 0) { 307 ctx->cb(ctx->status, ctx->raid_bdev, ctx->cb_ctx); 308 free(ctx); 309 } 310 } 311 312 static void 313 raid_bdev_write_superblock_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) 314 { 315 struct raid_bdev_write_sb_ctx *ctx = cb_arg; 316 int status = 0; 317 318 if (!success) { 319 SPDK_ERRLOG("Failed to save superblock on bdev %s\n", bdev_io->bdev->name); 320 status = -EIO; 321 } 322 323 spdk_bdev_free_io(bdev_io); 324 325 raid_bdev_write_sb_base_bdev_done(status, ctx); 326 } 327 328 static void 329 _raid_bdev_write_superblock(void *_ctx) 330 { 331 struct raid_bdev_write_sb_ctx *ctx = _ctx; 332 struct raid_bdev *raid_bdev = ctx->raid_bdev; 333 struct raid_base_bdev_info *base_info; 334 uint8_t i; 335 int rc; 336 337 for (i = ctx->submitted; i < raid_bdev->num_base_bdevs; i++) { 338 base_info = &raid_bdev->base_bdev_info[i]; 339 340 if (base_info->desc == NULL) { 341 assert(ctx->remaining > 1); 342 raid_bdev_write_sb_base_bdev_done(0, ctx); 343 ctx->submitted++; 344 continue; 345 } 346 347 rc = spdk_bdev_write(base_info->desc, base_info->app_thread_ch, 348 raid_bdev->sb_io_buf, 0, raid_bdev->sb_io_buf_size, 349 raid_bdev_write_superblock_cb, ctx); 350 if (rc != 0) { 351 struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(base_info->desc); 352 353 if (rc == -ENOMEM) { 354 ctx->wait_entry.bdev = bdev; 355 ctx->wait_entry.cb_fn = _raid_bdev_write_superblock; 356 ctx->wait_entry.cb_arg = ctx; 357 spdk_bdev_queue_io_wait(bdev, base_info->app_thread_ch, &ctx->wait_entry); 358 return; 359 } 360 361 assert(ctx->remaining > 1); 362 raid_bdev_write_sb_base_bdev_done(rc, ctx); 363 } 364 365 ctx->submitted++; 366 } 367 368 raid_bdev_write_sb_base_bdev_done(0, ctx); 369 } 370 371 void 372 raid_bdev_write_superblock(struct raid_bdev *raid_bdev, raid_bdev_write_sb_cb cb, void *cb_ctx) 373 { 374 struct raid_bdev_write_sb_ctx *ctx; 375 struct raid_bdev_superblock *sb = raid_bdev->sb; 376 int rc; 377 378 assert(spdk_get_thread() == spdk_thread_get_app_thread()); 379 assert(sb != NULL); 380 assert(cb != NULL); 381 382 if (raid_bdev->sb_io_buf == NULL) { 383 rc = raid_bdev_alloc_sb_io_buf(raid_bdev); 384 if (rc != 0) { 385 goto err; 386 } 387 } 388 389 ctx = calloc(1, sizeof(*ctx)); 390 if (!ctx) { 391 rc = -ENOMEM; 392 goto err; 393 } 394 395 ctx->raid_bdev = raid_bdev; 396 ctx->remaining = raid_bdev->num_base_bdevs + 1; 397 ctx->cb = cb; 398 ctx->cb_ctx = cb_ctx; 399 400 sb->seq_number++; 401 raid_bdev_sb_update_crc(sb); 402 403 if (spdk_bdev_is_md_interleaved(&raid_bdev->bdev)) { 404 void *sb_buf = sb; 405 uint32_t i; 406 407 for (i = 0; i < raid_bdev->sb_io_buf_size / raid_bdev->bdev.blocklen; i++) { 408 memcpy(raid_bdev->sb_io_buf + (i * raid_bdev->bdev.blocklen), 409 sb_buf + (i * sb->block_size), sb->block_size); 410 } 411 } 412 413 _raid_bdev_write_superblock(ctx); 414 return; 415 err: 416 cb(rc, raid_bdev, cb_ctx); 417 } 418 419 SPDK_LOG_REGISTER_COMPONENT(bdev_raid_sb) 420