1 /*- 2 * BSD LICENSE 3 * 4 * Copyright (c) Intel Corporation. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * * Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * * Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * * Neither the name of Intel Corporation nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 25 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 /* 35 * This is a module for test purpose which will simulate error cases for bdev. 36 */ 37 38 #include "spdk/stdinc.h" 39 #include "spdk/rpc.h" 40 #include "spdk/util.h" 41 #include "spdk/endian.h" 42 #include "spdk/nvme_spec.h" 43 #include "spdk/string.h" 44 45 #include "spdk/bdev_module.h" 46 #include "spdk/log.h" 47 48 #include "vbdev_error.h" 49 50 struct spdk_vbdev_error_config { 51 char *base_bdev; 52 TAILQ_ENTRY(spdk_vbdev_error_config) tailq; 53 }; 54 55 static TAILQ_HEAD(, spdk_vbdev_error_config) g_error_config 56 = TAILQ_HEAD_INITIALIZER(g_error_config); 57 58 struct vbdev_error_info { 59 uint32_t error_type; 60 uint32_t error_num; 61 }; 62 63 /* Context for each error bdev */ 64 struct error_disk { 65 struct spdk_bdev_part part; 66 struct vbdev_error_info error_vector[SPDK_BDEV_IO_TYPE_RESET]; 67 TAILQ_HEAD(, spdk_bdev_io) pending_ios; 68 }; 69 70 struct error_channel { 71 struct spdk_bdev_part_channel part_ch; 72 }; 73 74 static pthread_mutex_t g_vbdev_error_mutex = PTHREAD_MUTEX_INITIALIZER; 75 static SPDK_BDEV_PART_TAILQ g_error_disks = TAILQ_HEAD_INITIALIZER(g_error_disks); 76 77 static int vbdev_error_init(void); 78 static void vbdev_error_fini(void); 79 80 static void vbdev_error_examine(struct spdk_bdev *bdev); 81 static int vbdev_error_config_json(struct spdk_json_write_ctx *w); 82 83 static int vbdev_error_config_add(const char *base_bdev_name); 84 static int vbdev_error_config_remove(const char *base_bdev_name); 85 86 static struct spdk_bdev_module error_if = { 87 .name = "error", 88 .module_init = vbdev_error_init, 89 .module_fini = vbdev_error_fini, 90 .examine_config = vbdev_error_examine, 91 .config_json = vbdev_error_config_json, 92 93 }; 94 95 SPDK_BDEV_MODULE_REGISTER(error, &error_if) 96 97 static void 98 dummy_bdev_event_cb(enum spdk_bdev_event_type type, struct spdk_bdev *bdev, void *ctx) 99 { 100 } 101 102 int 103 vbdev_error_inject_error(char *name, uint32_t io_type, uint32_t error_type, uint32_t error_num) 104 { 105 struct spdk_bdev_desc *desc; 106 struct spdk_bdev *bdev; 107 struct spdk_bdev_part *part; 108 struct error_disk *error_disk = NULL; 109 uint32_t i; 110 int rc = 0; 111 112 pthread_mutex_lock(&g_vbdev_error_mutex); 113 114 rc = spdk_bdev_open_ext(name, false, dummy_bdev_event_cb, NULL, &desc); 115 if (rc != 0) { 116 SPDK_ERRLOG("Could not open ErrorInjection bdev %s\n", name); 117 pthread_mutex_unlock(&g_vbdev_error_mutex); 118 return rc; 119 } 120 121 bdev = spdk_bdev_desc_get_bdev(desc); 122 123 TAILQ_FOREACH(part, &g_error_disks, tailq) { 124 if (bdev == spdk_bdev_part_get_bdev(part)) { 125 error_disk = (struct error_disk *)part; 126 break; 127 } 128 } 129 130 if (error_disk == NULL) { 131 SPDK_ERRLOG("Could not find ErrorInjection bdev %s\n", name); 132 rc = -ENODEV; 133 goto exit; 134 } 135 136 if (0xffffffff == io_type) { 137 for (i = 0; i < SPDK_COUNTOF(error_disk->error_vector); i++) { 138 error_disk->error_vector[i].error_type = error_type; 139 error_disk->error_vector[i].error_num = error_num; 140 } 141 } else if (0 == 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[io_type].error_type = error_type; 147 error_disk->error_vector[io_type].error_num = error_num; 148 } 149 150 exit: 151 spdk_bdev_close(desc); 152 pthread_mutex_unlock(&g_vbdev_error_mutex); 153 return rc; 154 } 155 156 static void 157 vbdev_error_reset(struct error_disk *error_disk, struct spdk_bdev_io *bdev_io) 158 { 159 struct spdk_bdev_io *pending_io, *tmp; 160 161 TAILQ_FOREACH_SAFE(pending_io, &error_disk->pending_ios, module_link, tmp) { 162 TAILQ_REMOVE(&error_disk->pending_ios, pending_io, module_link); 163 spdk_bdev_io_complete(pending_io, SPDK_BDEV_IO_STATUS_FAILED); 164 } 165 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_SUCCESS); 166 } 167 168 static uint32_t 169 vbdev_error_get_error_type(struct error_disk *error_disk, uint32_t io_type) 170 { 171 if (error_disk->error_vector[io_type].error_num) { 172 return error_disk->error_vector[io_type].error_type; 173 } 174 return 0; 175 } 176 177 static void 178 vbdev_error_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io) 179 { 180 struct error_channel *ch = spdk_io_channel_get_ctx(_ch); 181 struct error_disk *error_disk = bdev_io->bdev->ctxt; 182 uint32_t error_type; 183 184 switch (bdev_io->type) { 185 case SPDK_BDEV_IO_TYPE_READ: 186 case SPDK_BDEV_IO_TYPE_WRITE: 187 case SPDK_BDEV_IO_TYPE_UNMAP: 188 case SPDK_BDEV_IO_TYPE_FLUSH: 189 break; 190 case SPDK_BDEV_IO_TYPE_RESET: 191 vbdev_error_reset(error_disk, bdev_io); 192 return; 193 default: 194 SPDK_ERRLOG("Error Injection: unknown I/O type %d\n", bdev_io->type); 195 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 196 return; 197 } 198 199 error_type = vbdev_error_get_error_type(error_disk, bdev_io->type); 200 if (error_type == 0) { 201 int rc = spdk_bdev_part_submit_request(&ch->part_ch, bdev_io); 202 203 if (rc) { 204 SPDK_ERRLOG("bdev_error: submit request failed, rc=%d\n", rc); 205 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 206 } 207 return; 208 } else if (error_type == VBDEV_IO_FAILURE) { 209 error_disk->error_vector[bdev_io->type].error_num--; 210 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 211 } else if (error_type == VBDEV_IO_PENDING) { 212 TAILQ_INSERT_TAIL(&error_disk->pending_ios, bdev_io, module_link); 213 error_disk->error_vector[bdev_io->type].error_num--; 214 } 215 } 216 217 static int 218 vbdev_error_destruct(void *ctx) 219 { 220 struct error_disk *error_disk = ctx; 221 struct spdk_bdev *base_bdev = spdk_bdev_part_get_base_bdev(&error_disk->part); 222 int rc; 223 224 rc = vbdev_error_config_remove(base_bdev->name); 225 if (rc != 0) { 226 SPDK_ERRLOG("vbdev_error_config_remove() failed\n"); 227 } 228 229 return spdk_bdev_part_free(&error_disk->part); 230 } 231 232 static int 233 vbdev_error_dump_info_json(void *ctx, struct spdk_json_write_ctx *w) 234 { 235 struct error_disk *error_disk = ctx; 236 struct spdk_bdev *base_bdev = spdk_bdev_part_get_base_bdev(&error_disk->part); 237 238 spdk_json_write_named_object_begin(w, "error_disk"); 239 240 spdk_json_write_named_string(w, "base_bdev", base_bdev->name); 241 242 spdk_json_write_object_end(w); 243 244 return 0; 245 } 246 247 static void 248 vbdev_error_write_config_json(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w) 249 { 250 /* No config per bdev. */ 251 } 252 253 254 static struct spdk_bdev_fn_table vbdev_error_fn_table = { 255 .destruct = vbdev_error_destruct, 256 .submit_request = vbdev_error_submit_request, 257 .dump_info_json = vbdev_error_dump_info_json, 258 .write_config_json = vbdev_error_write_config_json 259 }; 260 261 static void 262 vbdev_error_base_bdev_hotremove_cb(void *_part_base) 263 { 264 struct spdk_bdev_part_base *part_base = _part_base; 265 266 spdk_bdev_part_base_hotremove(part_base, &g_error_disks); 267 } 268 269 static int 270 _vbdev_error_create(const char *base_bdev_name) 271 { 272 struct spdk_bdev_part_base *base = NULL; 273 struct error_disk *disk = NULL; 274 struct spdk_bdev *base_bdev; 275 char *name; 276 int rc; 277 278 rc = spdk_bdev_part_base_construct_ext(base_bdev_name, 279 vbdev_error_base_bdev_hotremove_cb, 280 &error_if, &vbdev_error_fn_table, &g_error_disks, 281 NULL, NULL, sizeof(struct error_channel), 282 NULL, NULL, &base); 283 if (rc != 0) { 284 if (rc != -ENODEV) { 285 SPDK_ERRLOG("could not construct part base for bdev %s\n", base_bdev_name); 286 } 287 return rc; 288 } 289 290 base_bdev = spdk_bdev_part_base_get_bdev(base); 291 292 disk = calloc(1, sizeof(*disk)); 293 if (!disk) { 294 SPDK_ERRLOG("Memory allocation failure\n"); 295 spdk_bdev_part_base_free(base); 296 return -ENOMEM; 297 } 298 299 name = spdk_sprintf_alloc("EE_%s", base_bdev_name); 300 if (!name) { 301 SPDK_ERRLOG("name allocation failure\n"); 302 spdk_bdev_part_base_free(base); 303 free(disk); 304 return -ENOMEM; 305 } 306 307 rc = spdk_bdev_part_construct(&disk->part, base, name, 0, base_bdev->blockcnt, 308 "Error Injection Disk"); 309 free(name); 310 if (rc) { 311 SPDK_ERRLOG("could not construct part for bdev %s\n", base_bdev_name); 312 /* spdk_bdev_part_construct will free name on failure */ 313 spdk_bdev_part_base_free(base); 314 free(disk); 315 return rc; 316 } 317 318 TAILQ_INIT(&disk->pending_ios); 319 320 return 0; 321 } 322 323 int 324 vbdev_error_create(const char *base_bdev_name) 325 { 326 int rc; 327 328 rc = vbdev_error_config_add(base_bdev_name); 329 if (rc != 0) { 330 SPDK_ERRLOG("Adding config for ErrorInjection bdev %s failed (rc=%d)\n", 331 base_bdev_name, rc); 332 return rc; 333 } 334 335 rc = _vbdev_error_create(base_bdev_name); 336 if (rc == -ENODEV) { 337 rc = 0; 338 } else if (rc != 0) { 339 vbdev_error_config_remove(base_bdev_name); 340 SPDK_ERRLOG("Could not create ErrorInjection bdev %s (rc=%d)\n", 341 base_bdev_name, rc); 342 } 343 344 return rc; 345 } 346 347 void 348 vbdev_error_delete(const char *error_vbdev_name, spdk_delete_error_complete cb_fn, void *cb_arg) 349 { 350 int rc; 351 352 rc = spdk_bdev_unregister_by_name(error_vbdev_name, &error_if, cb_fn, cb_arg); 353 if (rc != 0) { 354 cb_fn(cb_arg, rc); 355 } 356 } 357 358 static void 359 vbdev_error_clear_config(void) 360 { 361 struct spdk_vbdev_error_config *cfg; 362 363 while ((cfg = TAILQ_FIRST(&g_error_config))) { 364 TAILQ_REMOVE(&g_error_config, cfg, tailq); 365 free(cfg->base_bdev); 366 free(cfg); 367 } 368 } 369 370 static struct spdk_vbdev_error_config * 371 vbdev_error_config_find_by_base_name(const char *base_bdev_name) 372 { 373 struct spdk_vbdev_error_config *cfg; 374 375 TAILQ_FOREACH(cfg, &g_error_config, tailq) { 376 if (strcmp(cfg->base_bdev, base_bdev_name) == 0) { 377 return cfg; 378 } 379 } 380 381 return NULL; 382 } 383 384 static int 385 vbdev_error_config_add(const char *base_bdev_name) 386 { 387 struct spdk_vbdev_error_config *cfg; 388 389 cfg = vbdev_error_config_find_by_base_name(base_bdev_name); 390 if (cfg) { 391 SPDK_ERRLOG("vbdev_error_config for bdev %s already exists\n", 392 base_bdev_name); 393 return -EEXIST; 394 } 395 396 cfg = calloc(1, sizeof(*cfg)); 397 if (!cfg) { 398 SPDK_ERRLOG("calloc() failed for vbdev_error_config\n"); 399 return -ENOMEM; 400 } 401 402 cfg->base_bdev = strdup(base_bdev_name); 403 if (!cfg->base_bdev) { 404 free(cfg); 405 SPDK_ERRLOG("strdup() failed for base_bdev_name\n"); 406 return -ENOMEM; 407 } 408 409 TAILQ_INSERT_TAIL(&g_error_config, cfg, tailq); 410 411 return 0; 412 } 413 414 static int 415 vbdev_error_config_remove(const char *base_bdev_name) 416 { 417 struct spdk_vbdev_error_config *cfg; 418 419 cfg = vbdev_error_config_find_by_base_name(base_bdev_name); 420 if (!cfg) { 421 return -ENOENT; 422 } 423 424 TAILQ_REMOVE(&g_error_config, cfg, tailq); 425 free(cfg->base_bdev); 426 free(cfg); 427 return 0; 428 } 429 430 static int 431 vbdev_error_init(void) 432 { 433 return 0; 434 } 435 436 static void 437 vbdev_error_fini(void) 438 { 439 vbdev_error_clear_config(); 440 } 441 442 static void 443 vbdev_error_examine(struct spdk_bdev *bdev) 444 { 445 struct spdk_vbdev_error_config *cfg; 446 int rc; 447 448 cfg = vbdev_error_config_find_by_base_name(bdev->name); 449 if (cfg != NULL) { 450 rc = _vbdev_error_create(bdev->name); 451 if (rc != 0) { 452 SPDK_ERRLOG("could not create error vbdev for bdev %s at examine\n", 453 bdev->name); 454 } 455 } 456 457 spdk_bdev_module_examine_done(&error_if); 458 } 459 460 static int 461 vbdev_error_config_json(struct spdk_json_write_ctx *w) 462 { 463 struct spdk_vbdev_error_config *cfg; 464 465 TAILQ_FOREACH(cfg, &g_error_config, tailq) { 466 spdk_json_write_object_begin(w); 467 468 spdk_json_write_named_string(w, "method", "bdev_error_create"); 469 spdk_json_write_named_object_begin(w, "params"); 470 spdk_json_write_named_string(w, "base_name", cfg->base_bdev); 471 spdk_json_write_object_end(w); 472 473 spdk_json_write_object_end(w); 474 } 475 476 return 0; 477 } 478