qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Luiz Capitulino <lcapitulino@redhat.com>
To: Federico Simoncelli <fsimonce@redhat.com>
Cc: kwolf@redhat.com, pbonzini@redhat.com, mtosatti@redhat.com,
	qemu-devel@nongnu.org, armbru@redhat.com
Subject: Re: [Qemu-devel] [PATCH 1/2 v2] Add blkmirror block driver
Date: Fri, 24 Feb 2012 16:17:22 -0200	[thread overview]
Message-ID: <20120224161722.5be3aede@doriath.home> (raw)
In-Reply-To: <1330102144-14491-1-git-send-email-fsimonce@redhat.com>

On Fri, 24 Feb 2012 16:49:03 +0000
Federico Simoncelli <fsimonce@redhat.com> wrote:

> From: Marcelo Tosatti <mtosatti@redhat.com>
> 
> Mirrored writes are used by live block copy.
> 
> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
> Signed-off-by: Federico Simoncelli <fsimonce@redhat.com>
> ---
>  Makefile.objs      |    2 +-
>  block/blkmirror.c  |  247 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  docs/blkmirror.txt |   16 ++++
>  3 files changed, 264 insertions(+), 1 deletions(-)
>  create mode 100644 block/blkmirror.c
>  create mode 100644 docs/blkmirror.txt
> 
> diff --git a/Makefile.objs b/Makefile.objs
> index 67ee3df..6020308 100644
> --- a/Makefile.objs
> +++ b/Makefile.objs
> @@ -34,7 +34,7 @@ block-nested-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o vpc.o vv
>  block-nested-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o qcow2-cache.o
>  block-nested-y += qed.o qed-gencb.o qed-l2-cache.o qed-table.o qed-cluster.o
>  block-nested-y += qed-check.o
> -block-nested-y += parallels.o nbd.o blkdebug.o sheepdog.o blkverify.o
> +block-nested-y += parallels.o nbd.o blkdebug.o sheepdog.o blkverify.o blkmirror.o
>  block-nested-y += stream.o
>  block-nested-$(CONFIG_WIN32) += raw-win32.o
>  block-nested-$(CONFIG_POSIX) += raw-posix.o
> diff --git a/block/blkmirror.c b/block/blkmirror.c
> new file mode 100644
> index 0000000..49e3381
> --- /dev/null
> +++ b/block/blkmirror.c
> @@ -0,0 +1,247 @@
> +/*
> + * Block driver for mirrored writes.
> + *
> + * Copyright (C) 2011 Red Hat, Inc.
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2 or later.
> + * See the COPYING file in the top-level directory.
> + */
> +
> +#include <stdarg.h>
> +#include "block_int.h"
> +
> +typedef struct {
> +    BlockDriverState *bs[2];
> +} BdrvMirrorState;
> +
> +typedef struct DupAIOCB DupAIOCB;
> +
> +typedef struct SingleAIOCB {
> +    BlockDriverAIOCB *aiocb;
> +    int finished;
> +    DupAIOCB *parent;
> +} SingleAIOCB;
> +
> +struct DupAIOCB {
> +    BlockDriverAIOCB common;
> +    int count;
> +
> +    BlockDriverCompletionFunc *cb;
> +    SingleAIOCB aios[2];
> +    int ret;
> +};
> +
> +/* Valid blkmirror filenames look like
> + * blkmirror:path/to/image1:path/to/image2 */
> +static int blkmirror_open(BlockDriverState *bs, const char *filename, int flags)
> +{
> +    BdrvMirrorState *m = bs->opaque;
> +    int ret, escape, i, n;
> +    char *filename2;
> +
> +    /* Parse the blkmirror: prefix */
> +    if (strncmp(filename, "blkmirror:", strlen("blkmirror:"))) {
> +        return -EINVAL;
> +    }
> +    filename += strlen("blkmirror:");

Minor: you can use strstart() here.

> +
> +    /* Parse the raw image filename */
> +    filename2 = g_malloc(strlen(filename)+1);
> +    escape = 0;
> +    for (i = n = 0; i < strlen(filename); i++) {
> +        if (!escape && filename[i] == ':') {
> +            break;
> +        }
> +        if (!escape && filename[i] == '\\') {
> +            escape = 1;
> +        } else {
> +            escape = 0;
> +        }
> +
> +        if (!escape) {
> +            filename2[n++] = filename[i];
> +        }
> +    }
> +    filename2[n] = '\0';

You're escaping only the first image name string, is that intentional?

> +
> +    m->bs[0] = bdrv_new("");
> +    if (m->bs[0] == NULL) {
> +        g_free(filename2);
> +        return -ENOMEM;
> +    }
> +    ret = bdrv_open(m->bs[0], filename2, flags, NULL);
> +    g_free(filename2);
> +    if (ret < 0) {

Leaking m->bs[0]?

> +        return ret;
> +    }
> +    filename += i + 1;
> +
> +    m->bs[1] = bdrv_new("");
> +    if (m->bs[1] == NULL) {
> +        bdrv_delete(m->bs[0]);
> +        return -ENOMEM;
> +    }
> +    ret = bdrv_open(m->bs[1], filename, flags | BDRV_O_NO_BACKING, NULL);
> +    if (ret < 0) {
> +        bdrv_delete(m->bs[0]);

What about m->bs[1]?

> +        return ret;
> +    }
> +
> +    return 0;
> +}
> +
> +static void blkmirror_close(BlockDriverState *bs)
> +{
> +    BdrvMirrorState *m = bs->opaque;
> +    int i;
> +
> +    for (i = 0; i < 2; i++) {
> +        bdrv_delete(m->bs[i]);
> +        m->bs[i] = NULL;
> +    }
> +}
> +
> +static coroutine_fn int blkmirror_co_flush(BlockDriverState *bs)
> +{
> +    BdrvMirrorState *m = bs->opaque;
> +    int ret;
> +
> +    ret = bdrv_co_flush(m->bs[0]);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +
> +    return bdrv_co_flush(m->bs[1]);
> +}
> +
> +static int64_t blkmirror_getlength(BlockDriverState *bs)
> +{
> +    BdrvMirrorState *m = bs->opaque;
> +
> +    return bdrv_getlength(m->bs[0]);
> +}
> +
> +static BlockDriverAIOCB *blkmirror_aio_readv(BlockDriverState *bs,
> +                                             int64_t sector_num,
> +                                             QEMUIOVector *qiov,
> +                                             int nb_sectors,
> +                                             BlockDriverCompletionFunc *cb,
> +                                             void *opaque)
> +{
> +    BdrvMirrorState *m = bs->opaque;
> +    return bdrv_aio_readv(m->bs[0], sector_num, qiov, nb_sectors, cb, opaque);
> +}
> +
> +static void dup_aio_cancel(BlockDriverAIOCB *blockacb)
> +{
> +    DupAIOCB *acb = container_of(blockacb, DupAIOCB, common);
> +    int i;
> +
> +    for (i = 0 ; i < 2; i++) {
> +        if (!acb->aios[i].finished) {
> +            bdrv_aio_cancel(acb->aios[i].aiocb);
> +        }
> +    }
> +    qemu_aio_release(acb);
> +}
> +
> +static AIOPool dup_aio_pool = {
> +    .aiocb_size         = sizeof(DupAIOCB),
> +    .cancel             = dup_aio_cancel,
> +};
> +
> +static void blkmirror_aio_cb(void *opaque, int ret)
> +{
> +    SingleAIOCB *scb = opaque;
> +    DupAIOCB *dcb = scb->parent;
> +
> +    scb->finished = 1;
> +    dcb->count--;
> +    assert(dcb->count >= 0);
> +    if (ret < 0) {
> +        dcb->ret = ret;
> +    }
> +    if (dcb->count == 0) {
> +        dcb->common.cb(dcb->common.opaque, dcb->ret);
> +        qemu_aio_release(dcb);
> +    }
> +}
> +
> +static DupAIOCB *dup_aio_get(BlockDriverState *bs,
> +                             BlockDriverCompletionFunc *cb,
> +                             void *opaque)
> +{
> +    DupAIOCB *dcb;
> +    int i;
> +
> +    dcb = qemu_aio_get(&dup_aio_pool, bs, cb, opaque);
> +    if (!dcb) {
> +        return NULL;
> +    }
> +    dcb->count = 2;
> +    for (i = 0; i < 2; i++) {
> +        dcb->aios[i].parent = dcb;
> +        dcb->aios[i].finished = 0;
> +    }
> +    dcb->ret = 0;
> +
> +    return dcb;
> +}
> +
> +static BlockDriverAIOCB *blkmirror_aio_writev(BlockDriverState *bs,
> +                                              int64_t sector_num,
> +                                              QEMUIOVector *qiov,
> +                                              int nb_sectors,
> +                                              BlockDriverCompletionFunc *cb,
> +                                              void *opaque)
> +{
> +    BdrvMirrorState *m = bs->opaque;
> +    DupAIOCB *dcb = dup_aio_get(bs, cb, opaque);
> +    int i;
> +
> +    for (i = 0; i < 2; i++) {
> +        dcb->aios[i].aiocb = bdrv_aio_writev(m->bs[i], sector_num, qiov,
> +                                             nb_sectors, &blkmirror_aio_cb,
> +                                             &dcb->aios[i]);
> +    }
> +
> +    return &dcb->common;
> +}
> +
> +static coroutine_fn int blkmirror_co_discard(BlockDriverState *bs,
> +                             int64_t sector_num, int nb_sectors)
> +{
> +    BdrvMirrorState *m = bs->opaque;
> +    int ret;
> +
> +    ret = bdrv_co_discard(m->bs[0], sector_num, nb_sectors);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +
> +    return bdrv_co_discard(m->bs[1], sector_num, nb_sectors);
> +}
> +
> +
> +static BlockDriver bdrv_blkmirror = {
> +    .format_name        = "blkmirror",
> +    .protocol_name      = "blkmirror",
> +    .instance_size      = sizeof(BdrvMirrorState),
> +
> +    .bdrv_getlength     = blkmirror_getlength,
> +
> +    .bdrv_file_open     = blkmirror_open,
> +    .bdrv_close         = blkmirror_close,
> +    .bdrv_co_flush_to_disk = blkmirror_co_flush,
> +    .bdrv_co_discard    = blkmirror_co_discard,
> +
> +    .bdrv_aio_readv     = blkmirror_aio_readv,
> +    .bdrv_aio_writev    = blkmirror_aio_writev,
> +};
> +
> +static void bdrv_blkmirror_init(void)
> +{
> +    bdrv_register(&bdrv_blkmirror);
> +}
> +
> +block_init(bdrv_blkmirror_init);
> diff --git a/docs/blkmirror.txt b/docs/blkmirror.txt
> new file mode 100644
> index 0000000..cf73f3f
> --- /dev/null
> +++ b/docs/blkmirror.txt
> @@ -0,0 +1,16 @@
> +Block mirror driver
> +-------------------
> +
> +This driver will mirror writes to two distinct images.
> +It's used internally by live block copy.
> +
> +Format
> +------
> +
> +blkmirror:/image1.img:/image2.img
> +
> +'\' (backslash) can be used to escape colon processing
> +as a separator, in the first image filename.
> +Backslashes themselves also can be escaped as '\\'.
> +
> +

  parent reply	other threads:[~2012-02-24 18:18 UTC|newest]

Thread overview: 95+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-02-22 17:13 [Qemu-devel] Live Block Migration using Mirroring Federico Simoncelli
2012-02-22 17:13 ` [Qemu-devel] [PATCH 1/3] Add blkmirror block driver Federico Simoncelli
2012-02-23 16:14   ` Stefan Hajnoczi
2012-02-23 16:18     ` Stefan Hajnoczi
2012-02-23 16:20       ` Federico Simoncelli
2012-02-23 16:28         ` Stefan Hajnoczi
2012-02-23 16:51           ` Federico Simoncelli
2012-02-23 16:18     ` Federico Simoncelli
2012-02-27  9:23     ` Stefan Hajnoczi
2012-02-27 11:37       ` Paolo Bonzini
2012-02-27 11:42         ` Stefan Hajnoczi
2012-02-27 11:48           ` Paolo Bonzini
2012-02-27 13:09             ` Stefan Hajnoczi
2012-02-27 13:47               ` Paolo Bonzini
2012-02-27 14:49                 ` Stefan Hajnoczi
2012-02-27 14:59                   ` Stefan Hajnoczi
2012-02-27 15:08                     ` Paolo Bonzini
2012-02-22 17:13 ` [Qemu-devel] [PATCH 2/3] Update the " Federico Simoncelli
2012-02-23  7:18   ` Paolo Bonzini
2012-02-23  9:44     ` Federico Simoncelli
2012-02-23  9:45       ` Paolo Bonzini
2012-02-22 17:13 ` [Qemu-devel] [PATCH 3/3] Add nocreate option to snapshot_blkdev Federico Simoncelli
2012-02-23  7:19   ` Paolo Bonzini
2012-02-23  7:38     ` Paolo Bonzini
2012-02-23  9:39       ` Federico Simoncelli
2012-02-23  9:48         ` Paolo Bonzini
2012-02-23 10:19           ` Federico Simoncelli
2012-02-23 11:30             ` Paolo Bonzini
2012-02-23 15:47 ` [Qemu-devel] Live Block Migration using Mirroring Stefan Hajnoczi
2012-02-23 16:10   ` Federico Simoncelli
2012-02-23 16:35 ` Stefan Hajnoczi
2012-02-23 17:06   ` Federico Simoncelli
2012-02-24 11:37 ` [Qemu-devel] [PATCH 1/2] Add blkmirror block driver Federico Simoncelli
2012-02-24 11:37 ` [Qemu-devel] [PATCH 2/2] Add the blockdev-reopen and blockdev-migrate commands Federico Simoncelli
2012-02-24 12:03   ` Kevin Wolf
2012-02-24 12:12     ` Federico Simoncelli
2012-02-24 13:11     ` Paolo Bonzini
2012-02-24 17:04     ` Luiz Capitulino
2012-02-27 14:57     ` Markus Armbruster
2012-02-24 16:49 ` [Qemu-devel] [PATCH 1/2 v2] Add blkmirror block driver Federico Simoncelli
2012-02-24 17:02   ` Eric Blake
2012-02-24 17:15     ` Federico Simoncelli
2012-02-24 18:49     ` Paolo Bonzini
2012-02-24 18:17   ` Luiz Capitulino [this message]
2012-02-27  9:17     ` Federico Simoncelli
2012-02-24 16:49 ` [Qemu-devel] [PATCH 2/2 v2] Add the blockdev-reopen and blockdev-migrate commands Federico Simoncelli
2012-02-24 17:46   ` Eric Blake
2012-02-24 18:57     ` Paolo Bonzini
2012-02-24 19:37       ` Eric Blake
2012-02-24 19:01   ` Luiz Capitulino
2012-02-24 19:40     ` Eric Blake
2012-02-24 20:26       ` Luiz Capitulino
2012-02-24 22:46         ` Eric Blake
2012-02-24 20:32     ` Paolo Bonzini
2012-02-24 20:36       ` Luiz Capitulino
2012-02-24 21:05         ` Paolo Bonzini
2012-02-24 22:30     ` Eric Blake
2012-02-25  6:47       ` Paolo Bonzini
2012-02-27 11:29     ` Federico Simoncelli
2012-02-27 12:12       ` Luiz Capitulino
2012-02-27 12:49         ` Paolo Bonzini
2012-02-27 13:06           ` Luiz Capitulino
2012-02-27 14:39             ` [Qemu-devel] drive transactions (was Re: [PATCH 2/2 v2] Add the blockdev-reopen and blockdev-migrate commands) Paolo Bonzini
2012-02-27 14:46               ` Anthony Liguori
2012-02-27 14:54                 ` Paolo Bonzini
2012-02-27 14:59                   ` Anthony Liguori
2012-02-27 15:03                     ` Paolo Bonzini
2012-02-27 15:06                       ` Anthony Liguori
2012-02-27 15:17                     ` Kevin Wolf
2012-02-27 15:24                       ` Anthony Liguori
2012-02-27 16:51                         ` Paolo Bonzini
2012-02-27 16:58                           ` Anthony Liguori
2012-02-27 17:06                             ` Paolo Bonzini
2012-02-27 16:33               ` Federico Simoncelli
2012-02-27 16:41                 ` Paolo Bonzini
2012-02-27 16:42                 ` Anthony Liguori
2012-02-27 16:50                   ` Federico Simoncelli
2012-02-27 16:53                     ` Anthony Liguori
2012-02-27 16:54                       ` Paolo Bonzini
2012-02-27 16:59                         ` Anthony Liguori
2012-02-27 17:37                   ` Luiz Capitulino
2012-02-28 15:47 ` [Qemu-devel] Live Block Migration using Mirroring Stefan Hajnoczi
2012-02-28 17:15   ` Federico Simoncelli
2012-02-28 17:36     ` Paolo Bonzini
2012-02-28 17:46       ` Federico Simoncelli
2012-02-28 18:02         ` Paolo Bonzini
2012-02-28 18:21           ` Federico Simoncelli
2012-02-28 17:26   ` Paolo Bonzini
2012-02-29 12:28   ` [Qemu-devel] [PATCHv3] Add blkmirror block driver Federico Simoncelli
2012-02-29 13:02     ` Federico Simoncelli
2012-02-29 17:01   ` [Qemu-devel] [PATCHv4] " Federico Simoncelli
2012-03-05 16:59 ` [Qemu-devel] Live Block Migration using Mirroring Marcelo Tosatti
2012-03-05 17:20   ` Eric Blake
2012-03-05 17:44     ` Marcelo Tosatti
2012-03-05 18:05       ` Paolo Bonzini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20120224161722.5be3aede@doriath.home \
    --to=lcapitulino@redhat.com \
    --cc=armbru@redhat.com \
    --cc=fsimonce@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=mtosatti@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).