Statistics
| Branch: | Revision:

root / block / blkdebug.c @ e4780db4

History | View | Annotate | Download (12.9 kB)

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
    QLIST_HEAD(, BlkdebugRule) rules[BLKDBG_EVENT_MAX];
32
    QSIMPLEQ_HEAD(, BlkdebugRule) active_rules;
33
} BDRVBlkdebugState;
34

    
35
typedef struct BlkdebugAIOCB {
36
    BlockDriverAIOCB common;
37
    QEMUBH *bh;
38
    int ret;
39
} BlkdebugAIOCB;
40

    
41
static void blkdebug_aio_cancel(BlockDriverAIOCB *blockacb);
42

    
43
static AIOPool blkdebug_aio_pool = {
44
    .aiocb_size = sizeof(BlkdebugAIOCB),
45
    .cancel     = blkdebug_aio_cancel,
46
};
47

    
48
enum {
49
    ACTION_INJECT_ERROR,
50
    ACTION_SET_STATE,
51
};
52

    
53
typedef struct BlkdebugRule {
54
    BlkDebugEvent event;
55
    int action;
56
    int state;
57
    union {
58
        struct {
59
            int error;
60
            int immediately;
61
            int once;
62
            int64_t sector;
63
        } inject;
64
        struct {
65
            int new_state;
66
        } set_state;
67
    } options;
68
    QLIST_ENTRY(BlkdebugRule) next;
69
    QSIMPLEQ_ENTRY(BlkdebugRule) active_next;
70
} BlkdebugRule;
71

    
72
static QemuOptsList inject_error_opts = {
73
    .name = "inject-error",
74
    .head = QTAILQ_HEAD_INITIALIZER(inject_error_opts.head),
75
    .desc = {
76
        {
77
            .name = "event",
78
            .type = QEMU_OPT_STRING,
79
        },
80
        {
81
            .name = "state",
82
            .type = QEMU_OPT_NUMBER,
83
        },
84
        {
85
            .name = "errno",
86
            .type = QEMU_OPT_NUMBER,
87
        },
88
        {
89
            .name = "sector",
90
            .type = QEMU_OPT_NUMBER,
91
        },
92
        {
93
            .name = "once",
94
            .type = QEMU_OPT_BOOL,
95
        },
96
        {
97
            .name = "immediately",
98
            .type = QEMU_OPT_BOOL,
99
        },
100
        { /* end of list */ }
101
    },
102
};
103

    
104
static QemuOptsList set_state_opts = {
105
    .name = "set-state",
106
    .head = QTAILQ_HEAD_INITIALIZER(set_state_opts.head),
107
    .desc = {
108
        {
109
            .name = "event",
110
            .type = QEMU_OPT_STRING,
111
        },
112
        {
113
            .name = "state",
114
            .type = QEMU_OPT_NUMBER,
115
        },
116
        {
117
            .name = "new_state",
118
            .type = QEMU_OPT_NUMBER,
119
        },
120
        { /* end of list */ }
121
    },
122
};
123

    
124
static QemuOptsList *config_groups[] = {
125
    &inject_error_opts,
126
    &set_state_opts,
127
    NULL
128
};
129

    
130
static const char *event_names[BLKDBG_EVENT_MAX] = {
131
    [BLKDBG_L1_UPDATE]                      = "l1_update",
132
    [BLKDBG_L1_GROW_ALLOC_TABLE]            = "l1_grow.alloc_table",
133
    [BLKDBG_L1_GROW_WRITE_TABLE]            = "l1_grow.write_table",
134
    [BLKDBG_L1_GROW_ACTIVATE_TABLE]         = "l1_grow.activate_table",
135

    
136
    [BLKDBG_L2_LOAD]                        = "l2_load",
137
    [BLKDBG_L2_UPDATE]                      = "l2_update",
138
    [BLKDBG_L2_UPDATE_COMPRESSED]           = "l2_update_compressed",
139
    [BLKDBG_L2_ALLOC_COW_READ]              = "l2_alloc.cow_read",
140
    [BLKDBG_L2_ALLOC_WRITE]                 = "l2_alloc.write",
141

    
142
    [BLKDBG_READ_AIO]                       = "read_aio",
143
    [BLKDBG_READ_BACKING_AIO]               = "read_backing_aio",
144
    [BLKDBG_READ_COMPRESSED]                = "read_compressed",
145

    
146
    [BLKDBG_WRITE_AIO]                      = "write_aio",
147
    [BLKDBG_WRITE_COMPRESSED]               = "write_compressed",
148

    
149
    [BLKDBG_VMSTATE_LOAD]                   = "vmstate_load",
150
    [BLKDBG_VMSTATE_SAVE]                   = "vmstate_save",
151

    
152
    [BLKDBG_COW_READ]                       = "cow_read",
153
    [BLKDBG_COW_WRITE]                      = "cow_write",
154

    
155
    [BLKDBG_REFTABLE_LOAD]                  = "reftable_load",
156
    [BLKDBG_REFTABLE_GROW]                  = "reftable_grow",
157

    
158
    [BLKDBG_REFBLOCK_LOAD]                  = "refblock_load",
159
    [BLKDBG_REFBLOCK_UPDATE]                = "refblock_update",
160
    [BLKDBG_REFBLOCK_UPDATE_PART]           = "refblock_update_part",
161
    [BLKDBG_REFBLOCK_ALLOC]                 = "refblock_alloc",
162
    [BLKDBG_REFBLOCK_ALLOC_HOOKUP]          = "refblock_alloc.hookup",
163
    [BLKDBG_REFBLOCK_ALLOC_WRITE]           = "refblock_alloc.write",
164
    [BLKDBG_REFBLOCK_ALLOC_WRITE_BLOCKS]    = "refblock_alloc.write_blocks",
165
    [BLKDBG_REFBLOCK_ALLOC_WRITE_TABLE]     = "refblock_alloc.write_table",
166
    [BLKDBG_REFBLOCK_ALLOC_SWITCH_TABLE]    = "refblock_alloc.switch_table",
167

    
168
    [BLKDBG_CLUSTER_ALLOC]                  = "cluster_alloc",
169
    [BLKDBG_CLUSTER_ALLOC_BYTES]            = "cluster_alloc_bytes",
170
    [BLKDBG_CLUSTER_FREE]                   = "cluster_free",
171
};
172

    
173
static int get_event_by_name(const char *name, BlkDebugEvent *event)
174
{
175
    int i;
176

    
177
    for (i = 0; i < BLKDBG_EVENT_MAX; i++) {
178
        if (!strcmp(event_names[i], name)) {
179
            *event = i;
180
            return 0;
181
        }
182
    }
183

    
184
    return -1;
185
}
186

    
187
struct add_rule_data {
188
    BDRVBlkdebugState *s;
189
    int action;
190
};
191

    
192
static int add_rule(QemuOpts *opts, void *opaque)
193
{
194
    struct add_rule_data *d = opaque;
195
    BDRVBlkdebugState *s = d->s;
196
    const char* event_name;
197
    BlkDebugEvent event;
198
    struct BlkdebugRule *rule;
199

    
200
    /* Find the right event for the rule */
201
    event_name = qemu_opt_get(opts, "event");
202
    if (!event_name || get_event_by_name(event_name, &event) < 0) {
203
        return -1;
204
    }
205

    
206
    /* Set attributes common for all actions */
207
    rule = g_malloc0(sizeof(*rule));
208
    *rule = (struct BlkdebugRule) {
209
        .event  = event,
210
        .action = d->action,
211
        .state  = qemu_opt_get_number(opts, "state", 0),
212
    };
213

    
214
    /* Parse action-specific options */
215
    switch (d->action) {
216
    case ACTION_INJECT_ERROR:
217
        rule->options.inject.error = qemu_opt_get_number(opts, "errno", EIO);
218
        rule->options.inject.once  = qemu_opt_get_bool(opts, "once", 0);
219
        rule->options.inject.immediately =
220
            qemu_opt_get_bool(opts, "immediately", 0);
221
        rule->options.inject.sector = qemu_opt_get_number(opts, "sector", -1);
222
        break;
223

    
224
    case ACTION_SET_STATE:
225
        rule->options.set_state.new_state =
226
            qemu_opt_get_number(opts, "new_state", 0);
227
        break;
228
    };
229

    
230
    /* Add the rule */
231
    QLIST_INSERT_HEAD(&s->rules[event], rule, next);
232

    
233
    return 0;
234
}
235

    
236
static int read_config(BDRVBlkdebugState *s, const char *filename)
237
{
238
    FILE *f;
239
    int ret;
240
    struct add_rule_data d;
241

    
242
    f = fopen(filename, "r");
243
    if (f == NULL) {
244
        return -errno;
245
    }
246

    
247
    ret = qemu_config_parse(f, config_groups, filename);
248
    if (ret < 0) {
249
        goto fail;
250
    }
251

    
252
    d.s = s;
253
    d.action = ACTION_INJECT_ERROR;
254
    qemu_opts_foreach(&inject_error_opts, add_rule, &d, 0);
255

    
256
    d.action = ACTION_SET_STATE;
257
    qemu_opts_foreach(&set_state_opts, add_rule, &d, 0);
258

    
259
    ret = 0;
260
fail:
261
    qemu_opts_reset(&inject_error_opts);
262
    qemu_opts_reset(&set_state_opts);
263
    fclose(f);
264
    return ret;
265
}
266

    
267
/* Valid blkdebug filenames look like blkdebug:path/to/config:path/to/image */
268
static int blkdebug_open(BlockDriverState *bs, const char *filename, int flags)
269
{
270
    BDRVBlkdebugState *s = bs->opaque;
271
    int ret;
272
    char *config, *c;
273

    
274
    /* Parse the blkdebug: prefix */
275
    if (strncmp(filename, "blkdebug:", strlen("blkdebug:"))) {
276
        return -EINVAL;
277
    }
278
    filename += strlen("blkdebug:");
279

    
280
    /* Read rules from config file */
281
    c = strchr(filename, ':');
282
    if (c == NULL) {
283
        return -EINVAL;
284
    }
285

    
286
    config = g_strdup(filename);
287
    config[c - filename] = '\0';
288
    ret = read_config(s, config);
289
    g_free(config);
290
    if (ret < 0) {
291
        return ret;
292
    }
293
    filename = c + 1;
294

    
295
    /* Set initial state */
296
    s->state = 1;
297

    
298
    /* Open the backing file */
299
    ret = bdrv_file_open(&bs->file, filename, flags);
300
    if (ret < 0) {
301
        return ret;
302
    }
303

    
304
    return 0;
305
}
306

    
307
static void error_callback_bh(void *opaque)
308
{
309
    struct BlkdebugAIOCB *acb = opaque;
310
    qemu_bh_delete(acb->bh);
311
    acb->common.cb(acb->common.opaque, acb->ret);
312
    qemu_aio_release(acb);
313
}
314

    
315
static void blkdebug_aio_cancel(BlockDriverAIOCB *blockacb)
316
{
317
    BlkdebugAIOCB *acb = container_of(blockacb, BlkdebugAIOCB, common);
318
    qemu_aio_release(acb);
319
}
320

    
321
static BlockDriverAIOCB *inject_error(BlockDriverState *bs,
322
    BlockDriverCompletionFunc *cb, void *opaque, BlkdebugRule *rule)
323
{
324
    BDRVBlkdebugState *s = bs->opaque;
325
    int error = rule->options.inject.error;
326
    struct BlkdebugAIOCB *acb;
327
    QEMUBH *bh;
328

    
329
    if (rule->options.inject.once) {
330
        QSIMPLEQ_INIT(&s->active_rules);
331
    }
332

    
333
    if (rule->options.inject.immediately) {
334
        return NULL;
335
    }
336

    
337
    acb = qemu_aio_get(&blkdebug_aio_pool, bs, cb, opaque);
338
    acb->ret = -error;
339

    
340
    bh = qemu_bh_new(error_callback_bh, acb);
341
    acb->bh = bh;
342
    qemu_bh_schedule(bh);
343

    
344
    return &acb->common;
345
}
346

    
347
static BlockDriverAIOCB *blkdebug_aio_readv(BlockDriverState *bs,
348
    int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
349
    BlockDriverCompletionFunc *cb, void *opaque)
350
{
351
    BDRVBlkdebugState *s = bs->opaque;
352
    BlkdebugRule *rule = NULL;
353

    
354
    QSIMPLEQ_FOREACH(rule, &s->active_rules, active_next) {
355
        if (rule->options.inject.sector == -1 ||
356
            (rule->options.inject.sector >= sector_num &&
357
             rule->options.inject.sector < sector_num + nb_sectors)) {
358
            break;
359
        }
360
    }
361

    
362
    if (rule && rule->options.inject.error) {
363
        return inject_error(bs, cb, opaque, rule);
364
    }
365

    
366
    return bdrv_aio_readv(bs->file, sector_num, qiov, nb_sectors, cb, opaque);
367
}
368

    
369
static BlockDriverAIOCB *blkdebug_aio_writev(BlockDriverState *bs,
370
    int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
371
    BlockDriverCompletionFunc *cb, void *opaque)
372
{
373
    BDRVBlkdebugState *s = bs->opaque;
374
    BlkdebugRule *rule = NULL;
375

    
376
    QSIMPLEQ_FOREACH(rule, &s->active_rules, active_next) {
377
        if (rule->options.inject.sector == -1 ||
378
            (rule->options.inject.sector >= sector_num &&
379
             rule->options.inject.sector < sector_num + nb_sectors)) {
380
            break;
381
        }
382
    }
383

    
384
    if (rule && rule->options.inject.error) {
385
        return inject_error(bs, cb, opaque, rule);
386
    }
387

    
388
    return bdrv_aio_writev(bs->file, sector_num, qiov, nb_sectors, cb, opaque);
389
}
390

    
391
static void blkdebug_close(BlockDriverState *bs)
392
{
393
    BDRVBlkdebugState *s = bs->opaque;
394
    BlkdebugRule *rule, *next;
395
    int i;
396

    
397
    for (i = 0; i < BLKDBG_EVENT_MAX; i++) {
398
        QLIST_FOREACH_SAFE(rule, &s->rules[i], next, next) {
399
            QLIST_REMOVE(rule, next);
400
            g_free(rule);
401
        }
402
    }
403
}
404

    
405
static bool process_rule(BlockDriverState *bs, struct BlkdebugRule *rule,
406
    int old_state, bool injected)
407
{
408
    BDRVBlkdebugState *s = bs->opaque;
409

    
410
    /* Only process rules for the current state */
411
    if (rule->state && rule->state != old_state) {
412
        return injected;
413
    }
414

    
415
    /* Take the action */
416
    switch (rule->action) {
417
    case ACTION_INJECT_ERROR:
418
        if (!injected) {
419
            QSIMPLEQ_INIT(&s->active_rules);
420
            injected = true;
421
        }
422
        QSIMPLEQ_INSERT_HEAD(&s->active_rules, rule, active_next);
423
        break;
424

    
425
    case ACTION_SET_STATE:
426
        s->state = rule->options.set_state.new_state;
427
        break;
428
    }
429
    return injected;
430
}
431

    
432
static void blkdebug_debug_event(BlockDriverState *bs, BlkDebugEvent event)
433
{
434
    BDRVBlkdebugState *s = bs->opaque;
435
    struct BlkdebugRule *rule;
436
    int old_state = s->state;
437
    bool injected;
438

    
439
    assert((int)event >= 0 && event < BLKDBG_EVENT_MAX);
440

    
441
    injected = false;
442
    QLIST_FOREACH(rule, &s->rules[event], next) {
443
        injected = process_rule(bs, rule, old_state, injected);
444
    }
445
}
446

    
447
static int64_t blkdebug_getlength(BlockDriverState *bs)
448
{
449
    return bdrv_getlength(bs->file);
450
}
451

    
452
static BlockDriver bdrv_blkdebug = {
453
    .format_name        = "blkdebug",
454
    .protocol_name      = "blkdebug",
455

    
456
    .instance_size      = sizeof(BDRVBlkdebugState),
457

    
458
    .bdrv_file_open     = blkdebug_open,
459
    .bdrv_close         = blkdebug_close,
460
    .bdrv_getlength     = blkdebug_getlength,
461

    
462
    .bdrv_aio_readv     = blkdebug_aio_readv,
463
    .bdrv_aio_writev    = blkdebug_aio_writev,
464

    
465
    .bdrv_debug_event   = blkdebug_debug_event,
466
};
467

    
468
static void bdrv_blkdebug_init(void)
469
{
470
    bdrv_register(&bdrv_blkdebug);
471
}
472

    
473
block_init(bdrv_blkdebug_init);