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 uint64_t nbytes; 19 uint8_t submitted; 20 uint8_t remaining; 21 raid_bdev_write_sb_cb cb; 22 void *cb_ctx; 23 struct spdk_bdev_io_wait_entry wait_entry; 24 }; 25 26 struct raid_bdev_read_sb_ctx { 27 struct spdk_bdev_desc *desc; 28 struct spdk_io_channel *ch; 29 raid_bdev_load_sb_cb cb; 30 void *cb_ctx; 31 void *buf; 32 uint32_t buf_size; 33 }; 34 35 static inline uint64_t 36 align_ceil(uint64_t val, uint64_t align) 37 { 38 return spdk_divide_round_up(val, align) * align; 39 } 40 41 int 42 raid_bdev_alloc_superblock(struct raid_bdev *raid_bdev, uint32_t block_size) 43 { 44 struct raid_bdev_superblock *sb; 45 46 sb = spdk_dma_zmalloc(SPDK_ALIGN_CEIL(RAID_BDEV_SB_MAX_LENGTH, block_size), 0x1000, NULL); 47 if (!sb) { 48 SPDK_ERRLOG("Failed to allocate raid bdev sb buffer\n"); 49 return -ENOMEM; 50 } 51 52 raid_bdev->sb = sb; 53 54 return 0; 55 } 56 57 void 58 raid_bdev_free_superblock(struct raid_bdev *raid_bdev) 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 = raid_bdev->bdev.blocklen; 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 void 96 raid_bdev_sb_update_crc(struct raid_bdev_superblock *sb) 97 { 98 sb->crc = 0; 99 sb->crc = spdk_crc32c_update(sb, sb->length, 0); 100 } 101 102 static bool 103 raid_bdev_sb_check_crc(struct raid_bdev_superblock *sb) 104 { 105 uint32_t crc, prev = sb->crc; 106 107 raid_bdev_sb_update_crc(sb); 108 crc = sb->crc; 109 sb->crc = prev; 110 111 return crc == prev; 112 } 113 114 static int 115 raid_bdev_parse_superblock(struct raid_bdev_read_sb_ctx *ctx) 116 { 117 struct raid_bdev_superblock *sb = ctx->buf; 118 struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(ctx->desc); 119 120 if (memcmp(sb->signature, RAID_BDEV_SB_SIG, sizeof(sb->signature))) { 121 SPDK_DEBUGLOG(bdev_raid_sb, "invalid signature\n"); 122 return -EINVAL; 123 } 124 125 if (sb->length > ctx->buf_size) { 126 if (sb->length > RAID_BDEV_SB_MAX_LENGTH) { 127 SPDK_WARNLOG("Incorrect superblock length on bdev %s\n", 128 spdk_bdev_get_name(bdev)); 129 return -EINVAL; 130 } 131 132 return -EAGAIN; 133 } 134 135 if (!raid_bdev_sb_check_crc(sb)) { 136 SPDK_WARNLOG("Incorrect superblock crc on bdev %s\n", spdk_bdev_get_name(bdev)); 137 return -EINVAL; 138 } 139 140 if (sb->version.major != RAID_BDEV_SB_VERSION_MAJOR) { 141 SPDK_ERRLOG("Not supported superblock major version %d on bdev %s\n", 142 sb->version.major, spdk_bdev_get_name(bdev)); 143 return -EINVAL; 144 } 145 146 if (sb->version.minor > RAID_BDEV_SB_VERSION_MINOR) { 147 SPDK_WARNLOG("Superblock minor version %d on bdev %s is higher than the currently supported: %d\n", 148 sb->version.minor, spdk_bdev_get_name(bdev), RAID_BDEV_SB_VERSION_MINOR); 149 } 150 151 return 0; 152 } 153 154 static void 155 raid_bdev_read_sb_ctx_free(struct raid_bdev_read_sb_ctx *ctx) 156 { 157 spdk_dma_free(ctx->buf); 158 159 free(ctx); 160 } 161 162 static void raid_bdev_read_sb_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg); 163 164 static int 165 raid_bdev_read_sb_remainder(struct raid_bdev_read_sb_ctx *ctx) 166 { 167 struct raid_bdev_superblock *sb = ctx->buf; 168 struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(ctx->desc); 169 uint32_t buf_size_prev; 170 void *buf; 171 int rc; 172 173 buf_size_prev = ctx->buf_size; 174 ctx->buf_size = align_ceil(sb->length, spdk_bdev_get_block_size(bdev)); 175 buf = spdk_dma_realloc(ctx->buf, ctx->buf_size, spdk_bdev_get_buf_align(bdev), NULL); 176 if (buf == NULL) { 177 SPDK_ERRLOG("Failed to reallocate buffer\n"); 178 return -ENOMEM; 179 } 180 ctx->buf = buf; 181 182 rc = spdk_bdev_read(ctx->desc, ctx->ch, ctx->buf + buf_size_prev, buf_size_prev, 183 ctx->buf_size - buf_size_prev, raid_bdev_read_sb_cb, ctx); 184 if (rc != 0) { 185 SPDK_ERRLOG("Failed to read bdev %s superblock remainder: %s\n", 186 spdk_bdev_get_name(bdev), spdk_strerror(-rc)); 187 return rc; 188 } 189 190 return 0; 191 } 192 193 static void 194 raid_bdev_read_sb_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) 195 { 196 struct raid_bdev_read_sb_ctx *ctx = cb_arg; 197 struct raid_bdev_superblock *sb = NULL; 198 int status; 199 200 spdk_bdev_free_io(bdev_io); 201 202 if (!success) { 203 status = -EIO; 204 goto out; 205 } 206 207 status = raid_bdev_parse_superblock(ctx); 208 if (status == -EAGAIN) { 209 status = raid_bdev_read_sb_remainder(ctx); 210 if (status == 0) { 211 return; 212 } 213 } else if (status != 0) { 214 SPDK_DEBUGLOG(bdev_raid_sb, "failed to parse bdev %s superblock\n", 215 spdk_bdev_get_name(spdk_bdev_desc_get_bdev(ctx->desc))); 216 } else { 217 sb = ctx->buf; 218 } 219 out: 220 ctx->cb(sb, status, ctx->cb_ctx); 221 222 raid_bdev_read_sb_ctx_free(ctx); 223 } 224 225 int 226 raid_bdev_load_base_bdev_superblock(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, 227 raid_bdev_load_sb_cb cb, void *cb_ctx) 228 { 229 struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(desc); 230 struct raid_bdev_read_sb_ctx *ctx; 231 int rc; 232 233 assert(cb != NULL); 234 235 ctx = calloc(1, sizeof(*ctx)); 236 if (!ctx) { 237 return -ENOMEM; 238 } 239 240 ctx->desc = desc; 241 ctx->ch = ch; 242 ctx->cb = cb; 243 ctx->cb_ctx = cb_ctx; 244 ctx->buf_size = align_ceil(sizeof(struct raid_bdev_superblock), spdk_bdev_get_block_size(bdev)); 245 ctx->buf = spdk_dma_malloc(ctx->buf_size, spdk_bdev_get_buf_align(bdev), NULL); 246 if (!ctx->buf) { 247 rc = -ENOMEM; 248 goto err; 249 } 250 251 rc = spdk_bdev_read(desc, ch, ctx->buf, 0, ctx->buf_size, raid_bdev_read_sb_cb, ctx); 252 if (rc) { 253 goto err; 254 } 255 256 return 0; 257 err: 258 raid_bdev_read_sb_ctx_free(ctx); 259 260 return rc; 261 } 262 263 static void 264 raid_bdev_write_sb_base_bdev_done(int status, struct raid_bdev_write_sb_ctx *ctx) 265 { 266 if (status != 0) { 267 ctx->status = status; 268 } 269 270 if (--ctx->remaining == 0) { 271 ctx->cb(ctx->status, ctx->raid_bdev, ctx->cb_ctx); 272 free(ctx); 273 } 274 } 275 276 static void 277 raid_bdev_write_superblock_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) 278 { 279 struct raid_bdev_write_sb_ctx *ctx = cb_arg; 280 int status = 0; 281 282 if (!success) { 283 SPDK_ERRLOG("Failed to save superblock on bdev %s\n", bdev_io->bdev->name); 284 status = -EIO; 285 } 286 287 spdk_bdev_free_io(bdev_io); 288 289 raid_bdev_write_sb_base_bdev_done(status, ctx); 290 } 291 292 static void 293 _raid_bdev_write_superblock(void *_ctx) 294 { 295 struct raid_bdev_write_sb_ctx *ctx = _ctx; 296 struct raid_bdev *raid_bdev = ctx->raid_bdev; 297 struct raid_base_bdev_info *base_info; 298 uint8_t i; 299 int rc; 300 301 for (i = ctx->submitted; i < raid_bdev->num_base_bdevs; i++) { 302 base_info = &raid_bdev->base_bdev_info[i]; 303 304 if (base_info->desc == NULL) { 305 assert(ctx->remaining > 1); 306 raid_bdev_write_sb_base_bdev_done(0, ctx); 307 ctx->submitted++; 308 continue; 309 } 310 311 rc = spdk_bdev_write(base_info->desc, base_info->app_thread_ch, 312 (void *)raid_bdev->sb, 0, ctx->nbytes, 313 raid_bdev_write_superblock_cb, ctx); 314 if (rc != 0) { 315 struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(base_info->desc); 316 317 if (rc == -ENOMEM) { 318 ctx->wait_entry.bdev = bdev; 319 ctx->wait_entry.cb_fn = _raid_bdev_write_superblock; 320 ctx->wait_entry.cb_arg = ctx; 321 spdk_bdev_queue_io_wait(bdev, base_info->app_thread_ch, &ctx->wait_entry); 322 return; 323 } 324 325 assert(ctx->remaining > 1); 326 raid_bdev_write_sb_base_bdev_done(rc, ctx); 327 } 328 329 ctx->submitted++; 330 } 331 332 raid_bdev_write_sb_base_bdev_done(0, ctx); 333 } 334 335 void 336 raid_bdev_write_superblock(struct raid_bdev *raid_bdev, raid_bdev_write_sb_cb cb, void *cb_ctx) 337 { 338 struct raid_bdev_write_sb_ctx *ctx; 339 struct raid_bdev_superblock *sb = raid_bdev->sb; 340 341 assert(spdk_get_thread() == spdk_thread_get_app_thread()); 342 assert(sb != NULL); 343 assert(cb != NULL); 344 345 ctx = calloc(1, sizeof(*ctx)); 346 if (!ctx) { 347 cb(-ENOMEM, raid_bdev, cb_ctx); 348 return; 349 } 350 351 ctx->raid_bdev = raid_bdev; 352 ctx->nbytes = align_ceil(sb->length, spdk_bdev_get_block_size(&raid_bdev->bdev)); 353 ctx->remaining = raid_bdev->num_base_bdevs + 1; 354 ctx->cb = cb; 355 ctx->cb_ctx = cb_ctx; 356 357 sb->seq_number++; 358 raid_bdev_sb_update_crc(sb); 359 360 _raid_bdev_write_superblock(ctx); 361 } 362 363 SPDK_LOG_REGISTER_COMPONENT(bdev_raid_sb) 364