Re: [Qemu-devel] [PATCH COLO v4 15/15] Implement new driver for block replication

2015-05-14 Thread Gonglei
On 2015/5/8 17:16, Wen Congyang wrote:
 +if (s-mode == REPLICATION_MODE_SECONDARY) {
 +secondary_do_checkpoint(s, errp);
 +
Maybe it should pass local_err here, and add check for it.

Regards,
-Gonglei




[Qemu-devel] [PATCH COLO v4 15/15] Implement new driver for block replication

2015-05-08 Thread Wen Congyang
Signed-off-by: Wen Congyang we...@cn.fujitsu.com
Signed-off-by: zhanghailiang zhang.zhanghaili...@huawei.com
Signed-off-by: Gonglei arei.gong...@huawei.com
---
 block/Makefile.objs |   1 +
 block/replication.c | 512 
 2 files changed, 513 insertions(+)
 create mode 100644 block/replication.c

diff --git a/block/Makefile.objs b/block/Makefile.objs
index 8dd9b9c..8b1c587 100644
--- a/block/Makefile.objs
+++ b/block/Makefile.objs
@@ -22,6 +22,7 @@ block-obj-$(CONFIG_LIBSSH2) += ssh.o
 block-obj-y += accounting.o
 block-obj-y += write-threshold.o
 block-obj-y += backup.o
+block-obj-y += replication.o
 
 common-obj-y += stream.o
 common-obj-y += commit.o
diff --git a/block/replication.c b/block/replication.c
new file mode 100644
index 000..f2a9b2b
--- /dev/null
+++ b/block/replication.c
@@ -0,0 +1,512 @@
+#include qemu-common.h
+#include block/block_int.h
+#include block/blockjob.h
+#include block/nbd.h
+
+typedef struct BDRVReplicationState {
+ReplicationMode mode;
+int replication_state;
+char *export_name;
+NBDExport *exp;
+BlockDriverState *active_disk;
+BlockDriverState *hidden_disk;
+int error;
+
+/*
+ * After failover, secondary qemu should read/write this
+ * bs directly.
+ */
+BlockDriverState *bs;
+} BDRVReplicationState;
+
+enum {
+BLOCK_REPLICATION_NONE, /* block replication is not started */
+BLOCK_REPLICATION_RUNNING,  /* block replication is running */
+BLOCK_REPLICATION_DONE, /* block replication is done(failover) */
+};
+
+#define COMMIT_CLUSTER_BITS 16
+#define COMMIT_CLUSTER_SIZE (1  COMMIT_CLUSTER_BITS)
+#define COMMIT_SECTORS_PER_CLUSTER (COMMIT_CLUSTER_SIZE / BDRV_SECTOR_SIZE)
+
+static void replication_stop(BlockDriverState *bs, bool failover, Error 
**errp);
+
+#define NBD_OPT_EXPORT  export
+#define REPLICATION_MODEmode
+static QemuOptsList replication_runtime_opts = {
+.name = replication,
+.head = QTAILQ_HEAD_INITIALIZER(replication_runtime_opts.head),
+.desc = {
+{
+.name = REPLICATION_MODE,
+.type = QEMU_OPT_STRING,
+},
+{
+.name = NBD_OPT_EXPORT,
+.type = QEMU_OPT_STRING,
+.help = The NBD server name,
+},
+{ /* end of list */ }
+},
+};
+
+static int replication_open(BlockDriverState *bs, QDict *options,
+int flags, Error **errp)
+{
+int ret;
+BDRVReplicationState *s = bs-opaque;;
+Error *local_err = NULL;
+QemuOpts *opts = NULL;
+const char *mode;
+
+ret = -EINVAL;
+opts = qemu_opts_create(replication_runtime_opts, NULL, 0, error_abort);
+qemu_opts_absorb_qdict(opts, options, local_err);
+if (local_err) {
+goto fail;
+}
+
+mode = qemu_opt_get(opts, REPLICATION_MODE);
+if (!mode) {
+error_setg(local_err, Missing the option mode);
+goto fail;
+}
+
+if (!strcmp(mode, primary)) {
+s-mode = REPLICATION_MODE_PRIMARY;
+} else if (!strcmp(mode, secondary)) {
+s-mode = REPLICATION_MODE_SECONDARY;
+} else {
+error_setg(local_err,
+   The option mode's value should be primary or secondary);
+goto fail;
+}
+
+if (s-mode == REPLICATION_MODE_SECONDARY) {
+s-export_name = g_strdup(qemu_opt_get(opts, NBD_OPT_EXPORT));
+if (!s-export_name) {
+error_setg(local_err, Missing the option export);
+goto fail;
+}
+}
+
+return 0;
+
+fail:
+qemu_opts_del(opts);
+/* propagate error */
+if (local_err) {
+error_propagate(errp, local_err);
+}
+return ret;
+}
+
+static void replication_close(BlockDriverState *bs)
+{
+BDRVReplicationState *s = bs-opaque;
+
+if (s-replication_state == BLOCK_REPLICATION_RUNNING) {
+replication_stop(bs, false, NULL);
+}
+
+g_free(s-export_name);
+}
+
+static void replication_refresh_filename(BlockDriverState *bs)
+{
+}
+
+static int64_t replication_getlength(BlockDriverState *bs)
+{
+return bdrv_getlength(bs-file);
+}
+
+static int replication_get_io_status(BDRVReplicationState *s)
+{
+switch (s-replication_state) {
+case BLOCK_REPLICATION_NONE:
+return -EIO;
+case BLOCK_REPLICATION_RUNNING:
+return 0;
+case BLOCK_REPLICATION_DONE:
+return s-mode == REPLICATION_MODE_PRIMARY ? -EIO : 1;
+default:
+abort();
+}
+}
+
+static int replication_return_value(BDRVReplicationState *s, int ret)
+{
+if (s-mode == REPLICATION_MODE_SECONDARY) {
+return ret;
+}
+
+if (ret  0) {
+s-error = ret;
+ret = 0;
+}
+
+return ret;
+}
+
+static coroutine_fn int replication_co_readv(BlockDriverState *bs,
+ int64_t sector_num,
+ int remaining_sectors,
+