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