1 /* 2 * Block protocol for I/O error injection 3 * 4 * Copyright (c) 2010 Kevin Wolf <kwolf@redhat.com> 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25 #include "qemu-common.h" 26 #include "block_int.h" 27 #include "module.h" 28 29 typedef struct BDRVBlkdebugState { 30 int state; 31 int new_state; 32 QLIST_HEAD(, BlkdebugRule) rules[BLKDBG_EVENT_MAX]; 33 QSIMPLEQ_HEAD(, BlkdebugRule) active_rules; 34 } BDRVBlkdebugState; 35 36 typedef struct BlkdebugAIOCB { 37 BlockDriverAIOCB common; 38 QEMUBH *bh; 39 int ret; 40 } BlkdebugAIOCB; 41 42 static void blkdebug_aio_cancel(BlockDriverAIOCB *blockacb); 43 44 static const AIOCBInfo blkdebug_aiocb_info = { 45 .aiocb_size = sizeof(BlkdebugAIOCB), 46 .cancel = blkdebug_aio_cancel, 47 }; 48 49 enum { 50 ACTION_INJECT_ERROR, 51 ACTION_SET_STATE, 52 }; 53 54 typedef struct BlkdebugRule { 55 BlkDebugEvent event; 56 int action; 57 int state; 58 union { 59 struct { 60 int error; 61 int immediately; 62 int once; 63 int64_t sector; 64 } inject; 65 struct { 66 int new_state; 67 } set_state; 68 } options; 69 QLIST_ENTRY(BlkdebugRule) next; 70 QSIMPLEQ_ENTRY(BlkdebugRule) active_next; 71 } BlkdebugRule; 72 73 static QemuOptsList inject_error_opts = { 74 .name = "inject-error", 75 .head = QTAILQ_HEAD_INITIALIZER(inject_error_opts.head), 76 .desc = { 77 { 78 .name = "event", 79 .type = QEMU_OPT_STRING, 80 }, 81 { 82 .name = "state", 83 .type = QEMU_OPT_NUMBER, 84 }, 85 { 86 .name = "errno", 87 .type = QEMU_OPT_NUMBER, 88 }, 89 { 90 .name = "sector", 91 .type = QEMU_OPT_NUMBER, 92 }, 93 { 94 .name = "once", 95 .type = QEMU_OPT_BOOL, 96 }, 97 { 98 .name = "immediately", 99 .type = QEMU_OPT_BOOL, 100 }, 101 { /* end of list */ } 102 }, 103 }; 104 105 static QemuOptsList set_state_opts = { 106 .name = "set-state", 107 .head = QTAILQ_HEAD_INITIALIZER(set_state_opts.head), 108 .desc = { 109 { 110 .name = "event", 111 .type = QEMU_OPT_STRING, 112 }, 113 { 114 .name = "state", 115 .type = QEMU_OPT_NUMBER, 116 }, 117 { 118 .name = "new_state", 119 .type = QEMU_OPT_NUMBER, 120 }, 121 { /* end of list */ } 122 }, 123 }; 124 125 static QemuOptsList *config_groups[] = { 126 &inject_error_opts, 127 &set_state_opts, 128 NULL 129 }; 130 131 static const char *event_names[BLKDBG_EVENT_MAX] = { 132 [BLKDBG_L1_UPDATE] = "l1_update", 133 [BLKDBG_L1_GROW_ALLOC_TABLE] = "l1_grow.alloc_table", 134 [BLKDBG_L1_GROW_WRITE_TABLE] = "l1_grow.write_table", 135 [BLKDBG_L1_GROW_ACTIVATE_TABLE] = "l1_grow.activate_table", 136 137 [BLKDBG_L2_LOAD] = "l2_load", 138 [BLKDBG_L2_UPDATE] = "l2_update", 139 [BLKDBG_L2_UPDATE_COMPRESSED] = "l2_update_compressed", 140 [BLKDBG_L2_ALLOC_COW_READ] = "l2_alloc.cow_read", 141 [BLKDBG_L2_ALLOC_WRITE] = "l2_alloc.write", 142 143 [BLKDBG_READ_AIO] = "read_aio", 144 [BLKDBG_READ_BACKING_AIO] = "read_backing_aio", 145 [BLKDBG_READ_COMPRESSED] = "read_compressed", 146 147 [BLKDBG_WRITE_AIO] = "write_aio", 148 [BLKDBG_WRITE_COMPRESSED] = "write_compressed", 149 150 [BLKDBG_VMSTATE_LOAD] = "vmstate_load", 151 [BLKDBG_VMSTATE_SAVE] = "vmstate_save", 152 153 [BLKDBG_COW_READ] = "cow_read", 154 [BLKDBG_COW_WRITE] = "cow_write", 155 156 [BLKDBG_REFTABLE_LOAD] = "reftable_load", 157 [BLKDBG_REFTABLE_GROW] = "reftable_grow", 158 159 [BLKDBG_REFBLOCK_LOAD] = "refblock_load", 160 [BLKDBG_REFBLOCK_UPDATE] = "refblock_update", 161 [BLKDBG_REFBLOCK_UPDATE_PART] = "refblock_update_part", 162 [BLKDBG_REFBLOCK_ALLOC] = "refblock_alloc", 163 [BLKDBG_REFBLOCK_ALLOC_HOOKUP] = "refblock_alloc.hookup", 164 [BLKDBG_REFBLOCK_ALLOC_WRITE] = "refblock_alloc.write", 165 [BLKDBG_REFBLOCK_ALLOC_WRITE_BLOCKS] = "refblock_alloc.write_blocks", 166 [BLKDBG_REFBLOCK_ALLOC_WRITE_TABLE] = "refblock_alloc.write_table", 167 [BLKDBG_REFBLOCK_ALLOC_SWITCH_TABLE] = "refblock_alloc.switch_table", 168 169 [BLKDBG_CLUSTER_ALLOC] = "cluster_alloc", 170 [BLKDBG_CLUSTER_ALLOC_BYTES] = "cluster_alloc_bytes", 171 [BLKDBG_CLUSTER_FREE] = "cluster_free", 172 }; 173 174 static int get_event_by_name(const char *name, BlkDebugEvent *event) 175 { 176 int i; 177 178 for (i = 0; i < BLKDBG_EVENT_MAX; i++) { 179 if (!strcmp(event_names[i], name)) { 180 *event = i; 181 return 0; 182 } 183 } 184 185 return -1; 186 } 187 188 struct add_rule_data { 189 BDRVBlkdebugState *s; 190 int action; 191 }; 192 193 static int add_rule(QemuOpts *opts, void *opaque) 194 { 195 struct add_rule_data *d = opaque; 196 BDRVBlkdebugState *s = d->s; 197 const char* event_name; 198 BlkDebugEvent event; 199 struct BlkdebugRule *rule; 200 201 /* Find the right event for the rule */ 202 event_name = qemu_opt_get(opts, "event"); 203 if (!event_name || get_event_by_name(event_name, &event) < 0) { 204 return -1; 205 } 206 207 /* Set attributes common for all actions */ 208 rule = g_malloc0(sizeof(*rule)); 209 *rule = (struct BlkdebugRule) { 210 .event = event, 211 .action = d->action, 212 .state = qemu_opt_get_number(opts, "state", 0), 213 }; 214 215 /* Parse action-specific options */ 216 switch (d->action) { 217 case ACTION_INJECT_ERROR: 218 rule->options.inject.error = qemu_opt_get_number(opts, "errno", EIO); 219 rule->options.inject.once = qemu_opt_get_bool(opts, "once", 0); 220 rule->options.inject.immediately = 221 qemu_opt_get_bool(opts, "immediately", 0); 222 rule->options.inject.sector = qemu_opt_get_number(opts, "sector", -1); 223 break; 224 225 case ACTION_SET_STATE: 226 rule->options.set_state.new_state = 227 qemu_opt_get_number(opts, "new_state", 0); 228 break; 229 }; 230 231 /* Add the rule */ 232 QLIST_INSERT_HEAD(&s->rules[event], rule, next); 233 234 return 0; 235 } 236 237 static int read_config(BDRVBlkdebugState *s, const char *filename) 238 { 239 FILE *f; 240 int ret; 241 struct add_rule_data d; 242 243 f = fopen(filename, "r"); 244 if (f == NULL) { 245 return -errno; 246 } 247 248 ret = qemu_config_parse(f, config_groups, filename); 249 if (ret < 0) { 250 goto fail; 251 } 252 253 d.s = s; 254 d.action = ACTION_INJECT_ERROR; 255 qemu_opts_foreach(&inject_error_opts, add_rule, &d, 0); 256 257 d.action = ACTION_SET_STATE; 258 qemu_opts_foreach(&set_state_opts, add_rule, &d, 0); 259 260 ret = 0; 261 fail: 262 qemu_opts_reset(&inject_error_opts); 263 qemu_opts_reset(&set_state_opts); 264 fclose(f); 265 return ret; 266 } 267 268 /* Valid blkdebug filenames look like blkdebug:path/to/config:path/to/image */ 269 static int blkdebug_open(BlockDriverState *bs, const char *filename, int flags) 270 { 271 BDRVBlkdebugState *s = bs->opaque; 272 int ret; 273 char *config, *c; 274 275 /* Parse the blkdebug: prefix */ 276 if (strncmp(filename, "blkdebug:", strlen("blkdebug:"))) { 277 return -EINVAL; 278 } 279 filename += strlen("blkdebug:"); 280 281 /* Read rules from config file */ 282 c = strchr(filename, ':'); 283 if (c == NULL) { 284 return -EINVAL; 285 } 286 287 config = g_strdup(filename); 288 config[c - filename] = '\0'; 289 ret = read_config(s, config); 290 g_free(config); 291 if (ret < 0) { 292 return ret; 293 } 294 filename = c + 1; 295 296 /* Set initial state */ 297 s->state = 1; 298 299 /* Open the backing file */ 300 ret = bdrv_file_open(&bs->file, filename, flags); 301 if (ret < 0) { 302 return ret; 303 } 304 305 return 0; 306 } 307 308 static void error_callback_bh(void *opaque) 309 { 310 struct BlkdebugAIOCB *acb = opaque; 311 qemu_bh_delete(acb->bh); 312 acb->common.cb(acb->common.opaque, acb->ret); 313 qemu_aio_release(acb); 314 } 315 316 static void blkdebug_aio_cancel(BlockDriverAIOCB *blockacb) 317 { 318 BlkdebugAIOCB *acb = container_of(blockacb, BlkdebugAIOCB, common); 319 qemu_aio_release(acb); 320 } 321 322 static BlockDriverAIOCB *inject_error(BlockDriverState *bs, 323 BlockDriverCompletionFunc *cb, void *opaque, BlkdebugRule *rule) 324 { 325 BDRVBlkdebugState *s = bs->opaque; 326 int error = rule->options.inject.error; 327 struct BlkdebugAIOCB *acb; 328 QEMUBH *bh; 329 330 if (rule->options.inject.once) { 331 QSIMPLEQ_INIT(&s->active_rules); 332 } 333 334 if (rule->options.inject.immediately) { 335 return NULL; 336 } 337 338 acb = qemu_aio_get(&blkdebug_aiocb_info, bs, cb, opaque); 339 acb->ret = -error; 340 341 bh = qemu_bh_new(error_callback_bh, acb); 342 acb->bh = bh; 343 qemu_bh_schedule(bh); 344 345 return &acb->common; 346 } 347 348 static BlockDriverAIOCB *blkdebug_aio_readv(BlockDriverState *bs, 349 int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, 350 BlockDriverCompletionFunc *cb, void *opaque) 351 { 352 BDRVBlkdebugState *s = bs->opaque; 353 BlkdebugRule *rule = NULL; 354 355 QSIMPLEQ_FOREACH(rule, &s->active_rules, active_next) { 356 if (rule->options.inject.sector == -1 || 357 (rule->options.inject.sector >= sector_num && 358 rule->options.inject.sector < sector_num + nb_sectors)) { 359 break; 360 } 361 } 362 363 if (rule && rule->options.inject.error) { 364 return inject_error(bs, cb, opaque, rule); 365 } 366 367 return bdrv_aio_readv(bs->file, sector_num, qiov, nb_sectors, cb, opaque); 368 } 369 370 static BlockDriverAIOCB *blkdebug_aio_writev(BlockDriverState *bs, 371 int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, 372 BlockDriverCompletionFunc *cb, void *opaque) 373 { 374 BDRVBlkdebugState *s = bs->opaque; 375 BlkdebugRule *rule = NULL; 376 377 QSIMPLEQ_FOREACH(rule, &s->active_rules, active_next) { 378 if (rule->options.inject.sector == -1 || 379 (rule->options.inject.sector >= sector_num && 380 rule->options.inject.sector < sector_num + nb_sectors)) { 381 break; 382 } 383 } 384 385 if (rule && rule->options.inject.error) { 386 return inject_error(bs, cb, opaque, rule); 387 } 388 389 return bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors, cb, opaque); 390 } 391 392 static void blkdebug_close(BlockDriverState *bs) 393 { 394 BDRVBlkdebugState *s = bs->opaque; 395 BlkdebugRule *rule, *next; 396 int i; 397 398 for (i = 0; i < BLKDBG_EVENT_MAX; i++) { 399 QLIST_FOREACH_SAFE(rule, &s->rules[i], next, next) { 400 QLIST_REMOVE(rule, next); 401 g_free(rule); 402 } 403 } 404 } 405 406 static bool process_rule(BlockDriverState *bs, struct BlkdebugRule *rule, 407 bool injected) 408 { 409 BDRVBlkdebugState *s = bs->opaque; 410 411 /* Only process rules for the current state */ 412 if (rule->state && rule->state != s->state) { 413 return injected; 414 } 415 416 /* Take the action */ 417 switch (rule->action) { 418 case ACTION_INJECT_ERROR: 419 if (!injected) { 420 QSIMPLEQ_INIT(&s->active_rules); 421 injected = true; 422 } 423 QSIMPLEQ_INSERT_HEAD(&s->active_rules, rule, active_next); 424 break; 425 426 case ACTION_SET_STATE: 427 s->new_state = rule->options.set_state.new_state; 428 break; 429 } 430 return injected; 431 } 432 433 static void blkdebug_debug_event(BlockDriverState *bs, BlkDebugEvent event) 434 { 435 BDRVBlkdebugState *s = bs->opaque; 436 struct BlkdebugRule *rule; 437 bool injected; 438 439 assert((int)event >= 0 && event < BLKDBG_EVENT_MAX); 440 441 injected = false; 442 s->new_state = s->state; 443 QLIST_FOREACH(rule, &s->rules[event], next) { 444 injected = process_rule(bs, rule, injected); 445 } 446 s->state = s->new_state; 447 } 448 449 static int64_t blkdebug_getlength(BlockDriverState *bs) 450 { 451 return bdrv_getlength(bs->file); 452 } 453 454 static BlockDriver bdrv_blkdebug = { 455 .format_name = "blkdebug", 456 .protocol_name = "blkdebug", 457 458 .instance_size = sizeof(BDRVBlkdebugState), 459 460 .bdrv_file_open = blkdebug_open, 461 .bdrv_close = blkdebug_close, 462 .bdrv_getlength = blkdebug_getlength, 463 464 .bdrv_aio_readv = blkdebug_aio_readv, 465 .bdrv_aio_writev = blkdebug_aio_writev, 466 467 .bdrv_debug_event = blkdebug_debug_event, 468 }; 469 470 static void bdrv_blkdebug_init(void) 471 { 472 bdrv_register(&bdrv_blkdebug); 473 } 474 475 block_init(bdrv_blkdebug_init); 476