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 int 98 vbdev_error_inject_error(char *name, uint32_t io_type, uint32_t error_type, uint32_t error_num) 99 { 100 struct spdk_bdev *bdev; 101 struct spdk_bdev_part *part; 102 struct error_disk *error_disk = NULL; 103 uint32_t i; 104 105 pthread_mutex_lock(&g_vbdev_error_mutex); 106 bdev = spdk_bdev_get_by_name(name); 107 if (!bdev) { 108 SPDK_ERRLOG("Could not find ErrorInjection bdev %s\n", name); 109 pthread_mutex_unlock(&g_vbdev_error_mutex); 110 return -ENODEV; 111 } 112 113 TAILQ_FOREACH(part, &g_error_disks, tailq) { 114 if (bdev == spdk_bdev_part_get_bdev(part)) { 115 error_disk = (struct error_disk *)part; 116 break; 117 } 118 } 119 120 if (error_disk == NULL) { 121 SPDK_ERRLOG("Could not find ErrorInjection bdev %s\n", name); 122 pthread_mutex_unlock(&g_vbdev_error_mutex); 123 return -ENODEV; 124 } 125 126 if (0xffffffff == io_type) { 127 for (i = 0; i < SPDK_COUNTOF(error_disk->error_vector); i++) { 128 error_disk->error_vector[i].error_type = error_type; 129 error_disk->error_vector[i].error_num = error_num; 130 } 131 } else if (0 == io_type) { 132 for (i = 0; i < SPDK_COUNTOF(error_disk->error_vector); i++) { 133 error_disk->error_vector[i].error_num = 0; 134 } 135 } else { 136 error_disk->error_vector[io_type].error_type = error_type; 137 error_disk->error_vector[io_type].error_num = error_num; 138 } 139 pthread_mutex_unlock(&g_vbdev_error_mutex); 140 return 0; 141 } 142 143 static void 144 vbdev_error_reset(struct error_disk *error_disk, struct spdk_bdev_io *bdev_io) 145 { 146 struct spdk_bdev_io *pending_io, *tmp; 147 148 TAILQ_FOREACH_SAFE(pending_io, &error_disk->pending_ios, module_link, tmp) { 149 TAILQ_REMOVE(&error_disk->pending_ios, pending_io, module_link); 150 spdk_bdev_io_complete(pending_io, SPDK_BDEV_IO_STATUS_FAILED); 151 } 152 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_SUCCESS); 153 } 154 155 static uint32_t 156 vbdev_error_get_error_type(struct error_disk *error_disk, uint32_t io_type) 157 { 158 if (error_disk->error_vector[io_type].error_num) { 159 return error_disk->error_vector[io_type].error_type; 160 } 161 return 0; 162 } 163 164 static void 165 vbdev_error_submit_request(struct spdk_io_channel *_ch, struct spdk_bdev_io *bdev_io) 166 { 167 struct error_channel *ch = spdk_io_channel_get_ctx(_ch); 168 struct error_disk *error_disk = bdev_io->bdev->ctxt; 169 uint32_t error_type; 170 171 switch (bdev_io->type) { 172 case SPDK_BDEV_IO_TYPE_READ: 173 case SPDK_BDEV_IO_TYPE_WRITE: 174 case SPDK_BDEV_IO_TYPE_UNMAP: 175 case SPDK_BDEV_IO_TYPE_FLUSH: 176 break; 177 case SPDK_BDEV_IO_TYPE_RESET: 178 vbdev_error_reset(error_disk, bdev_io); 179 return; 180 default: 181 SPDK_ERRLOG("Error Injection: unknown I/O type %d\n", bdev_io->type); 182 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 183 return; 184 } 185 186 error_type = vbdev_error_get_error_type(error_disk, bdev_io->type); 187 if (error_type == 0) { 188 int rc = spdk_bdev_part_submit_request(&ch->part_ch, bdev_io); 189 190 if (rc) { 191 SPDK_ERRLOG("bdev_error: submit request failed, rc=%d\n", rc); 192 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 193 } 194 return; 195 } else if (error_type == VBDEV_IO_FAILURE) { 196 error_disk->error_vector[bdev_io->type].error_num--; 197 spdk_bdev_io_complete(bdev_io, SPDK_BDEV_IO_STATUS_FAILED); 198 } else if (error_type == VBDEV_IO_PENDING) { 199 TAILQ_INSERT_TAIL(&error_disk->pending_ios, bdev_io, module_link); 200 error_disk->error_vector[bdev_io->type].error_num--; 201 } 202 } 203 204 static int 205 vbdev_error_destruct(void *ctx) 206 { 207 struct error_disk *error_disk = ctx; 208 struct spdk_bdev *base_bdev = spdk_bdev_part_get_base_bdev(&error_disk->part); 209 int rc; 210 211 rc = vbdev_error_config_remove(base_bdev->name); 212 if (rc != 0) { 213 SPDK_ERRLOG("vbdev_error_config_remove() failed\n"); 214 } 215 216 return spdk_bdev_part_free(&error_disk->part); 217 } 218 219 static int 220 vbdev_error_dump_info_json(void *ctx, struct spdk_json_write_ctx *w) 221 { 222 struct error_disk *error_disk = ctx; 223 struct spdk_bdev *base_bdev = spdk_bdev_part_get_base_bdev(&error_disk->part); 224 225 spdk_json_write_named_object_begin(w, "error_disk"); 226 227 spdk_json_write_named_string(w, "base_bdev", base_bdev->name); 228 229 spdk_json_write_object_end(w); 230 231 return 0; 232 } 233 234 static void 235 vbdev_error_write_config_json(struct spdk_bdev *bdev, struct spdk_json_write_ctx *w) 236 { 237 /* No config per bdev. */ 238 } 239 240 241 static struct spdk_bdev_fn_table vbdev_error_fn_table = { 242 .destruct = vbdev_error_destruct, 243 .submit_request = vbdev_error_submit_request, 244 .dump_info_json = vbdev_error_dump_info_json, 245 .write_config_json = vbdev_error_write_config_json 246 }; 247 248 static void 249 vbdev_error_base_bdev_hotremove_cb(void *_part_base) 250 { 251 struct spdk_bdev_part_base *part_base = _part_base; 252 253 spdk_bdev_part_base_hotremove(part_base, &g_error_disks); 254 } 255 256 static int 257 _vbdev_error_create(const char *base_bdev_name) 258 { 259 struct spdk_bdev_part_base *base = NULL; 260 struct error_disk *disk = NULL; 261 struct spdk_bdev *base_bdev; 262 char *name; 263 int rc; 264 265 rc = spdk_bdev_part_base_construct_ext(base_bdev_name, 266 vbdev_error_base_bdev_hotremove_cb, 267 &error_if, &vbdev_error_fn_table, &g_error_disks, 268 NULL, NULL, sizeof(struct error_channel), 269 NULL, NULL, &base); 270 if (rc != 0) { 271 if (rc != -ENODEV) { 272 SPDK_ERRLOG("could not construct part base for bdev %s\n", base_bdev_name); 273 } 274 return rc; 275 } 276 277 base_bdev = spdk_bdev_part_base_get_bdev(base); 278 279 disk = calloc(1, sizeof(*disk)); 280 if (!disk) { 281 SPDK_ERRLOG("Memory allocation failure\n"); 282 spdk_bdev_part_base_free(base); 283 return -ENOMEM; 284 } 285 286 name = spdk_sprintf_alloc("EE_%s", base_bdev_name); 287 if (!name) { 288 SPDK_ERRLOG("name allocation failure\n"); 289 spdk_bdev_part_base_free(base); 290 free(disk); 291 return -ENOMEM; 292 } 293 294 rc = spdk_bdev_part_construct(&disk->part, base, name, 0, base_bdev->blockcnt, 295 "Error Injection Disk"); 296 free(name); 297 if (rc) { 298 SPDK_ERRLOG("could not construct part for bdev %s\n", base_bdev_name); 299 /* spdk_bdev_part_construct will free name on failure */ 300 spdk_bdev_part_base_free(base); 301 free(disk); 302 return rc; 303 } 304 305 TAILQ_INIT(&disk->pending_ios); 306 307 return 0; 308 } 309 310 int 311 vbdev_error_create(const char *base_bdev_name) 312 { 313 int rc; 314 315 rc = vbdev_error_config_add(base_bdev_name); 316 if (rc != 0) { 317 SPDK_ERRLOG("Adding config for ErrorInjection bdev %s failed (rc=%d)\n", 318 base_bdev_name, rc); 319 return rc; 320 } 321 322 rc = _vbdev_error_create(base_bdev_name); 323 if (rc == -ENODEV) { 324 rc = 0; 325 } else if (rc != 0) { 326 vbdev_error_config_remove(base_bdev_name); 327 SPDK_ERRLOG("Could not create ErrorInjection bdev %s (rc=%d)\n", 328 base_bdev_name, rc); 329 } 330 331 return rc; 332 } 333 334 void 335 vbdev_error_delete(struct spdk_bdev *vbdev, spdk_delete_error_complete cb_fn, void *cb_arg) 336 { 337 if (!vbdev || vbdev->module != &error_if) { 338 cb_fn(cb_arg, -ENODEV); 339 return; 340 } 341 342 spdk_bdev_unregister(vbdev, cb_fn, cb_arg); 343 } 344 345 static void 346 vbdev_error_clear_config(void) 347 { 348 struct spdk_vbdev_error_config *cfg; 349 350 while ((cfg = TAILQ_FIRST(&g_error_config))) { 351 TAILQ_REMOVE(&g_error_config, cfg, tailq); 352 free(cfg->base_bdev); 353 free(cfg); 354 } 355 } 356 357 static struct spdk_vbdev_error_config * 358 vbdev_error_config_find_by_base_name(const char *base_bdev_name) 359 { 360 struct spdk_vbdev_error_config *cfg; 361 362 TAILQ_FOREACH(cfg, &g_error_config, tailq) { 363 if (strcmp(cfg->base_bdev, base_bdev_name) == 0) { 364 return cfg; 365 } 366 } 367 368 return NULL; 369 } 370 371 static int 372 vbdev_error_config_add(const char *base_bdev_name) 373 { 374 struct spdk_vbdev_error_config *cfg; 375 376 cfg = vbdev_error_config_find_by_base_name(base_bdev_name); 377 if (cfg) { 378 SPDK_ERRLOG("vbdev_error_config for bdev %s already exists\n", 379 base_bdev_name); 380 return -EEXIST; 381 } 382 383 cfg = calloc(1, sizeof(*cfg)); 384 if (!cfg) { 385 SPDK_ERRLOG("calloc() failed for vbdev_error_config\n"); 386 return -ENOMEM; 387 } 388 389 cfg->base_bdev = strdup(base_bdev_name); 390 if (!cfg->base_bdev) { 391 free(cfg); 392 SPDK_ERRLOG("strdup() failed for base_bdev_name\n"); 393 return -ENOMEM; 394 } 395 396 TAILQ_INSERT_TAIL(&g_error_config, cfg, tailq); 397 398 return 0; 399 } 400 401 static int 402 vbdev_error_config_remove(const char *base_bdev_name) 403 { 404 struct spdk_vbdev_error_config *cfg; 405 406 cfg = vbdev_error_config_find_by_base_name(base_bdev_name); 407 if (!cfg) { 408 return -ENOENT; 409 } 410 411 TAILQ_REMOVE(&g_error_config, cfg, tailq); 412 free(cfg->base_bdev); 413 free(cfg); 414 return 0; 415 } 416 417 static int 418 vbdev_error_init(void) 419 { 420 return 0; 421 } 422 423 static void 424 vbdev_error_fini(void) 425 { 426 vbdev_error_clear_config(); 427 } 428 429 static void 430 vbdev_error_examine(struct spdk_bdev *bdev) 431 { 432 struct spdk_vbdev_error_config *cfg; 433 int rc; 434 435 cfg = vbdev_error_config_find_by_base_name(bdev->name); 436 if (cfg != NULL) { 437 rc = _vbdev_error_create(bdev->name); 438 if (rc != 0) { 439 SPDK_ERRLOG("could not create error vbdev for bdev %s at examine\n", 440 bdev->name); 441 } 442 } 443 444 spdk_bdev_module_examine_done(&error_if); 445 } 446 447 static int 448 vbdev_error_config_json(struct spdk_json_write_ctx *w) 449 { 450 struct spdk_vbdev_error_config *cfg; 451 452 TAILQ_FOREACH(cfg, &g_error_config, tailq) { 453 spdk_json_write_object_begin(w); 454 455 spdk_json_write_named_string(w, "method", "bdev_error_create"); 456 spdk_json_write_named_object_begin(w, "params"); 457 spdk_json_write_named_string(w, "base_name", cfg->base_bdev); 458 spdk_json_write_object_end(w); 459 460 spdk_json_write_object_end(w); 461 } 462 463 return 0; 464 } 465