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 void 42 raid_bdev_init_superblock(struct raid_bdev *raid_bdev) 43 { 44 struct raid_bdev_superblock *sb = raid_bdev->sb; 45 struct raid_base_bdev_info *base_info; 46 struct raid_bdev_sb_base_bdev *sb_base_bdev; 47 48 memset(sb, 0, RAID_BDEV_SB_MAX_LENGTH); 49 50 memcpy(&sb->signature, RAID_BDEV_SB_SIG, sizeof(sb->signature)); 51 sb->version.major = RAID_BDEV_SB_VERSION_MAJOR; 52 sb->version.minor = RAID_BDEV_SB_VERSION_MINOR; 53 spdk_uuid_copy(&sb->uuid, &raid_bdev->bdev.uuid); 54 snprintf(sb->name, RAID_BDEV_SB_NAME_SIZE, "%s", raid_bdev->bdev.name); 55 sb->raid_size = raid_bdev->bdev.blockcnt; 56 sb->block_size = raid_bdev->bdev.blocklen; 57 sb->level = raid_bdev->level; 58 sb->strip_size = raid_bdev->strip_size; 59 /* TODO: sb->state */ 60 sb->num_base_bdevs = sb->base_bdevs_size = raid_bdev->num_base_bdevs; 61 sb->length = sizeof(*sb) + sizeof(*sb_base_bdev) * sb->base_bdevs_size; 62 63 sb_base_bdev = &sb->base_bdevs[0]; 64 RAID_FOR_EACH_BASE_BDEV(raid_bdev, base_info) { 65 spdk_uuid_copy(&sb_base_bdev->uuid, &base_info->uuid); 66 sb_base_bdev->data_offset = base_info->data_offset; 67 sb_base_bdev->data_size = base_info->data_size; 68 sb_base_bdev->state = RAID_SB_BASE_BDEV_CONFIGURED; 69 sb_base_bdev->slot = raid_bdev_base_bdev_slot(base_info); 70 sb_base_bdev++; 71 } 72 } 73 74 static void 75 raid_bdev_sb_update_crc(struct raid_bdev_superblock *sb) 76 { 77 sb->crc = 0; 78 sb->crc = spdk_crc32c_update(sb, sb->length, 0); 79 } 80 81 static bool 82 raid_bdev_sb_check_crc(struct raid_bdev_superblock *sb) 83 { 84 uint32_t crc, prev = sb->crc; 85 86 raid_bdev_sb_update_crc(sb); 87 crc = sb->crc; 88 sb->crc = prev; 89 90 return crc == prev; 91 } 92 93 static int 94 raid_bdev_parse_superblock(struct raid_bdev_read_sb_ctx *ctx) 95 { 96 struct raid_bdev_superblock *sb = ctx->buf; 97 struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(ctx->desc); 98 99 if (memcmp(sb->signature, RAID_BDEV_SB_SIG, sizeof(sb->signature))) { 100 SPDK_DEBUGLOG(bdev_raid_sb, "invalid signature\n"); 101 return -EINVAL; 102 } 103 104 if (sb->length > ctx->buf_size) { 105 if (sb->length > RAID_BDEV_SB_MAX_LENGTH) { 106 SPDK_WARNLOG("Incorrect superblock length on bdev %s\n", 107 spdk_bdev_get_name(bdev)); 108 return -EINVAL; 109 } 110 111 return -EAGAIN; 112 } 113 114 if (!raid_bdev_sb_check_crc(sb)) { 115 SPDK_WARNLOG("Incorrect superblock crc on bdev %s\n", spdk_bdev_get_name(bdev)); 116 return -EINVAL; 117 } 118 119 if (sb->version.major != RAID_BDEV_SB_VERSION_MAJOR) { 120 SPDK_ERRLOG("Not supported superblock major version %d on bdev %s\n", 121 sb->version.major, spdk_bdev_get_name(bdev)); 122 return -EINVAL; 123 } 124 125 if (sb->version.minor > RAID_BDEV_SB_VERSION_MINOR) { 126 SPDK_WARNLOG("Superblock minor version %d on bdev %s is higher than the currently supported: %d\n", 127 sb->version.minor, spdk_bdev_get_name(bdev), RAID_BDEV_SB_VERSION_MINOR); 128 } 129 130 return 0; 131 } 132 133 static void 134 raid_bdev_read_sb_ctx_free(struct raid_bdev_read_sb_ctx *ctx) 135 { 136 spdk_dma_free(ctx->buf); 137 138 free(ctx); 139 } 140 141 static void raid_bdev_read_sb_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg); 142 143 static int 144 raid_bdev_read_sb_remainder(struct raid_bdev_read_sb_ctx *ctx) 145 { 146 struct raid_bdev_superblock *sb = ctx->buf; 147 struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(ctx->desc); 148 uint32_t buf_size_prev; 149 void *buf; 150 int rc; 151 152 buf_size_prev = ctx->buf_size; 153 ctx->buf_size = align_ceil(sb->length, spdk_bdev_get_block_size(bdev)); 154 buf = spdk_dma_realloc(ctx->buf, ctx->buf_size, spdk_bdev_get_buf_align(bdev), NULL); 155 if (buf == NULL) { 156 SPDK_ERRLOG("Failed to reallocate buffer\n"); 157 return -ENOMEM; 158 } 159 ctx->buf = buf; 160 161 rc = spdk_bdev_read(ctx->desc, ctx->ch, ctx->buf + buf_size_prev, buf_size_prev, 162 ctx->buf_size - buf_size_prev, raid_bdev_read_sb_cb, ctx); 163 if (rc != 0) { 164 SPDK_ERRLOG("Failed to read bdev %s superblock remainder: %s\n", 165 spdk_bdev_get_name(bdev), spdk_strerror(-rc)); 166 return rc; 167 } 168 169 return 0; 170 } 171 172 static void 173 raid_bdev_read_sb_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) 174 { 175 struct raid_bdev_read_sb_ctx *ctx = cb_arg; 176 struct raid_bdev_superblock *sb = NULL; 177 int status; 178 179 spdk_bdev_free_io(bdev_io); 180 181 if (!success) { 182 status = -EIO; 183 goto out; 184 } 185 186 status = raid_bdev_parse_superblock(ctx); 187 if (status == -EAGAIN) { 188 status = raid_bdev_read_sb_remainder(ctx); 189 if (status == 0) { 190 return; 191 } 192 } else if (status != 0) { 193 SPDK_DEBUGLOG(bdev_raid_sb, "failed to parse bdev %s superblock\n", 194 spdk_bdev_get_name(spdk_bdev_desc_get_bdev(ctx->desc))); 195 } else { 196 sb = ctx->buf; 197 } 198 out: 199 ctx->cb(sb, status, ctx->cb_ctx); 200 201 raid_bdev_read_sb_ctx_free(ctx); 202 } 203 204 int 205 raid_bdev_load_base_bdev_superblock(struct spdk_bdev_desc *desc, struct spdk_io_channel *ch, 206 raid_bdev_load_sb_cb cb, void *cb_ctx) 207 { 208 struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(desc); 209 struct raid_bdev_read_sb_ctx *ctx; 210 int rc; 211 212 assert(cb != NULL); 213 214 ctx = calloc(1, sizeof(*ctx)); 215 if (!ctx) { 216 return -ENOMEM; 217 } 218 219 ctx->desc = desc; 220 ctx->ch = ch; 221 ctx->cb = cb; 222 ctx->cb_ctx = cb_ctx; 223 ctx->buf_size = align_ceil(sizeof(struct raid_bdev_superblock), spdk_bdev_get_block_size(bdev)); 224 ctx->buf = spdk_dma_malloc(ctx->buf_size, spdk_bdev_get_buf_align(bdev), NULL); 225 if (!ctx->buf) { 226 rc = -ENOMEM; 227 goto err; 228 } 229 230 rc = spdk_bdev_read(desc, ch, ctx->buf, 0, ctx->buf_size, raid_bdev_read_sb_cb, ctx); 231 if (rc) { 232 goto err; 233 } 234 235 return 0; 236 err: 237 raid_bdev_read_sb_ctx_free(ctx); 238 239 return rc; 240 } 241 242 static void 243 raid_bdev_write_sb_base_bdev_done(int status, struct raid_bdev_write_sb_ctx *ctx) 244 { 245 if (status != 0) { 246 ctx->status = status; 247 } 248 249 if (--ctx->remaining == 0) { 250 ctx->cb(ctx->status, ctx->raid_bdev, ctx->cb_ctx); 251 free(ctx); 252 } 253 } 254 255 static void 256 raid_bdev_write_superblock_cb(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) 257 { 258 struct raid_bdev_write_sb_ctx *ctx = cb_arg; 259 int status = 0; 260 261 if (!success) { 262 SPDK_ERRLOG("Failed to save superblock on bdev %s\n", bdev_io->bdev->name); 263 status = -EIO; 264 } 265 266 spdk_bdev_free_io(bdev_io); 267 268 raid_bdev_write_sb_base_bdev_done(status, ctx); 269 } 270 271 static void 272 _raid_bdev_write_superblock(void *_ctx) 273 { 274 struct raid_bdev_write_sb_ctx *ctx = _ctx; 275 struct raid_bdev *raid_bdev = ctx->raid_bdev; 276 struct raid_base_bdev_info *base_info; 277 uint8_t i; 278 int rc; 279 280 for (i = ctx->submitted; i < raid_bdev->num_base_bdevs; i++) { 281 base_info = &raid_bdev->base_bdev_info[i]; 282 283 if (base_info->desc == NULL) { 284 assert(ctx->remaining > 1); 285 raid_bdev_write_sb_base_bdev_done(0, ctx); 286 ctx->submitted++; 287 continue; 288 } 289 290 rc = spdk_bdev_write(base_info->desc, base_info->app_thread_ch, 291 (void *)raid_bdev->sb, 0, ctx->nbytes, 292 raid_bdev_write_superblock_cb, ctx); 293 if (rc != 0) { 294 struct spdk_bdev *bdev = spdk_bdev_desc_get_bdev(base_info->desc); 295 296 if (rc == -ENOMEM) { 297 ctx->wait_entry.bdev = bdev; 298 ctx->wait_entry.cb_fn = _raid_bdev_write_superblock; 299 ctx->wait_entry.cb_arg = ctx; 300 spdk_bdev_queue_io_wait(bdev, base_info->app_thread_ch, &ctx->wait_entry); 301 return; 302 } 303 304 assert(ctx->remaining > 1); 305 raid_bdev_write_sb_base_bdev_done(rc, ctx); 306 } 307 308 ctx->submitted++; 309 } 310 311 raid_bdev_write_sb_base_bdev_done(0, ctx); 312 } 313 314 void 315 raid_bdev_write_superblock(struct raid_bdev *raid_bdev, raid_bdev_write_sb_cb cb, void *cb_ctx) 316 { 317 struct raid_bdev_write_sb_ctx *ctx; 318 struct raid_bdev_superblock *sb = raid_bdev->sb; 319 320 assert(spdk_get_thread() == spdk_thread_get_app_thread()); 321 assert(sb != NULL); 322 assert(cb != NULL); 323 324 ctx = calloc(1, sizeof(*ctx)); 325 if (!ctx) { 326 cb(-ENOMEM, raid_bdev, cb_ctx); 327 return; 328 } 329 330 ctx->raid_bdev = raid_bdev; 331 ctx->nbytes = align_ceil(sb->length, spdk_bdev_get_block_size(&raid_bdev->bdev)); 332 ctx->remaining = raid_bdev->num_base_bdevs + 1; 333 ctx->cb = cb; 334 ctx->cb_ctx = cb_ctx; 335 336 sb->seq_number++; 337 raid_bdev_sb_update_crc(sb); 338 339 _raid_bdev_write_superblock(ctx); 340 } 341 342 SPDK_LOG_REGISTER_COMPONENT(bdev_raid_sb) 343