Patchwork [RFC,4/7] blkdebug: Inject errors

login
register
mail settings
Submitter Kevin Wolf
Date March 15, 2010, 5:08 p.m.
Message ID <1268672915-12233-5-git-send-email-kwolf@redhat.com>
Download mbox | patch
Permalink /patch/47769/
State New
Headers show

Comments

Kevin Wolf - March 15, 2010, 5:08 p.m.
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 <kwolf@redhat.com>
---
 block/blkdebug.c |   63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 63 insertions(+), 0 deletions(-)
Christoph Hellwig - March 28, 2010, 12:25 p.m.
On Mon, Mar 15, 2010 at 06:08:32PM +0100, Kevin Wolf wrote:
> 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 <kwolf@redhat.com>

The magic iocb is quite a hack, but it should work good enough for now.


Reviewed-by: Christoph Hellwig <hch@lst.de>

Patch

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;