qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Blue Swirl <blauwirbel@gmail.com>
To: Marcelo Tosatti <mtosatti@redhat.com>
Cc: kwolf@redhat.com, Jes.Sorensen@redhat.com, dlaor@redhat.com,
	qemu-devel@nongnu.org, avi@redhat.com
Subject: Re: [Qemu-devel] [patch 2/7] Add blkmirror block driver
Date: Tue, 24 May 2011 22:03:21 +0300	[thread overview]
Message-ID: <BANLkTimax21i4bQgAtRTKnBLAMXEBZxGKg@mail.gmail.com> (raw)
In-Reply-To: <20110523213410.726580546@amt.cnet>

On Tue, May 24, 2011 at 12:31 AM, Marcelo Tosatti <mtosatti@redhat.com> wrote:
> Mirrored writes are used by live block copy.
>
> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
>
> Index: qemu-block-copy/block/blkmirror.c
> ===================================================================
> --- /dev/null
> +++ qemu-block-copy/block/blkmirror.c
> @@ -0,0 +1,239 @@
> +/*
> + * 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;
> +
> +/* 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;
> +    char *raw, *c;
> +
> +    /* Parse the blkmirror: prefix */
> +    if (strncmp(filename, "blkmirror:", strlen("blkmirror:"))) {
> +        return -EINVAL;
> +    }
> +    filename += strlen("blkmirror:");
> +
> +    /* Parse the raw image filename */
> +    c = strchr(filename, ':');
> +    if (c == NULL) {
> +        return -EINVAL;
> +    }
> +
> +    raw = strdup(filename);
> +    raw[c - filename] = '\0';
> +    ret = bdrv_file_open(&m->bs[0], raw, flags);
> +    free(raw);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +    filename = c + 1;
> +
> +    ret = bdrv_file_open(&m->bs[1], filename, flags);
> +    if (ret < 0) {
> +        bdrv_delete(m->bs[0]);
> +        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 int blkmirror_flush(BlockDriverState *bs)
> +{
> +    BdrvMirrorState *m = bs->opaque;
> +
> +    bdrv_flush(m->bs[0]);
> +    bdrv_flush(m->bs[1]);
> +
> +    return 0;
> +}
> +
> +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);
> +}
> +
> +typedef struct DupAIOCB {
> +    BlockDriverAIOCB common;
> +    int count;
> +
> +    BlockDriverCompletionFunc *cb;
> +    void *opaque;
> +
> +    BlockDriverAIOCB *src_aiocb;
> +    BlockDriverAIOCB *dest_aiocb;
> +
> +    int ret;
> +} DupAIOCB;

Usually all types are defined at the top of the file.

> +
> +static void dup_aio_cancel(BlockDriverAIOCB *blockacb)
> +{
> +    DupAIOCB *acb = container_of(blockacb, DupAIOCB, common);
> +
> +    bdrv_aio_cancel(acb->src_aiocb);
> +    bdrv_aio_cancel(acb->dest_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)
> +{
> +    DupAIOCB *dcb = opaque;
> +
> +    dcb->count--;
> +    assert(dcb->count >= 0);
> +    if (dcb->count == 0) {
> +        if (dcb->ret < 0) {
> +            ret = dcb->ret;
> +        }
> +        dcb->common.cb(dcb->opaque, ret);
> +        qemu_aio_release(dcb);
> +    }
> +    dcb->ret = ret;
> +}
> +
> +static DupAIOCB *dup_aio_get(BlockDriverState *bs,
> +                             BlockDriverCompletionFunc *cb,
> +                             void *opaque)
> +{
> +    DupAIOCB *dcb;
> +
> +    dcb = qemu_aio_get(&dup_aio_pool, bs, cb, opaque);
> +    if (!dcb)
> +        return NULL;

Please use QEMU's scripts/checkpatch.pl.

> +    dcb->count = 2;
> +    dcb->ret = 0;
> +    dcb->opaque = opaque;
> +
> +    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);
> +
> +    dcb->src_aiocb = bdrv_aio_writev(m->bs[0], sector_num, qiov, nb_sectors,
> +                                     &blkmirror_aio_cb, dcb);
> +    if (!dcb->src_aiocb) {
> +        qemu_aio_release(dcb);
> +        return NULL;
> +    }
> +
> +    dcb->dest_aiocb = bdrv_aio_writev(m->bs[1], sector_num, qiov, nb_sectors,
> +                                      &blkmirror_aio_cb, dcb);
> +    if (!dcb->dest_aiocb) {
> +        bdrv_aio_cancel(dcb->src_aiocb);
> +        qemu_aio_release(dcb);
> +        return NULL;
> +    }
> +
> +    return &dcb->common;
> +}
> +
> +static BlockDriverAIOCB *blkmirror_aio_flush(BlockDriverState *bs,
> +                                             BlockDriverCompletionFunc *cb,
> +                                             void *opaque)
> +{
> +    BdrvMirrorState *m = bs->opaque;
> +    DupAIOCB *dcb = dup_aio_get(bs, cb, opaque);
> +
> +    dcb->src_aiocb = bdrv_aio_flush(m->bs[0], &blkmirror_aio_cb, dcb);
> +    if (!dcb->src_aiocb) {
> +        qemu_aio_release(dcb);
> +        return NULL;
> +    }
> +    dcb->dest_aiocb = bdrv_aio_flush(m->bs[1], &blkmirror_aio_cb, dcb);
> +    if (!dcb->dest_aiocb) {
> +        bdrv_aio_cancel(dcb->src_aiocb);
> +        qemu_aio_release(dcb);
> +        return NULL;
> +    }
> +
> +    return &dcb->common;
> +}
> +
> +static int blkmirror_discard(BlockDriverState *bs, int64_t sector_num,
> +                             int nb_sectors)
> +{
> +    BdrvMirrorState *m = bs->opaque;
> +    int ret;
> +
> +    ret = bdrv_discard(m->bs[0], sector_num, nb_sectors);
> +    if (ret < 0) {
> +        return ret;
> +    }
> +
> +    return bdrv_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_flush         = blkmirror_flush,
> +    .bdrv_discard       = blkmirror_discard,
> +
> +    .bdrv_aio_readv     = blkmirror_aio_readv,
> +    .bdrv_aio_writev    = blkmirror_aio_writev,
> +    .bdrv_aio_flush     = blkmirror_aio_flush,
> +};
> +
> +static void bdrv_blkmirror_init(void)
> +{
> +    bdrv_register(&bdrv_blkmirror);
> +}
> +
> +block_init(bdrv_blkmirror_init);
> Index: qemu-block-copy/Makefile.objs
> ===================================================================
> --- qemu-block-copy.orig/Makefile.objs
> +++ qemu-block-copy/Makefile.objs
> @@ -22,7 +22,7 @@ block-nested-y += raw.o cow.o qcow.o vdi
>  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-$(CONFIG_WIN32) += raw-win32.o
>  block-nested-$(CONFIG_POSIX) += raw-posix.o
>  block-nested-$(CONFIG_CURL) += curl.o
>
>
>
>

  reply	other threads:[~2011-05-24 19:03 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-05-23 21:31 [Qemu-devel] [patch 0/7] live block copy (v3) Marcelo Tosatti
2011-05-23 21:31 ` [Qemu-devel] [patch 1/7] add migration_active function Marcelo Tosatti
2011-05-27 17:43   ` Kevin Wolf
2011-05-30  0:53   ` Jes Sorensen
2011-05-23 21:31 ` [Qemu-devel] [patch 2/7] Add blkmirror block driver Marcelo Tosatti
2011-05-24 19:03   ` Blue Swirl [this message]
2011-05-27 17:45   ` Kevin Wolf
2011-05-29  8:45   ` Avi Kivity
2011-05-23 21:31 ` [Qemu-devel] [patch 3/7] Add error messages for live block copy Marcelo Tosatti
2011-05-23 21:31 ` [Qemu-devel] [patch 4/7] Add blkdebug points " Marcelo Tosatti
2011-05-23 21:31 ` [Qemu-devel] [patch 5/7] Add vmstop code " Marcelo Tosatti
2011-05-23 21:31 ` [Qemu-devel] [patch 6/7] QEMU " Marcelo Tosatti
2011-05-24 19:15   ` Blue Swirl
2011-06-03 15:59     ` Marcelo Tosatti
2011-05-29  8:54   ` Avi Kivity
2011-05-31 16:06     ` Marcelo Tosatti
2011-05-31 16:14       ` Avi Kivity
2011-05-31 16:38         ` Marcelo Tosatti
2011-05-31 16:53           ` Avi Kivity
2011-06-03 16:20             ` Marcelo Tosatti
2011-05-23 21:31 ` [Qemu-devel] [patch 7/7] do not allow migration if block copy in progress Marcelo Tosatti
2011-05-29  8:54   ` Avi Kivity
  -- strict thread matches above, loose matches on Subject: below --
2011-06-06 16:55 [Qemu-devel] [patch 0/7] live block copy (v4) Marcelo Tosatti
2011-06-06 16:55 ` [Qemu-devel] [patch 2/7] Add blkmirror block driver Marcelo Tosatti
2011-06-06 21:52   ` malc
2011-06-07 10:25   ` Stefan Hajnoczi

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=BANLkTimax21i4bQgAtRTKnBLAMXEBZxGKg@mail.gmail.com \
    --to=blauwirbel@gmail.com \
    --cc=Jes.Sorensen@redhat.com \
    --cc=avi@redhat.com \
    --cc=dlaor@redhat.com \
    --cc=kwolf@redhat.com \
    --cc=mtosatti@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).