From: Federico Simoncelli <fsimonce@redhat.com>
To: qemu-devel@nongnu.org
Cc: kwolf@redhat.com, mtosatti@redhat.com, armbru@redhat.com,
lcapitulino@redhat.com, Federico Simoncelli <fsimonce@redhat.com>,
pbonzini@redhat.com
Subject: [Qemu-devel] [PATCH 1/2 v2] Add blkmirror block driver
Date: Fri, 24 Feb 2012 16:49:03 +0000 [thread overview]
Message-ID: <1330102144-14491-1-git-send-email-fsimonce@redhat.com> (raw)
In-Reply-To: <1329930815-7995-1-git-send-email-fsimonce@redhat.com>
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:");
+
+ /* 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';
+
+ 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) {
+ 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]);
+ 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 '\\'.
+
+
--
1.7.1
next prev parent reply other threads:[~2012-02-24 16:49 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 ` Federico Simoncelli [this message]
2012-02-24 17:02 ` [Qemu-devel] [PATCH 1/2 v2] Add blkmirror block driver Eric Blake
2012-02-24 17:15 ` Federico Simoncelli
2012-02-24 18:49 ` Paolo Bonzini
2012-02-24 18:17 ` Luiz Capitulino
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=1330102144-14491-1-git-send-email-fsimonce@redhat.com \
--to=fsimonce@redhat.com \
--cc=armbru@redhat.com \
--cc=kwolf@redhat.com \
--cc=lcapitulino@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).