From: Paolo Bonzini <pbonzini@redhat.com>
To: qemu-devel@nongnu.org
Cc: kwolf@redhat.com, stefanha@linux.vnet.ibm.com, jcody@redhat.com,
Marcelo Tosatti <mtosatti@redhat.com>,
fsimonce@redhat.com, eblake@redhat.com
Subject: [Qemu-devel] [PATCH 5/6] Add blkmirror block driver
Date: Wed, 29 Feb 2012 14:37:29 +0100 [thread overview]
Message-ID: <1330522650-15357-6-git-send-email-pbonzini@redhat.com> (raw)
In-Reply-To: <1330522650-15357-1-git-send-email-pbonzini@redhat.com>
From: Marcelo Tosatti <mtosatti@redhat.com>
Mirrored writes are used by live block copy.
The blkmirror driver is for internal use only, because it requires
bdrv_append to set up a backing_hd for it. It relies on a quirk
of bdrv_append, which leaves the old image open for writes.
The source is hardcoded as the backing_hd for the destination, so that
copy-on-write functions properly. Since the source is not yet available
at the time blkmirror_open is called, the backing_hd is set later.
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Signed-off-by: Federico Simoncelli <fsimonce@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
This version of the driver is almost entirely rewritten to
use bs->backing_hd and bs->file. This is necessary in order
to share as much code as possible with group snapshots.
Makefile.objs | 2 +-
block/blkmirror.c | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++++
docs/blkmirror.txt | 16 ++++++
3 files changed, 170 insertions(+), 1 deletions(-)
create mode 100644 block/blkmirror.c
create mode 100644 docs/blkmirror.txt
diff --git a/Makefile.objs b/Makefile.objs
index 808de6a..982f44b 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -74,7 +74,7 @@ fsdev-obj-$(CONFIG_VIRTFS) += $(addprefix fsdev/, $(fsdev-nested-y))
# suppress *all* target specific code in case of system emulation, i.e. a
# single QEMU executable should support all CPUs and machines.
-common-obj-y = $(block-obj-y) blockdev.o
+common-obj-y = $(block-obj-y) blockdev.o block/blkmirror.o
common-obj-y += $(net-obj-y)
common-obj-y += $(qobject-obj-y)
common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX))
diff --git a/block/blkmirror.c b/block/blkmirror.c
new file mode 100644
index 0000000..4862364
--- /dev/null
+++ b/block/blkmirror.c
@@ -0,0 +1,153 @@
+/*
+ * 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"
+
+/* Valid blkmirror filenames look like
+ * blkmirror:path/to/image1:path/to/image2 */
+static int blkmirror_open(BlockDriverState *bs, const char *filename, int flags)
+{
+ int ret, n;
+ const char *filename2;
+ char *format;
+ BlockDriver *drv;
+
+ /* Parse the blkmirror: prefix */
+ if (strncmp(filename, "blkmirror:", strlen("blkmirror:"))) {
+ return -EINVAL;
+ }
+ filename += strlen("blkmirror:");
+
+ /* The source image filename is added by bdrv_append. We only need
+ * to parse and open the destination image and format. */
+ n = strcspn(filename, ":");
+ if (filename[n] == 0) {
+ format = NULL;
+ filename2 = filename;
+ } else {
+ format = g_strdup(filename);
+ format[n] = 0;
+ filename2 = format + n + 1;
+ }
+
+ drv = bdrv_find_whitelisted_format(format);
+ if (!drv) {
+ ret = -ENOENT;
+ goto out;
+ }
+
+ bs->file = bdrv_new("");
+ if (bs->file == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ /* If we crash, we cannot assume that the destination is a
+ * valid mirror and we have to start over. So speed up things
+ * by effectively operating on the destination in cache=unsafe
+ * mode.
+ */
+ ret = bdrv_open(bs->file, filename2,
+ flags | BDRV_O_NO_BACKING | BDRV_O_NO_FLUSH | BDRV_O_CACHE_WB,
+ drv);
+ if (ret < 0) {
+ goto out;
+ }
+
+out:
+ g_free(format);
+ return ret;
+}
+
+static void blkmirror_close(BlockDriverState *bs)
+{
+ bs->file->backing_hd = NULL;
+
+ /* backing_hd and file closed by the caller. */
+}
+
+static coroutine_fn int blkmirror_co_flush(BlockDriverState *bs)
+{
+ return bdrv_co_flush(bs->backing_hd);
+}
+
+static int64_t blkmirror_getlength(BlockDriverState *bs)
+{
+ return bdrv_getlength(bs->file);
+}
+
+static int coroutine_fn blkmirror_co_is_allocated(BlockDriverState *bs,
+ int64_t sector_num,
+ int nb_sectors, int *pnum)
+{
+ return bdrv_is_allocated(bs->file, sector_num, nb_sectors, pnum);
+}
+
+static int blkmirror_co_readv(BlockDriverState *bs,
+ int64_t sector_num, int nb_sectors,
+ QEMUIOVector *qiov)
+{
+ return bdrv_co_readv(bs->backing_hd, sector_num, nb_sectors, qiov);
+}
+
+static int blkmirror_co_writev(BlockDriverState *bs,
+ int64_t sector_num, int nb_sectors,
+ QEMUIOVector *qiov)
+{
+ int ret;
+
+ /* bs->backing_hd is set after initialization. */
+ bs->file->backing_hd = bs->backing_hd;
+
+ ret = bdrv_co_writev(bs->backing_hd, sector_num, nb_sectors, qiov);
+ if (ret >= 0) {
+ ret = bdrv_co_writev(bs->file, sector_num, nb_sectors, qiov);
+ }
+
+ return ret;
+}
+
+static coroutine_fn int blkmirror_co_discard(BlockDriverState *bs,
+ int64_t sector_num, int nb_sectors)
+{
+ int ret;
+
+ ret = bdrv_co_discard(bs->backing_hd, sector_num, nb_sectors);
+ if (ret >= 0) {
+ ret = bdrv_co_discard(bs->file, sector_num, nb_sectors);
+ }
+
+ return ret;
+}
+
+
+static BlockDriver bdrv_blkmirror = {
+ .format_name = "blkmirror",
+ .protocol_name = "blkmirror",
+ .instance_size = 0,
+
+ .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_co_is_allocated = blkmirror_co_is_allocated,
+ .bdrv_co_readv = blkmirror_co_readv,
+ .bdrv_co_writev = blkmirror_co_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.7.6
next prev parent reply other threads:[~2012-02-29 13:38 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-02-29 13:37 [Qemu-devel] [PATCH 0/6] Mirrored writes using blockdev-transaction Paolo Bonzini
2012-02-29 13:37 ` [Qemu-devel] [PATCH 1/6] fix format name for backing file Paolo Bonzini
2012-02-29 13:37 ` [Qemu-devel] [PATCH 2/6] qapi: complete implementation of unions Paolo Bonzini
2012-02-29 13:37 ` [Qemu-devel] [PATCH 3/6] rename blockdev-group-snapshot-sync Paolo Bonzini
2012-02-29 14:25 ` Paolo Bonzini
2012-02-29 15:08 ` Luiz Capitulino
2012-02-29 15:23 ` Paolo Bonzini
2012-03-01 13:30 ` Luiz Capitulino
2012-03-01 13:33 ` Paolo Bonzini
2012-02-29 18:41 ` Eric Blake
2012-03-01 10:18 ` Paolo Bonzini
2012-02-29 13:37 ` [Qemu-devel] [PATCH 4/6] add reuse field Paolo Bonzini
2012-02-29 18:50 ` Eric Blake
2012-03-01 10:22 ` Kevin Wolf
2012-02-29 13:37 ` Paolo Bonzini [this message]
2012-02-29 14:37 ` [Qemu-devel] [PATCH 5/6] Add blkmirror block driver Stefan Hajnoczi
2012-02-29 14:56 ` Paolo Bonzini
2012-02-29 19:36 ` Eric Blake
2012-02-29 13:37 ` [Qemu-devel] [PATCH 6/6] add mirroring to blockdev-transaction Paolo Bonzini
2012-02-29 19:47 ` Eric Blake
2012-03-01 6:46 ` 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=1330522650-15357-6-git-send-email-pbonzini@redhat.com \
--to=pbonzini@redhat.com \
--cc=eblake@redhat.com \
--cc=fsimonce@redhat.com \
--cc=jcody@redhat.com \
--cc=kwolf@redhat.com \
--cc=mtosatti@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=stefanha@linux.vnet.ibm.com \
/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).