1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2017 Intel Corporation. 3 * All rights reserved. 4 */ 5 6 /* 7 * This is a module for test purpose which will simulate error cases for bdev. 8 */ 9 10 #include "spdk/stdinc.h" 11 #include "spdk/rpc.h" 12 #include "spdk/util.h" 13 #include "spdk/endian.h" 14 #include "spdk/nvme_spec.h" 15 #include "spdk/string.h" 16 17 #include "spdk/bdev_module.h" 18 #include "spdk/log.h" 19 20 #include "vbdev_error.h" 21 22 struct spdk_vbdev_error_config { 23 char *base_bdev; 24 struct spdk_uuid uuid; 25 TAILQ_ENTRY(spdk_vbdev_error_config) tailq; 26 }; 27 28 static TAILQ_HEAD(, spdk_vbdev_error_config) g_error_config 29 = TAILQ_HEAD_INITIALIZER(g_error_config); 30 31 struct vbdev_error_info { 32 uint32_t error_type; 33 uint32_t error_num; 34 uint64_t error_qd; 35 uint64_t corrupt_offset; 36 uint8_t corrupt_value; 37 }; 38 39 struct error_io { 40 enum vbdev_error_type error_type; 41 TAILQ_ENTRY(error_io) link; 42 }; 43 44 /* Context for each error bdev */ 45 struct error_disk { 46 struct spdk_bdev_part part; 47 struct vbdev_error_info error_vector[SPDK_BDEV_IO_TYPE_RESET]; 48 }; 49 50 struct error_channel { 51 struct spdk_bdev_part_channel part_ch; 52 uint64_t io_inflight; 53 TAILQ_HEAD(, error_io) pending_ios; 54 }; 55 56 static pthread_mutex_t g_vbdev_error_mutex = PTHREAD_MUTEX_INITIALIZER; 57 static SPDK_BDEV_PART_TAILQ g_error_disks = TAILQ_HEAD_INITIALIZER(g_error_disks); 58 59 static int vbdev_error_init(void); 60 static void vbdev_error_fini(void); 61 62 static void vbdev_error_examine(struct spdk_bdev *bdev); 63 static int vbdev_error_config_json(struct spdk_json_write_ctx *w); 64 65 static int vbdev_error_config_add(const char *base_bdev_name, const struct spdk_uuid *uuid); 66 static int vbdev_error_config_remove(const char *base_bdev_name); 67 68 static int 69 vbdev_error_get_ctx_size(void) 70 { 71 return sizeof(struct error_io); 72 } 73 74 static struct spdk_bdev_module error_if = { 75 .name = "error", 76 .module_init = vbdev_error_init, 77 .module_fini = vbdev_error_fini, 78 .examine_config = vbdev_error_examine, 79 .config_json = vbdev_error_config_json, 80 .get_ctx_size = vbdev_error_get_ctx_size, 81 82 }; 83 84 SPDK_BDEV_MODULE_REGISTER(error, &error_if) 85 86 static void 87 dummy_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *ctx) 88 { 89 } 90 91 int 92 vbdev_error_inject_error(char *name, const struct vbdev_error_inject_opts *opts) 93 { 94 struct spdk_bdev_desc *desc; 95 struct spdk_bdev *bdev; 96 struct spdk_bdev_part *part; 97 struct error_disk *error_disk = NULL; 98 uint32_t i; 99 int rc = 0; 100 101 if (opts->error_type == VBDEV_IO_CORRUPT_DATA) { 102 if (opts->corrupt_value == 0) { 103 /* If corrupt_value is 0, XOR cannot cause data corruption. */ 104 SPDK_ERRLOG("corrupt_value should be non-zero.\n"); 105 return -EINVAL; 106 } 107 } 108 109 pthread_mutex_lock(&g_vbdev_error_mutex); 110 111 rc = spdk_bdev_open_ext(name, false, dummy_bdev_event_cb, NULL, &desc); 112 if (rc != 0) { 113 SPDK_ERRLOG("Could not open ErrorInjection bdev %s\n", name); 114 pthread_mutex_unlock(&g_vbdev_error_mutex); 115 return rc; 116 } 117 118 bdev = spdk_bdev_desc_get_bdev(desc); 119 120 TAILQ_FOREACH(part, &g_error_disks, tailq) { 121 if (bdev == spdk_bdev_part_get_bdev(part)) { 122 error_disk = (struct error_disk *)part; 123 break; 124 } 125 } 126 127 if (error_disk == NULL) { 128 SPDK_ERRLOG("Could not find ErrorInjection bdev %s\n", name); 129 rc = -ENODEV; 130 goto exit; 131 } 132 133 if (0xffffffff == opts->io_type) { 134 for (i = 0; i < SPDK_COUNTOF(error_disk->error_vector); i++) { 135 error_disk->error_vector[i].error_type = opts->error_type; 136 error_disk->error_vector[i].error_num = opts->error_num; 137 error_disk->error_vector[i].error_qd = opts->error_qd; 138 error_disk->error_vector[i].corrupt_offset = opts->corrupt_offset; 139 error_disk->error_vector[i].corrupt_value = opts->corrupt_value; 140 } 141 } else if (0 == opts->io_type) { 142 for (i = 0; i < SPDK_COUNTOF(error_disk->error_vector); i++) { 143 error_disk->error_vector[i].error_num = 0; 144 } 145 } else { 146 error_disk->error_vector[opts->io_type].error_type = opts->error_type; 147 error_disk->error_vector[opts->io_type].error_num = opts->error_num; 148 error_disk->error_vector[opts->io_type].error_qd = opts->error_qd; 149 error_disk->error_vector[opts->io_type].corrupt_offset = opts->corrupt_offset; 150 error_disk->error_vector[opts->io_type].corrupt_value = opts->corrupt_value; 151 } 152 153 exit: 154 spdk_bdev_close(desc); 155 pthread_mutex_unlock(&g_vbdev_error_mutex); 156 return rc; 157 } 158 159 static void 160 vbdev_error_ch_abort_ios(struct spdk_io_channel_iter *i) 161 { 162 struct error_channel *ch = spdk_io_channel_get_ctx(spdk_io_channel_iter_get_channel(i)); 163 struct error_io *error_io, *tmp; 164 165 TAILQ_FOREACH_SAFE(error_io, &ch->pending_ios, link, tmp) { 166 TAILQ_REMOVE(&ch->pending_ios, error_io, link); 167 spdk_bdev_io_complete(spdk_bdev_io_from_ctx(error_io), SPDK_BDEV_IO_STATUS_ABORTED); 168 } 169 170 spdk_for_each_channel_continue(i, 0); 171 } 172 173 static void 174 vbdev_error_ch_abort_ios_done(struct spdk_io_channel_iter *i, int status) 175 { 176 struct spdk_bdev_io *reset_io = spdk_io_channel_iter_get_ctx(i); 177 178 if (status != 0) { 179 SPDK_ERRLOG("Failed to abort pending I/Os on bdev %s, status = %d\n", 180 reset_io->bdev->name, status); 181 spdk_bdev_io_complete(reset_io, SPDK_BDEV_IO_STATUS_FAILED); 182 } else { 183 spdk_bdev_io_complete(reset_io, SPDK_BDEV_IO_STATUS_SUCCESS); 184 } 185 } 186 187 static void 188 vbdev_error_reset(struct error_disk *error_disk, struct spdk_bdev_io *bdev_io) 189 { 190 spdk_for_each_channel(&error_disk->part, vbdev_error_ch_abort_ios, bdev_io, 191 vbdev_error_ch_abort_ios_done); 192 } 193 194 static uint32_t 195 vbdev_error_get_error_type(struct error_disk *error_disk, struct error_channel *ch, 196 uint32_t io_type) 197 { 198 uint32_t error_num; 199 struct vbdev_error_info *error_info; 200 201 switch (io_type) { 202 case SPDK_BDEV_IO_TYPE_READ: 203 case SPDK_BDEV_IO_TYPE_WRITE: 204 case SPDK_BDEV_IO_TYPE_UNMAP: 205 case SPDK_BDEV_IO_TYPE_FLUSH: 206 break; 207 default: 208 return VBDEV_IO_NO_ERROR; 209 } 210 211 error_info = &error_disk->error_vector[io_type]; 212 213 if (ch->io_inflight < error_info->error_qd) { 214 return VBDEV_IO_NO_ERROR; 215 } 216 217 error_num = error_info->error_num; 218 do { 219 if (error_num == 0) { 220 return VBDEV_IO_NO_ERROR; 221 } 222 } while (!__atomic_compare_exchange_n(&error_info->error_num, 223 &error_num, error_num - 1, 224 false, __ATOMIC_RELAXED, __ATOMIC_RELAXED)); 225 226 return error_info->error_type; 227 } 228 229 static void 230 vbdev_error_corrupt_io_data(struct spdk_bdev_io *bdev_io, uint64_t corrupt_offset, 231 uint8_t corrupt_value) 232 { 233 uint8_t *buf; 234 int i; 235 236 if (bdev_io->u.bdev.iovs == NULL || bdev_io->u.bdev.iovs[0].iov_base == NULL) { 237 return; 238 } 239 240 for (i = 0; i < bdev_io->u.bdev.iovcnt; i++) { 241 if (bdev_io->u.bdev.iovs[i].iov_len > corrupt_offset) { 242 buf = (uint8_t *)bdev_io->u.bdev.iovs[i].iov_base; 243 244 buf[corrupt_offset] ^= corrupt_value; 245 break; 246 } 247 248 corrupt_offset -= bdev_io->u.bdev.iovs[i].iov_len; 249 } 250 } 251 252 static void 253 vbdev_error_complete_request(struct spdk_bdev_io *bdev_io, bool success, void *cb_arg) 254 { 255 struct error_io *error_io = (struct error_io *)bdev_io->driver_ctx; 256 int status = success ? SPDK_BDEV_IO_STATUS_SUCCESS : SPDK_BDEV_IO_STATUS_FAILED; 257 struct error_disk *error_disk = bdev_io->bdev->ctxt; 258 struct error_channel *ch = spdk_io_channel_get_ctx(spdk_bdev_io_get_io_channel(bdev_io)); 259 260 assert(ch->io_inflight > 0); 261 ch->io_inflight--; 262 263 if (success && bdev_io->type == SPDK_BDEV_IO_TYPE_READ) { 264 if (error_io->error_type == VBDEV_IO_CORRUPT_DATA) { 265 vbdev_error_corrupt_io_data(bdev_io, 266 error_disk->error_vector[bdev_io->type].corrupt_offset, 267 error_disk->error_vector[bdev_io->type].corrupt_value); 268 } 269 } 270 271 spdk_bdev_io_complete(bdev_io, status); 272 } 273 274 static void 275 vbdev_error_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io) 276 { 277 struct error_io *error_io = (struct error_io *)bdev_io->driver_ctx; 278 struct error_channel *ch = spdk_io_channel_get_ctx(_ch); 279 struct error_disk *error_disk = bdev_io->bdev->ctxt; 280 int rc; 281 282 if (bdev_io->type == SPDK_BDEV_IO_TYPE_RESET) { 283 vbdev_error_reset(error_disk, bdev_io); 284 return; 285 } 286 287 error_io->error_type = vbdev_error_get_error_type(error_disk, ch, bdev_io->type); 288 289 switch (error_io->error_type) { 290 case VBDEV_IO_FAILURE: 291 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 292 break; 293 case VBDEV_IO_NOMEM: 294 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_NOMEM); 295 break; 296 case VBDEV_IO_PENDING: 297 TAILQ_INSERT_TAIL(&ch->pending_ios, error_io, link); 298 break; 299 case VBDEV_IO_CORRUPT_DATA: 300 if (bdev_io->type == SPDK_BDEV_IO_TYPE_WRITE) { 301 vbdev_error_corrupt_io_data(bdev_io, 302 error_disk->error_vector[bdev_io->type].corrupt_offset, 303 error_disk->error_vector[bdev_io->type].corrupt_value); 304 } 305 /* fallthrough */ 306 case VBDEV_IO_NO_ERROR: 307 ch->io_inflight++; 308 rc = spdk_bdev_part_submit_request_ext(&ch->part_ch, bdev_io, 309 vbdev_error_complete_request); 310 311 if (rc) { 312 SPDK_ERRLOG("bdev_error: submit request failed, rc=%d\n", rc); 313 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 314 ch->io_inflight--; 315 } 316 break; 317 default: 318 assert(false); 319 break; 320 } 321 } 322 323 static int 324 vbdev_error_destruct(void *ctx) 325 { 326 struct error_disk *error_disk = ctx; 327 struct spdk_bdev *base_bdev = spdk_bdev_part_get_base_bdev(&error_disk->part); 328 int rc; 329 330 rc = vbdev_error_config_remove(base_bdev->name); 331 if (rc != 0) { 332 SPDK_ERRLOG("vbdev_error_config_remove() failed\n"); 333 } 334 335 return spdk_bdev_part_free(&error_disk->part); 336 } 337 338 static int 339 vbdev_error_dump_info_json(void *ctx, struct spdk_json_write_ctx *w) 340 { 341 struct error_disk *error_disk = ctx; 342 struct spdk_bdev *base_bdev = spdk_bdev_part_get_base_bdev(&error_disk->part); 343 344 spdk_json_write_named_object_begin(w, "error_disk"); 345 346 spdk_json_write_named_string(w, "base_bdev", base_bdev->name); 347 348 spdk_json_write_object_end(w); 349 350 return 0; 351 } 352 353 static void 354 vbdev_error_write_config_json(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w) 355 { 356 /* No config per bdev. */ 357 } 358 359 360 static struct spdk_bdev_fn_table vbdev_error_fn_table = { 361 .destruct = vbdev_error_destruct, 362 .submit_request = vbdev_error_submit_request, 363 .dump_info_json = vbdev_error_dump_info_json, 364 .write_config_json = vbdev_error_write_config_json 365 }; 366 367 static void 368 vbdev_error_base_bdev_hotremove_cb(void *_part_base) 369 { 370 struct spdk_bdev_part_base *part_base = _part_base; 371 372 spdk_bdev_part_base_hotremove(part_base, &g_error_disks); 373 } 374 375 static int 376 vbdev_error_ch_create_cb(void *io_device, void *ctx_buf) 377 { 378 struct error_channel *ch = ctx_buf; 379 380 ch->io_inflight = 0; 381 TAILQ_INIT(&ch->pending_ios); 382 383 return 0; 384 } 385 386 static void 387 vbdev_error_ch_destroy_cb(void *io_device, void *ctx_buf) 388 { 389 } 390 391 static int 392 _vbdev_error_create(const char *base_bdev_name, const struct spdk_uuid *uuid) 393 { 394 struct spdk_bdev_part_base *base = NULL; 395 struct error_disk *disk = NULL; 396 struct spdk_bdev *base_bdev, *bdev; 397 char *name; 398 int rc; 399 400 rc = spdk_bdev_part_base_construct_ext(base_bdev_name, 401 vbdev_error_base_bdev_hotremove_cb, 402 &error_if, &vbdev_error_fn_table, &g_error_disks, 403 NULL, NULL, sizeof(struct error_channel), 404 vbdev_error_ch_create_cb, vbdev_error_ch_destroy_cb, 405 &base); 406 if (rc != 0) { 407 if (rc != -ENODEV) { 408 SPDK_ERRLOG("could not construct part base for bdev %s\n", base_bdev_name); 409 } 410 return rc; 411 } 412 413 base_bdev = spdk_bdev_part_base_get_bdev(base); 414 415 disk = calloc(1, sizeof(*disk)); 416 if (!disk) { 417 SPDK_ERRLOG("Memory allocation failure\n"); 418 spdk_bdev_part_base_free(base); 419 return -ENOMEM; 420 } 421 422 name = spdk_sprintf_alloc("EE_%s", base_bdev_name); 423 if (!name) { 424 SPDK_ERRLOG("name allocation failure\n"); 425 spdk_bdev_part_base_free(base); 426 free(disk); 427 return -ENOMEM; 428 } 429 430 if (!spdk_uuid_is_null(uuid)) { 431 bdev = spdk_bdev_part_get_bdev(&disk->part); 432 spdk_uuid_copy(&bdev->uuid, uuid); 433 } 434 435 rc = spdk_bdev_part_construct(&disk->part, base, name, 0, base_bdev->blockcnt, 436 "Error Injection Disk"); 437 free(name); 438 if (rc) { 439 SPDK_ERRLOG("could not construct part for bdev %s\n", base_bdev_name); 440 /* spdk_bdev_part_construct will free name on failure */ 441 spdk_bdev_part_base_free(base); 442 free(disk); 443 return rc; 444 } 445 446 return 0; 447 } 448 449 int 450 vbdev_error_create(const char *base_bdev_name, const struct spdk_uuid *uuid) 451 { 452 int rc; 453 454 rc = vbdev_error_config_add(base_bdev_name, uuid); 455 if (rc != 0) { 456 SPDK_ERRLOG("Adding config for ErrorInjection bdev %s failed (rc=%d)\n", 457 base_bdev_name, rc); 458 return rc; 459 } 460 461 rc = _vbdev_error_create(base_bdev_name, uuid); 462 if (rc == -ENODEV) { 463 rc = 0; 464 } else if (rc != 0) { 465 vbdev_error_config_remove(base_bdev_name); 466 SPDK_ERRLOG("Could not create ErrorInjection bdev %s (rc=%d)\n", 467 base_bdev_name, rc); 468 } 469 470 return rc; 471 } 472 473 void 474 vbdev_error_delete(const char *error_vbdev_name, spdk_delete_error_complete cb_fn, void *cb_arg) 475 { 476 int rc; 477 478 rc = spdk_bdev_unregister_by_name(error_vbdev_name, &error_if, cb_fn, cb_arg); 479 if (rc != 0) { 480 cb_fn(cb_arg, rc); 481 } 482 } 483 484 static void 485 vbdev_error_clear_config(void) 486 { 487 struct spdk_vbdev_error_config *cfg; 488 489 while ((cfg = TAILQ_FIRST(&g_error_config))) { 490 TAILQ_REMOVE(&g_error_config, cfg, tailq); 491 free(cfg->base_bdev); 492 free(cfg); 493 } 494 } 495 496 static struct spdk_vbdev_error_config * 497 vbdev_error_config_find_by_base_name(const char *base_bdev_name) 498 { 499 struct spdk_vbdev_error_config *cfg; 500 501 TAILQ_FOREACH(cfg, &g_error_config, tailq) { 502 if (strcmp(cfg->base_bdev, base_bdev_name) == 0) { 503 return cfg; 504 } 505 } 506 507 return NULL; 508 } 509 510 static int 511 vbdev_error_config_add(const char *base_bdev_name, const struct spdk_uuid *uuid) 512 { 513 struct spdk_vbdev_error_config *cfg; 514 515 cfg = vbdev_error_config_find_by_base_name(base_bdev_name); 516 if (cfg) { 517 SPDK_ERRLOG("vbdev_error_config for bdev %s already exists\n", 518 base_bdev_name); 519 return -EEXIST; 520 } 521 522 cfg = calloc(1, sizeof(*cfg)); 523 if (!cfg) { 524 SPDK_ERRLOG("calloc() failed for vbdev_error_config\n"); 525 return -ENOMEM; 526 } 527 528 cfg->base_bdev = strdup(base_bdev_name); 529 if (!cfg->base_bdev) { 530 free(cfg); 531 SPDK_ERRLOG("strdup() failed for base_bdev_name\n"); 532 return -ENOMEM; 533 } 534 535 spdk_uuid_copy(&cfg->uuid, uuid); 536 TAILQ_INSERT_TAIL(&g_error_config, cfg, tailq); 537 538 return 0; 539 } 540 541 static int 542 vbdev_error_config_remove(const char *base_bdev_name) 543 { 544 struct spdk_vbdev_error_config *cfg; 545 546 cfg = vbdev_error_config_find_by_base_name(base_bdev_name); 547 if (!cfg) { 548 return -ENOENT; 549 } 550 551 TAILQ_REMOVE(&g_error_config, cfg, tailq); 552 free(cfg->base_bdev); 553 free(cfg); 554 return 0; 555 } 556 557 static int 558 vbdev_error_init(void) 559 { 560 return 0; 561 } 562 563 static void 564 vbdev_error_fini(void) 565 { 566 vbdev_error_clear_config(); 567 } 568 569 static void 570 vbdev_error_examine(struct spdk_bdev *bdev) 571 { 572 struct spdk_vbdev_error_config *cfg; 573 int rc; 574 575 cfg = vbdev_error_config_find_by_base_name(bdev->name); 576 if (cfg != NULL) { 577 rc = _vbdev_error_create(bdev->name, &cfg->uuid); 578 if (rc != 0) { 579 SPDK_ERRLOG("could not create error vbdev for bdev %s at examine\n", 580 bdev->name); 581 } 582 } 583 584 spdk_bdev_module_examine_done(&error_if); 585 } 586 587 static int 588 vbdev_error_config_json(struct spdk_json_write_ctx *w) 589 { 590 struct spdk_vbdev_error_config *cfg; 591 592 TAILQ_FOREACH(cfg, &g_error_config, tailq) { 593 spdk_json_write_object_begin(w); 594 595 spdk_json_write_named_string(w, "method", "bdev_error_create"); 596 spdk_json_write_named_object_begin(w, "params"); 597 spdk_json_write_named_string(w, "base_name", cfg->base_bdev); 598 if (!spdk_uuid_is_null(&cfg->uuid)) { 599 spdk_json_write_named_uuid(w, "uuid", &cfg->uuid); 600 } 601 spdk_json_write_object_end(w); 602 603 spdk_json_write_object_end(w); 604 } 605 606 return 0; 607 } 608