Statistics
| Branch: | Revision:

root / block / blkdebug.c @ fab5cf59

History | View | Annotate | Download (12.8 kB)

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