Add a mechanism to inject errors instead of passing requests on. With no
further patches applied, you can use it by setting inject_errno in gdb.

Signed-off-by: Kevin Wolf <kw...@redhat.com>
---
 block/blkdebug.c |   63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 63 insertions(+), 0 deletions(-)

diff --git a/block/blkdebug.c b/block/blkdebug.c
index 2c7e0dd..f8ccd3c 100644
--- a/block/blkdebug.c
+++ b/block/blkdebug.c
@@ -26,10 +26,26 @@
 #include "block_int.h"
 #include "module.h"
 
+#include <stdbool.h>
+
 typedef struct BDRVBlkdebugState {
     BlockDriverState *hd;
+
+    int inject_errno;
+    bool inject_once;
+
+    /* Decides if aio_readv/writev fails right away (true) or returns an error
+     * return value only in the callback (false) */
+    bool inject_immediately;
 } BDRVBlkdebugState;
 
+struct callback_data {
+    QEMUBH *bh;
+    BlockDriverCompletionFunc *cb;
+    int ret;
+    void *opaque;
+};
+
 static int blkdebug_open(BlockDriverState *bs, const char *filename, int flags)
 {
     BDRVBlkdebugState *s = bs->opaque;
@@ -42,11 +58,53 @@ static int blkdebug_open(BlockDriverState *bs, const char 
*filename, int flags)
     return bdrv_file_open(&s->hd, filename, flags);
 }
 
+static void error_callback_bh(void *opaque)
+{
+    struct callback_data *d = opaque;
+    qemu_bh_delete(d->bh);
+    d->cb(d->opaque, d->ret);
+    qemu_free(d);
+}
+
+static BlockDriverAIOCB *inject_error(BlockDriverState *bs,
+    BlockDriverCompletionFunc *cb, void *opaque)
+{
+    BDRVBlkdebugState *s = bs->opaque;
+    int error = s->inject_errno;
+    struct callback_data *d;
+    QEMUBH *bh;
+
+    if (s->inject_once) {
+        s->inject_errno = 0;
+    }
+
+    if (s->inject_immediately) {
+        return NULL;
+    }
+
+    d = qemu_mallocz(sizeof(*d));
+    d->ret = error;
+    d->opaque = opaque;
+    d->cb = cb;
+
+    bh = qemu_bh_new(error_callback_bh, d);
+    d->bh = bh;
+    qemu_bh_schedule(bh);
+
+    // TODO Use a real AIOCB
+    return (BlockDriverAIOCB*) 42;
+}
+
 static BlockDriverAIOCB *blkdebug_aio_readv(BlockDriverState *bs,
     int64_t sector_num, QEMUIOVector *qiov, int nb_sectors,
     BlockDriverCompletionFunc *cb, void *opaque)
 {
     BDRVBlkdebugState *s = bs->opaque;
+
+    if (s->inject_errno) {
+        return inject_error(bs, cb, opaque);
+    }
+
     BlockDriverAIOCB *acb =
         bdrv_aio_readv(s->hd, sector_num, qiov, nb_sectors, cb, opaque);
     return acb;
@@ -57,6 +115,11 @@ static BlockDriverAIOCB 
*blkdebug_aio_writev(BlockDriverState *bs,
     BlockDriverCompletionFunc *cb, void *opaque)
 {
     BDRVBlkdebugState *s = bs->opaque;
+
+    if (s->inject_errno) {
+        return inject_error(bs, cb, opaque);
+    }
+
     BlockDriverAIOCB *acb =
         bdrv_aio_writev(s->hd, sector_num, qiov, nb_sectors, cb, opaque);
     return acb;
-- 
1.6.6.1



Reply via email to