From: Marcelo Tosatti <mtosatti@redhat.com>
To: qemu-devel@nongnu.org
Cc: kwolf@redhat.com, Jes.Sorensen@redhat.com, dlaor@redhat.com,
avi@redhat.com, Marcelo Tosatti <mtosatti@redhat.com>
Subject: [Qemu-devel] [patch 2/7] Add blkmirror block driver
Date: Mon, 23 May 2011 18:31:17 -0300 [thread overview]
Message-ID: <20110523213410.726580546@amt.cnet> (raw)
In-Reply-To: 20110523213115.164535428@amt.cnet
[-- Attachment #1: blkmirror --]
[-- Type: text/plain, Size: 7343 bytes --]
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;
+
+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;
+ 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
next prev parent reply other threads:[~2011-05-23 21:34 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 ` Marcelo Tosatti [this message]
2011-05-24 19:03 ` [Qemu-devel] [patch 2/7] Add blkmirror block driver Blue Swirl
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=20110523213410.726580546@amt.cnet \
--to=mtosatti@redhat.com \
--cc=Jes.Sorensen@redhat.com \
--cc=avi@redhat.com \
--cc=dlaor@redhat.com \
--cc=kwolf@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).