qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v24 00/12] Block replication for continuous checkpoints
@ 2016-07-27  7:01 Changlong Xie
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 01/12] unblock backup operations in backing file Changlong Xie
                   ` (12 more replies)
  0 siblings, 13 replies; 29+ messages in thread
From: Changlong Xie @ 2016-07-27  7:01 UTC (permalink / raw)
  To: qemu devel, qemu block, Stefan Hajnoczi, Fam Zheng, Max Reitz,
	Kevin Wolf, Jeff Cody
  Cc: Paolo Bonzini, John Snow, Eric Blake, Markus Armbruster,
	Dr. David Alan Gilbert, Dong Eddie, Jiang Yunhong, zhanghailiang,
	Gonglei, Wen Congyang, Changlong Xie, Wang Weiwei

Block replication is a very important feature which is used for
continuous checkpoints(for example: COLO).

You can get the detailed information about block replication from here:
http://wiki.qemu.org/Features/BlockReplication

Usage:
Please refer to docs/block-replication.txt

You can get the patch here:
https://github.com//Pating/qemu/tree/block-replication-v24

You can get the patch with framework here:
https://github.com//Pating/qemu/tree/colo_framework_v23

TODO:
1. Continuous block replication. It will be started after basic functions
   are accepted.

Change Log:

V24:
1. Address comments from Max
p9: pass NULL to bdrv_lookup_bs(), and introduce bdrv_is_root_node() to check top_bs
p11: perfect @top-id description, and make it #optional 
p12: "replication" => "Replication", add docs/block-replication.txt
Note: we need bdrv_is_root_node() in p9, so this patchset is based on kevin/qmp-node-name, 
V23:
1. Address comments from Stefan and Max, this series introduce p7/p12
p2. add Copyright for block_backup.h 
p7. support configure --disable-replication
p8. update 2.7 to 2.8
p11. update 2.7 to 2.8, add missing "top-id"
p12. update MAINTAINERS
V22:
1. Rebase to the lastest code
2. modify code adapt to the modification of backup_start & commit_active_start
3. rewrite io_read & io_write for interface changes 
V21:
1. Rebase to the lastest code
2. use bdrv_pwrite_zeroes() and BDRV_SECTOR_BITS for p9
V20 Resend:
1. Resend to avoid bothering qemu-trivial maintainers
2. Address comments from Eric, fix header file issue and add a brief commit message for p7
V20:
1. Rebase to the lastest code
2. Address comments from stefan
p8: 
1. error_setg() with an error message when check_top_bs() fails. 
2. remove bdrv_ref(s->hidden_disk->bs) since commit 5c438bc6
3. use bloc_job_cancel_sync() before active commit
p9: 
1. fix uninitialized 'pattern_buf'
2. introduce mkstemp(3) to fix unique filenames
3. use qemu_vfree() for qemu_blockalign() memory
4. add missing replication_start_all()
5. remove useless pattern for io_write()
V19:
1. Rebase to v2.6.0
2. Address comments from stefan
p3: a new patch that export interfaces for extra serialization
p8: 
1. call replication_stop() before freeing s->top_id
2. check top_bs
3. reopen file readonly in error return paths
4. enable extra serialization between read and COW
p9: try to hanlde SIGABRT
V18:
p6: add local_err in all replication callbacks to prevent "errp == NULL"
p7: add missing qemu_iovec_destroy(xxx)
V17:
1. Rebase to the lastest codes 
p2: refactor backup_do_checkpoint addressed comments from Jeff Cody
p4: fix bugs in "drive_add buddy xxx" hmp commands
p6: add "since: 2.7"
p7: fix bug in replication_close(), add missing "qapi/error.h", add test-replication 
p8: add "since: 2.7"
V16:
1. Rebase to the newest codes
2. Address comments from Stefan & hailiang
p3: we don't need this patch now
p4: add "top-id" parameters for secondary
p6: fix NULL pointer in replication callbacks, remove unnecessary typedefs, 
add doc comments that explain the semantics of Replication
p7: Refactor AioContext for thread-safe, remove unnecessary get_top_bs()
*Note*: I'm working on replication testcase now, will send out in V17
V15:
1. Rebase to the newest codes
2. Fix typos and coding style addresed Eric's comments
3. Address Stefan's comments
   1) Make backup_do_checkpoint public, drop the changes on BlockJobDriver
   2) Update the message and description for [PATCH 4/9]
   3) Make replication_(start/stop/do_checkpoint)_all as global interfaces
   4) Introduce AioContext lock to protect start/stop/do_checkpoint callbacks
   5) Use BdrvChild instead of holding on to BlockDriverState * pointers
4. Clear BDRV_O_INACTIVE for hidden disk's open_flags since commit 09e0c771  
5. Introduce replication_get_error_all to check replication status
6. Remove useless discard interface
V14:
1. Implement auto complete active commit
2. Implement active commit block job for replication.c
3. Address the comments from Stefan, add replication-specific API and data
   structure, also remove old block layer APIs
V13:
1. Rebase to the newest codes
2. Remove redundant marcos and semicolon in replication.c 
3. Fix typos in block-replication.txt
V12:
1. Rebase to the newest codes
2. Use backing reference to replcace 'allow-write-backing-file'
V11:
1. Reopen the backing file when starting blcok replication if it is not
   opened in R/W mode
2. Unblock BLOCK_OP_TYPE_BACKUP_SOURCE and BLOCK_OP_TYPE_BACKUP_TARGET
   when opening backing file
3. Block the top BDS so there is only one block job for the top BDS and
   its backing chain.
V10:
1. Use blockdev-remove-medium and blockdev-insert-medium to replace backing
   reference.
2. Address the comments from Eric Blake
V9:
1. Update the error messages
2. Rebase to the newest qemu
3. Split child add/delete support. These patches are sent in another patchset.
V8:
1. Address Alberto Garcia's comments
V7:
1. Implement adding/removing quorum child. Remove the option non-connect.
2. Simplify the backing refrence option according to Stefan Hajnoczi's suggestion
V6:
1. Rebase to the newest qemu.
V5:
1. Address the comments from Gong Lei
2. Speed the failover up. The secondary vm can take over very quickly even
   if there are too many I/O requests.
V4:
1. Introduce a new driver replication to avoid touch nbd and qcow2.
V3:
1: use error_setg() instead of error_set()
2. Add a new block job API
3. Active disk, hidden disk and nbd target uses the same AioContext
4. Add a testcase to test new hbitmap API
V2:
1. Redesign the secondary qemu(use image-fleecing)
2. Use Error objects to return error message
3. Address the comments from Max Reitz and Eric Blake

Changlong Xie (5):
  Backup: export interfaces for extra serialization
  configure: support replication
  Introduce new APIs to do replication operation
  tests: add unit test case for replication
  MAINTAINERS: add maintainer for replication

Wen Congyang (7):
  unblock backup operations in backing file
  Backup: clear all bitmap when doing block checkpoint
  Link backup into block core
  docs: block replication's description
  auto complete active commit
  Implement new driver for block replication
  support replication driver in blockdev-add

 MAINTAINERS                  |   9 +
 Makefile.objs                |   1 +
 block.c                      |  17 ++
 block/Makefile.objs          |   3 +-
 block/backup.c               |  59 +++-
 block/mirror.c               |  13 +-
 block/replication.c          | 659 +++++++++++++++++++++++++++++++++++++++++++
 blockdev.c                   |   2 +-
 configure                    |  11 +
 docs/block-replication.txt   | 239 ++++++++++++++++
 include/block/block_backup.h |  39 +++
 include/block/block_int.h    |   3 +-
 qapi/block-core.json         |  36 ++-
 qemu-img.c                   |   2 +-
 replication.c                | 107 +++++++
 replication.h                | 174 ++++++++++++
 tests/.gitignore             |   1 +
 tests/Makefile.include       |   4 +
 tests/test-replication.c     | 575 +++++++++++++++++++++++++++++++++++++
 19 files changed, 1937 insertions(+), 17 deletions(-)
 create mode 100644 block/replication.c
 create mode 100644 docs/block-replication.txt
 create mode 100644 include/block/block_backup.h
 create mode 100644 replication.c
 create mode 100644 replication.h
 create mode 100644 tests/test-replication.c

-- 
1.9.3

^ permalink raw reply	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH v24 01/12] unblock backup operations in backing file
  2016-07-27  7:01 [Qemu-devel] [PATCH v24 00/12] Block replication for continuous checkpoints Changlong Xie
@ 2016-07-27  7:01 ` Changlong Xie
  2016-08-04  9:46   ` Stefan Hajnoczi
  2016-08-16 13:13   ` Kashyap Chamarthy
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 02/12] Backup: clear all bitmap when doing block checkpoint Changlong Xie
                   ` (11 subsequent siblings)
  12 siblings, 2 replies; 29+ messages in thread
From: Changlong Xie @ 2016-07-27  7:01 UTC (permalink / raw)
  To: qemu devel, qemu block, Stefan Hajnoczi, Fam Zheng, Max Reitz,
	Kevin Wolf, Jeff Cody
  Cc: Paolo Bonzini, John Snow, Eric Blake, Markus Armbruster,
	Dr. David Alan Gilbert, Dong Eddie, Jiang Yunhong, zhanghailiang,
	Gonglei, Wen Congyang, Changlong Xie, Wang Weiwei

From: Wen Congyang <wency@cn.fujitsu.com>

Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
Signed-off-by: Wang WeiWei <wangww.fnst@cn.fujitsu.com>
---
 block.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/block.c b/block.c
index 9f037db..63e4636 100644
--- a/block.c
+++ b/block.c
@@ -1310,6 +1310,23 @@ void bdrv_set_backing_hd(BlockDriverState *bs, BlockDriverState *backing_hd)
     /* Otherwise we won't be able to commit due to check in bdrv_commit */
     bdrv_op_unblock(backing_hd, BLOCK_OP_TYPE_COMMIT_TARGET,
                     bs->backing_blocker);
+    /*
+     * We do backup in 3 ways:
+     * 1. drive backup
+     *    The target bs is new opened, and the source is top BDS
+     * 2. blockdev backup
+     *    Both the source and the target are top BDSes.
+     * 3. internal backup(used for block replication)
+     *    Both the source and the target are backing file
+     *
+     * In case 1 and 2, neither the source nor the target is the backing file.
+     * In case 3, we will block the top BDS, so there is only one block job
+     * for the top BDS and its backing chain.
+     */
+    bdrv_op_unblock(backing_hd, BLOCK_OP_TYPE_BACKUP_SOURCE,
+                    bs->backing_blocker);
+    bdrv_op_unblock(backing_hd, BLOCK_OP_TYPE_BACKUP_TARGET,
+                    bs->backing_blocker);
 out:
     bdrv_refresh_limits(bs, NULL);
 }
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH v24 02/12] Backup: clear all bitmap when doing block checkpoint
  2016-07-27  7:01 [Qemu-devel] [PATCH v24 00/12] Block replication for continuous checkpoints Changlong Xie
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 01/12] unblock backup operations in backing file Changlong Xie
@ 2016-07-27  7:01 ` Changlong Xie
  2016-08-04  9:47   ` Stefan Hajnoczi
  2016-08-16 12:55   ` Kashyap Chamarthy
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 03/12] Backup: export interfaces for extra serialization Changlong Xie
                   ` (10 subsequent siblings)
  12 siblings, 2 replies; 29+ messages in thread
From: Changlong Xie @ 2016-07-27  7:01 UTC (permalink / raw)
  To: qemu devel, qemu block, Stefan Hajnoczi, Fam Zheng, Max Reitz,
	Kevin Wolf, Jeff Cody
  Cc: Paolo Bonzini, John Snow, Eric Blake, Markus Armbruster,
	Dr. David Alan Gilbert, Dong Eddie, Jiang Yunhong, zhanghailiang,
	Gonglei, Wen Congyang, Changlong Xie, Wang Weiwei

From: Wen Congyang <wency@cn.fujitsu.com>

Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
Signed-off-by: Wang WeiWei <wangww.fnst@cn.fujitsu.com>
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Gonglei <arei.gonglei@huawei.com>
---
 block/backup.c               | 18 ++++++++++++++++++
 include/block/block_backup.h | 25 +++++++++++++++++++++++++
 2 files changed, 43 insertions(+)
 create mode 100644 include/block/block_backup.h

diff --git a/block/backup.c b/block/backup.c
index 2c05323..3bce416 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -17,6 +17,7 @@
 #include "block/block.h"
 #include "block/block_int.h"
 #include "block/blockjob.h"
+#include "block/block_backup.h"
 #include "qapi/error.h"
 #include "qapi/qmp/qerror.h"
 #include "qemu/ratelimit.h"
@@ -253,6 +254,23 @@ static void backup_attached_aio_context(BlockJob *job, AioContext *aio_context)
     blk_set_aio_context(s->target, aio_context);
 }
 
+void backup_do_checkpoint(BlockJob *job, Error **errp)
+{
+    BackupBlockJob *backup_job = container_of(job, BackupBlockJob, common);
+    int64_t len;
+
+    assert(job->driver->job_type == BLOCK_JOB_TYPE_BACKUP);
+
+    if (backup_job->sync_mode != MIRROR_SYNC_MODE_NONE) {
+        error_setg(errp, "The backup job only supports block checkpoint in"
+                   " sync=none mode");
+        return;
+    }
+
+    len = DIV_ROUND_UP(backup_job->common.len, backup_job->cluster_size);
+    bitmap_zero(backup_job->done_bitmap, len);
+}
+
 static const BlockJobDriver backup_job_driver = {
     .instance_size          = sizeof(BackupBlockJob),
     .job_type               = BLOCK_JOB_TYPE_BACKUP,
diff --git a/include/block/block_backup.h b/include/block/block_backup.h
new file mode 100644
index 0000000..157596c
--- /dev/null
+++ b/include/block/block_backup.h
@@ -0,0 +1,25 @@
+/*
+ * QEMU backup
+ *
+ * Copyright (c) 2013 Proxmox Server Solutions
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ * Copyright (c) 2016 Intel Corporation
+ * Copyright (c) 2016 FUJITSU LIMITED
+ *
+ * Authors:
+ *  Dietmar Maurer <dietmar@proxmox.com>
+ *  Changlong Xie <xiecl.fnst@cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef BLOCK_BACKUP_H
+#define BLOCK_BACKUP_H
+
+#include "block/block_int.h"
+
+void backup_do_checkpoint(BlockJob *job, Error **errp);
+
+#endif
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH v24 03/12] Backup: export interfaces for extra serialization
  2016-07-27  7:01 [Qemu-devel] [PATCH v24 00/12] Block replication for continuous checkpoints Changlong Xie
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 01/12] unblock backup operations in backing file Changlong Xie
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 02/12] Backup: clear all bitmap when doing block checkpoint Changlong Xie
@ 2016-07-27  7:01 ` Changlong Xie
  2016-08-04  9:53   ` Stefan Hajnoczi
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 04/12] Link backup into block core Changlong Xie
                   ` (9 subsequent siblings)
  12 siblings, 1 reply; 29+ messages in thread
From: Changlong Xie @ 2016-07-27  7:01 UTC (permalink / raw)
  To: qemu devel, qemu block, Stefan Hajnoczi, Fam Zheng, Max Reitz,
	Kevin Wolf, Jeff Cody
  Cc: Paolo Bonzini, John Snow, Eric Blake, Markus Armbruster,
	Dr. David Alan Gilbert, Dong Eddie, Jiang Yunhong, zhanghailiang,
	Gonglei, Wen Congyang, Changlong Xie, Wang Weiwei

Normal backup(sync='none') workflow:
step 1. NBD peformance I/O write from client to server
   qcow2_co_writev
    bdrv_co_writev
     ...
       bdrv_aligned_pwritev
        notifier_with_return_list_notify -> backup_do_cow
         bdrv_driver_pwritev // write new contents

step 2. drive-backup sync=none
   backup_do_cow
   {
    wait_for_overlapping_requests
    cow_request_begin
    for(; start < end; start++) {
            bdrv_co_readv_no_serialising //read old contents from Secondary disk
            bdrv_co_writev // write old contents to hidden-disk
    }
    cow_request_end
   }

step 3. Then roll back to "step 1" to write new contents to Secondary disk.

And for replication, we must make sure that we only read the old contents from
Secondary disk in order to keep contents consistent.

1) Replication workflow of Secondary
                                                         virtio-blk
                                                              ^
------->  1 NBD                                               |
   ||     server                                       3 replication
   ||        ^                                                ^
   ||        |           backing                 backing      |
   ||  Secondary disk 6<-------- hidden-disk 5 <-------- active-disk 4
   ||        |                         ^
   ||        '-------------------------'
   ||           drive-backup sync=none 2

Hence, we need these interfaces to implement coarse-grained serialization between
COW of Secondary disk and the read operation of replication.

Example codes about how to use them:

*#include "block/block_backup.h"

static coroutine_fn int xxx_co_readv()
{
        CowRequest req;
        BlockJob *job = secondary_disk->bs->job;

        if (job) {
              backup_wait_for_overlapping_requests(job, start, end);
              backup_cow_request_begin(&req, job, start, end);
              ret = bdrv_co_readv();
              backup_cow_request_end(&req);
              goto out;
        }
        ret = bdrv_co_readv();
out:
        return ret;
}

Signed-off-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Wang WeiWei <wangww.fnst@cn.fujitsu.com>
---
 block/backup.c               | 41 ++++++++++++++++++++++++++++++++++-------
 include/block/block_backup.h | 14 ++++++++++++++
 2 files changed, 48 insertions(+), 7 deletions(-)

diff --git a/block/backup.c b/block/backup.c
index 3bce416..919b63a 100644
--- a/block/backup.c
+++ b/block/backup.c
@@ -28,13 +28,6 @@
 #define BACKUP_CLUSTER_SIZE_DEFAULT (1 << 16)
 #define SLICE_TIME 100000000ULL /* ns */
 
-typedef struct CowRequest {
-    int64_t start;
-    int64_t end;
-    QLIST_ENTRY(CowRequest) list;
-    CoQueue wait_queue; /* coroutines blocked on this request */
-} CowRequest;
-
 typedef struct BackupBlockJob {
     BlockJob common;
     BlockBackend *target;
@@ -271,6 +264,40 @@ void backup_do_checkpoint(BlockJob *job, Error **errp)
     bitmap_zero(backup_job->done_bitmap, len);
 }
 
+void backup_wait_for_overlapping_requests(BlockJob *job, int64_t sector_num,
+                                          int nb_sectors)
+{
+    BackupBlockJob *backup_job = container_of(job, BackupBlockJob, common);
+    int64_t sectors_per_cluster = cluster_size_sectors(backup_job);
+    int64_t start, end;
+
+    assert(job->driver->job_type == BLOCK_JOB_TYPE_BACKUP);
+
+    start = sector_num / sectors_per_cluster;
+    end = DIV_ROUND_UP(sector_num + nb_sectors, sectors_per_cluster);
+    wait_for_overlapping_requests(backup_job, start, end);
+}
+
+void backup_cow_request_begin(CowRequest *req, BlockJob *job,
+                              int64_t sector_num,
+                              int nb_sectors)
+{
+    BackupBlockJob *backup_job = container_of(job, BackupBlockJob, common);
+    int64_t sectors_per_cluster = cluster_size_sectors(backup_job);
+    int64_t start, end;
+
+    assert(job->driver->job_type == BLOCK_JOB_TYPE_BACKUP);
+
+    start = sector_num / sectors_per_cluster;
+    end = DIV_ROUND_UP(sector_num + nb_sectors, sectors_per_cluster);
+    cow_request_begin(req, backup_job, start, end);
+}
+
+void backup_cow_request_end(CowRequest *req)
+{
+    cow_request_end(req);
+}
+
 static const BlockJobDriver backup_job_driver = {
     .instance_size          = sizeof(BackupBlockJob),
     .job_type               = BLOCK_JOB_TYPE_BACKUP,
diff --git a/include/block/block_backup.h b/include/block/block_backup.h
index 157596c..8a75947 100644
--- a/include/block/block_backup.h
+++ b/include/block/block_backup.h
@@ -20,6 +20,20 @@
 
 #include "block/block_int.h"
 
+typedef struct CowRequest {
+    int64_t start;
+    int64_t end;
+    QLIST_ENTRY(CowRequest) list;
+    CoQueue wait_queue; /* coroutines blocked on this request */
+} CowRequest;
+
+void backup_wait_for_overlapping_requests(BlockJob *job, int64_t sector_num,
+                                          int nb_sectors);
+void backup_cow_request_begin(CowRequest *req, BlockJob *job,
+                              int64_t sector_num,
+                              int nb_sectors);
+void backup_cow_request_end(CowRequest *req);
+
 void backup_do_checkpoint(BlockJob *job, Error **errp);
 
 #endif
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH v24 04/12] Link backup into block core
  2016-07-27  7:01 [Qemu-devel] [PATCH v24 00/12] Block replication for continuous checkpoints Changlong Xie
                   ` (2 preceding siblings ...)
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 03/12] Backup: export interfaces for extra serialization Changlong Xie
@ 2016-07-27  7:01 ` Changlong Xie
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 05/12] docs: block replication's description Changlong Xie
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 29+ messages in thread
From: Changlong Xie @ 2016-07-27  7:01 UTC (permalink / raw)
  To: qemu devel, qemu block, Stefan Hajnoczi, Fam Zheng, Max Reitz,
	Kevin Wolf, Jeff Cody
  Cc: Paolo Bonzini, John Snow, Eric Blake, Markus Armbruster,
	Dr. David Alan Gilbert, Dong Eddie, Jiang Yunhong, zhanghailiang,
	Gonglei, Wen Congyang, Changlong Xie, Wang Weiwei

From: Wen Congyang <wency@cn.fujitsu.com>

Some programs that add a dependency on it will use
the block layer directly.

Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
Signed-off-by: Wang WeiWei <wangww.fnst@cn.fujitsu.com>
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Gonglei <arei.gonglei@huawei.com>
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Jeff Cody <jcody@redhat.com>
---
 block/Makefile.objs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/block/Makefile.objs b/block/Makefile.objs
index 2593a2f..8a3270b 100644
--- a/block/Makefile.objs
+++ b/block/Makefile.objs
@@ -22,11 +22,11 @@ block-obj-$(CONFIG_ARCHIPELAGO) += archipelago.o
 block-obj-$(CONFIG_LIBSSH2) += ssh.o
 block-obj-y += accounting.o dirty-bitmap.o
 block-obj-y += write-threshold.o
+block-obj-y += backup.o
 
 block-obj-y += crypto.o
 
 common-obj-y += stream.o
-common-obj-y += backup.o
 
 iscsi.o-cflags     := $(LIBISCSI_CFLAGS)
 iscsi.o-libs       := $(LIBISCSI_LIBS)
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH v24 05/12] docs: block replication's description
  2016-07-27  7:01 [Qemu-devel] [PATCH v24 00/12] Block replication for continuous checkpoints Changlong Xie
                   ` (3 preceding siblings ...)
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 04/12] Link backup into block core Changlong Xie
@ 2016-07-27  7:01 ` Changlong Xie
  2016-08-04  9:55   ` Stefan Hajnoczi
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 06/12] auto complete active commit Changlong Xie
                   ` (7 subsequent siblings)
  12 siblings, 1 reply; 29+ messages in thread
From: Changlong Xie @ 2016-07-27  7:01 UTC (permalink / raw)
  To: qemu devel, qemu block, Stefan Hajnoczi, Fam Zheng, Max Reitz,
	Kevin Wolf, Jeff Cody
  Cc: Paolo Bonzini, John Snow, Eric Blake, Markus Armbruster,
	Dr. David Alan Gilbert, Dong Eddie, Jiang Yunhong, zhanghailiang,
	Gonglei, Wen Congyang, Changlong Xie, Wang Weiwei

From: Wen Congyang <wency@cn.fujitsu.com>

Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
Signed-off-by: Wang WeiWei <wangww.fnst@cn.fujitsu.com>
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Gonglei <arei.gonglei@huawei.com>
---
 docs/block-replication.txt | 239 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 239 insertions(+)
 create mode 100644 docs/block-replication.txt

diff --git a/docs/block-replication.txt b/docs/block-replication.txt
new file mode 100644
index 0000000..6bde673
--- /dev/null
+++ b/docs/block-replication.txt
@@ -0,0 +1,239 @@
+Block replication
+----------------------------------------
+Copyright Fujitsu, Corp. 2016
+Copyright (c) 2016 Intel Corporation
+Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+
+This work is licensed under the terms of the GNU GPL, version 2 or later.
+See the COPYING file in the top-level directory.
+
+Block replication is used for continuous checkpoints. It is designed
+for COLO (COarse-grain LOck-stepping) where the Secondary VM is running.
+It can also be applied for FT/HA (Fault-tolerance/High Assurance) scenario,
+where the Secondary VM is not running.
+
+This document gives an overview of block replication's design.
+
+== Background ==
+High availability solutions such as micro checkpoint and COLO will do
+consecutive checkpoints. The VM state of the Primary and Secondary VM is
+identical right after a VM checkpoint, but becomes different as the VM
+executes till the next checkpoint. To support disk contents checkpoint,
+the modified disk contents in the Secondary VM must be buffered, and are
+only dropped at next checkpoint time. To reduce the network transportation
+effort during a vmstate checkpoint, the disk modification operations of
+the Primary disk are asynchronously forwarded to the Secondary node.
+
+== Workflow ==
+The following is the image of block replication workflow:
+
+        +----------------------+            +------------------------+
+        |Primary Write Requests|            |Secondary Write Requests|
+        +----------------------+            +------------------------+
+                  |                                       |
+                  |                                      (4)
+                  |                                       V
+                  |                              /-------------\
+                  |      Copy and Forward        |             |
+                  |---------(1)----------+       | Disk Buffer |
+                  |                      |       |             |
+                  |                     (3)      \-------------/
+                  |                 speculative      ^
+                  |                write through    (2)
+                  |                      |           |
+                  V                      V           |
+           +--------------+           +----------------+
+           | Primary Disk |           | Secondary Disk |
+           +--------------+           +----------------+
+
+    1) Primary write requests will be copied and forwarded to Secondary
+       QEMU.
+    2) Before Primary write requests are written to Secondary disk, the
+       original sector content will be read from Secondary disk and
+       buffered in the Disk buffer, but it will not overwrite the existing
+       sector content (it could be from either "Secondary Write Requests" or
+       previous COW of "Primary Write Requests") in the Disk buffer.
+    3) Primary write requests will be written to Secondary disk.
+    4) Secondary write requests will be buffered in the Disk buffer and it
+       will overwrite the existing sector content in the buffer.
+
+== Architecture ==
+We are going to implement block replication from many basic
+blocks that are already in QEMU.
+
+         virtio-blk       ||
+             ^            ||                            .----------
+             |            ||                            | Secondary
+        1 Quorum          ||                            '----------
+         /      \         ||
+        /        \        ||
+   Primary    2 filter
+     disk         ^                                                             virtio-blk
+                  |                                                                  ^
+                3 NBD  ------->  3 NBD                                               |
+                client    ||     server                                          2 filter
+                          ||        ^                                                ^
+--------.                 ||        |                                                |
+Primary |                 ||  Secondary disk <--------- hidden-disk 5 <--------- active-disk 4
+--------'                 ||        |          backing        ^       backing
+                          ||        |                         |
+                          ||        |                         |
+                          ||        '-------------------------'
+                          ||           drive-backup sync=none 6
+
+1) The disk on the primary is represented by a block device with two
+children, providing replication between a primary disk and the host that
+runs the secondary VM. The read pattern (fifo) for quorum can be extended
+to make the primary always read from the local disk instead of going through
+NBD.
+
+2) The new block filter (the name is replication) will control the block
+replication.
+
+3) The secondary disk receives writes from the primary VM through QEMU's
+embedded NBD server (speculative write-through).
+
+4) The disk on the secondary is represented by a custom block device
+(called active-disk). It should start as an empty disk, and the format
+should support bdrv_make_empty() and backing file.
+
+5) The hidden-disk is created automatically. It buffers the original content
+that is modified by the primary VM. It should also start as an empty disk,
+and the driver supports bdrv_make_empty() and backing file.
+
+6) The drive-backup job (sync=none) is run to allow hidden-disk to buffer
+any state that would otherwise be lost by the speculative write-through
+of the NBD server into the secondary disk. So before block replication,
+the primary disk and secondary disk should contain the same data.
+
+== Failure Handling ==
+There are 7 internal errors when block replication is running:
+1. I/O error on primary disk
+2. Forwarding primary write requests failed
+3. Backup failed
+4. I/O error on secondary disk
+5. I/O error on active disk
+6. Making active disk or hidden disk empty failed
+7. Doing failover failed
+In case 1 and 5, we just report the error to the disk layer. In case 2, 3,
+4 and 6, we just report block replication's error to FT/HA manager (which
+decides when to do a new checkpoint, when to do failover).
+In case 7, if active commit failed, we use replication failover failed state
+in Secondary's write operation (what decides which target to write).
+
+== New block driver interface ==
+We add four block driver interfaces to control block replication:
+a. replication_start_all()
+   Start block replication, called in migration/checkpoint thread.
+   We must call block_replication_start_all() in secondary QEMU before
+   calling block_replication_start_all() in primary QEMU. The caller
+   must hold the I/O mutex lock if it is in migration/checkpoint
+   thread.
+b. replication_do_checkpoint_all()
+   This interface is called after all VM state is transferred to
+   Secondary QEMU. The Disk buffer will be dropped in this interface.
+   The caller must hold the I/O mutex lock if it is in migration/checkpoint
+   thread.
+c. replication_get_error_all()
+   This interface is called to check if error happened in replication.
+   The caller must hold the I/O mutex lock if it is in migration/checkpoint
+   thread.
+d. replication_stop_all()
+   It is called on failover. We will flush the Disk buffer into
+   Secondary Disk and stop block replication. The vm should be stopped
+   before calling it if you use this API to shutdown the guest, or other
+   things except failover. The caller must hold the I/O mutex lock if it is
+   in migration/checkpoint thread.
+
+== Usage ==
+Primary:
+  -drive if=xxx,driver=quorum,read-pattern=fifo,id=colo1,vote-threshold=1,\
+         children.0.file.filename=1.raw,\
+         children.0.driver=raw
+
+  Run qmp command in primary qemu:
+    { 'execute': 'human-monitor-command',
+      'arguments': {
+          'command-line': 'drive_add -n buddy driver=replication,mode=primary,file.driver=nbd,file.host=xxxx,file.port=xxxx,file.export=colo1,node-name=nbd_client1'
+      }
+    }
+    { 'execute': 'x-blockdev-change',
+      'arguments': {
+          'parent': 'colo1',
+          'node': 'nbd_client1'
+      }
+    }
+  Note:
+  1. There should be only one NBD Client for each primary disk.
+  2. host is the secondary physical machine's hostname or IP
+  3. Each disk must have its own export name.
+  4. It is all a single argument to -drive and you should ignore the
+     leading whitespace.
+  5. The qmp command line must be run after running qmp command line in
+     secondary qemu.
+  6. After failover we need remove children.1 (replication driver).
+
+Secondary:
+  -drive if=none,driver=raw,file.filename=1.raw,id=colo1 \
+  -drive if=xxx,id=topxxx,driver=replication,mode=secondary,top-id=topxxx\
+         file.file.filename=active_disk.qcow2,\
+         file.driver=qcow2,\
+         file.backing.file.filename=hidden_disk.qcow2,\
+         file.backing.driver=qcow2,\
+         file.backing.backing=colo1
+
+  Then run qmp command in secondary qemu:
+    { 'execute': 'nbd-server-start',
+      'arguments': {
+          'addr': {
+              'type': 'inet',
+              'data': {
+                  'host': 'xxx',
+                  'port': 'xxx'
+              }
+          }
+      }
+    }
+    { 'execute': 'nbd-server-add',
+      'arguments': {
+          'device': 'colo1',
+          'writable': true
+      }
+    }
+
+  Note:
+  1. The export name in secondary QEMU command line is the secondary
+     disk's id.
+  2. The export name for the same disk must be the same
+  3. The qmp command nbd-server-start and nbd-server-add must be run
+     before running the qmp command migrate on primary QEMU
+  4. Active disk, hidden disk and nbd target's length should be the
+     same.
+  5. It is better to put active disk and hidden disk in ramdisk.
+  6. It is all a single argument to -drive, and you should ignore
+     the leading whitespace.
+
+After Failover:
+Primary:
+  The secondary host is down, so we should run the following qmp command
+  to remove the nbd child from the quorum:
+  { 'execute': 'x-blockdev-change',
+    'arguments': {
+        'parent': 'colo1',
+        'child': 'children.1'
+    }
+  }
+  { 'execute': 'human-monitor-command',
+    'arguments': {
+        'command-line': 'drive_del xxxx'
+    }
+  }
+  Note: there is no qmp command to remove the blockdev now
+
+Secondary:
+  The primary host is down, so we should do the following thing:
+  { 'execute': 'nbd-server-stop' }
+
+TODO:
+1. Continuous block replication
+2. Shared disk
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH v24 06/12] auto complete active commit
  2016-07-27  7:01 [Qemu-devel] [PATCH v24 00/12] Block replication for continuous checkpoints Changlong Xie
                   ` (4 preceding siblings ...)
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 05/12] docs: block replication's description Changlong Xie
@ 2016-07-27  7:01 ` Changlong Xie
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 07/12] configure: support replication Changlong Xie
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 29+ messages in thread
From: Changlong Xie @ 2016-07-27  7:01 UTC (permalink / raw)
  To: qemu devel, qemu block, Stefan Hajnoczi, Fam Zheng, Max Reitz,
	Kevin Wolf, Jeff Cody
  Cc: Paolo Bonzini, John Snow, Eric Blake, Markus Armbruster,
	Dr. David Alan Gilbert, Dong Eddie, Jiang Yunhong, zhanghailiang,
	Gonglei, Wen Congyang, Changlong Xie, Wang Weiwei

From: Wen Congyang <wency@cn.fujitsu.com>

Auto complete mirror job in background to prevent from
blocking synchronously

Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
Signed-off-by: Wang WeiWei <wangww.fnst@cn.fujitsu.com>
---
 block/mirror.c            | 13 +++++++++----
 blockdev.c                |  2 +-
 include/block/block_int.h |  3 ++-
 qemu-img.c                |  2 +-
 4 files changed, 13 insertions(+), 7 deletions(-)

diff --git a/block/mirror.c b/block/mirror.c
index b1e633e..63ed253 100644
--- a/block/mirror.c
+++ b/block/mirror.c
@@ -856,7 +856,8 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
                              BlockCompletionFunc *cb,
                              void *opaque, Error **errp,
                              const BlockJobDriver *driver,
-                             bool is_none_mode, BlockDriverState *base)
+                             bool is_none_mode, BlockDriverState *base,
+                             bool auto_complete)
 {
     MirrorBlockJob *s;
 
@@ -892,6 +893,9 @@ static void mirror_start_job(const char *job_id, BlockDriverState *bs,
     s->granularity = granularity;
     s->buf_size = ROUND_UP(buf_size, granularity);
     s->unmap = unmap;
+    if (auto_complete) {
+        s->should_complete = true;
+    }
 
     s->dirty_bitmap = bdrv_create_dirty_bitmap(bs, granularity, NULL, errp);
     if (!s->dirty_bitmap) {
@@ -930,14 +934,15 @@ void mirror_start(const char *job_id, BlockDriverState *bs,
     mirror_start_job(job_id, bs, target, replaces,
                      speed, granularity, buf_size, backing_mode,
                      on_source_error, on_target_error, unmap, cb, opaque, errp,
-                     &mirror_job_driver, is_none_mode, base);
+                     &mirror_job_driver, is_none_mode, base, false);
 }
 
 void commit_active_start(const char *job_id, BlockDriverState *bs,
                          BlockDriverState *base, int64_t speed,
                          BlockdevOnError on_error,
                          BlockCompletionFunc *cb,
-                         void *opaque, Error **errp)
+                         void *opaque, Error **errp,
+                         bool auto_complete)
 {
     int64_t length, base_length;
     int orig_base_flags;
@@ -978,7 +983,7 @@ void commit_active_start(const char *job_id, BlockDriverState *bs,
     mirror_start_job(job_id, bs, base, NULL, speed, 0, 0,
                      MIRROR_LEAVE_BACKING_CHAIN,
                      on_error, on_error, false, cb, opaque, &local_err,
-                     &commit_active_job_driver, false, base);
+                     &commit_active_job_driver, false, base, auto_complete);
     if (local_err) {
         error_propagate(errp, local_err);
         goto error_restore_flags;
diff --git a/blockdev.c b/blockdev.c
index 2d38537..38d4c89 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -3145,7 +3145,7 @@ void qmp_block_commit(bool has_job_id, const char *job_id, const char *device,
             goto out;
         }
         commit_active_start(has_job_id ? job_id : NULL, bs, base_bs, speed,
-                            on_error, block_job_cb, bs, &local_err);
+                            on_error, block_job_cb, bs, &local_err, false);
     } else {
         commit_start(has_job_id ? job_id : NULL, bs, base_bs, top_bs, speed,
                      on_error, block_job_cb, bs,
diff --git a/include/block/block_int.h b/include/block/block_int.h
index 8054146..0586cee 100644
--- a/include/block/block_int.h
+++ b/include/block/block_int.h
@@ -694,13 +694,14 @@ void commit_start(const char *job_id, BlockDriverState *bs,
  * @cb: Completion function for the job.
  * @opaque: Opaque pointer value passed to @cb.
  * @errp: Error object.
+ * @auto_complete: Auto complete the job.
  *
  */
 void commit_active_start(const char *job_id, BlockDriverState *bs,
                          BlockDriverState *base, int64_t speed,
                          BlockdevOnError on_error,
                          BlockCompletionFunc *cb,
-                         void *opaque, Error **errp);
+                         void *opaque, Error **errp, bool auto_complete);
 /*
  * mirror_start:
  * @job_id: The id of the newly-created job, or %NULL to use the
diff --git a/qemu-img.c b/qemu-img.c
index 2e40e1f..ae204c9 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -921,7 +921,7 @@ static int img_commit(int argc, char **argv)
     };
 
     commit_active_start("commit", bs, base_bs, 0, BLOCKDEV_ON_ERROR_REPORT,
-                        common_block_job_cb, &cbi, &local_err);
+                        common_block_job_cb, &cbi, &local_err, false);
     if (local_err) {
         goto done;
     }
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH v24 07/12] configure: support replication
  2016-07-27  7:01 [Qemu-devel] [PATCH v24 00/12] Block replication for continuous checkpoints Changlong Xie
                   ` (5 preceding siblings ...)
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 06/12] auto complete active commit Changlong Xie
@ 2016-07-27  7:01 ` Changlong Xie
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 08/12] Introduce new APIs to do replication operation Changlong Xie
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 29+ messages in thread
From: Changlong Xie @ 2016-07-27  7:01 UTC (permalink / raw)
  To: qemu devel, qemu block, Stefan Hajnoczi, Fam Zheng, Max Reitz,
	Kevin Wolf, Jeff Cody
  Cc: Paolo Bonzini, John Snow, Eric Blake, Markus Armbruster,
	Dr. David Alan Gilbert, Dong Eddie, Jiang Yunhong, zhanghailiang,
	Gonglei, Wen Congyang, Changlong Xie, Wang Weiwei

configure --(enable/disable)-replication to switch replication
support on/off, and it is on by default.
We later introduce replation support.

Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
Signed-off-by: Wang WeiWei <wangww.fnst@cn.fujitsu.com>
---
 configure | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/configure b/configure
index 5ada56d..6f5d151 100755
--- a/configure
+++ b/configure
@@ -320,6 +320,7 @@ vhdx=""
 numa=""
 tcmalloc="no"
 jemalloc="no"
+replication="yes"
 
 # parse CC options first
 for opt do
@@ -1150,6 +1151,10 @@ for opt do
   ;;
   --enable-jemalloc) jemalloc="yes"
   ;;
+  --disable-replication) replication="no"
+  ;;
+  --enable-replication) replication="yes"
+  ;;
   *)
       echo "ERROR: unknown option $opt"
       echo "Try '$0 --help' for more information"
@@ -1380,6 +1385,7 @@ disabled with --disable-FEATURE, default is enabled if available:
   numa            libnuma support
   tcmalloc        tcmalloc support
   jemalloc        jemalloc support
+  replication     replication support
 
 NOTE: The object files are built at the place where configure is launched
 EOF
@@ -4895,6 +4901,7 @@ echo "NUMA host support $numa"
 echo "tcmalloc support  $tcmalloc"
 echo "jemalloc support  $jemalloc"
 echo "avx2 optimization $avx2_opt"
+echo "replication support $replication"
 
 if test "$sdl_too_old" = "yes"; then
 echo "-> Your SDL version is too old - please upgrade to have SDL support"
@@ -5465,6 +5472,10 @@ if test "$have_rtnetlink" = "yes" ; then
   echo "CONFIG_RTNETLINK=y" >> $config_host_mak
 fi
 
+if test "$replication" = "yes" ; then
+  echo "CONFIG_REPLICATION=y" >> $config_host_mak
+fi
+
 # Hold two types of flag:
 #   CONFIG_THREAD_SETNAME_BYTHREAD  - we've got a way of setting the name on
 #                                     a thread we have a handle to
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH v24 08/12] Introduce new APIs to do replication operation
  2016-07-27  7:01 [Qemu-devel] [PATCH v24 00/12] Block replication for continuous checkpoints Changlong Xie
                   ` (6 preceding siblings ...)
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 07/12] configure: support replication Changlong Xie
@ 2016-07-27  7:01 ` Changlong Xie
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 09/12] Implement new driver for block replication Changlong Xie
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 29+ messages in thread
From: Changlong Xie @ 2016-07-27  7:01 UTC (permalink / raw)
  To: qemu devel, qemu block, Stefan Hajnoczi, Fam Zheng, Max Reitz,
	Kevin Wolf, Jeff Cody
  Cc: Paolo Bonzini, John Snow, Eric Blake, Markus Armbruster,
	Dr. David Alan Gilbert, Dong Eddie, Jiang Yunhong, zhanghailiang,
	Gonglei, Wen Congyang, Changlong Xie, Wang Weiwei

This commit introduces six replication interfaces(for block, network etc).
Firstly we can use replication_(new/remove) to create/destroy replication
instances, then in migration we can use replication_(start/stop/do_checkpoint
/get_error)_all to handle all replication operations. More detail please
refer to replication.h

Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
Signed-off-by: Wang WeiWei <wangww.fnst@cn.fujitsu.com>
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Gonglei <arei.gonglei@huawei.com>
---
 Makefile.objs        |   1 +
 qapi/block-core.json |  13 ++++
 replication.c        | 107 +++++++++++++++++++++++++++++++
 replication.h        | 174 +++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 295 insertions(+)
 create mode 100644 replication.c
 create mode 100644 replication.h

diff --git a/Makefile.objs b/Makefile.objs
index 7f1f0a3..a9d82c3 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -15,6 +15,7 @@ block-obj-$(CONFIG_POSIX) += aio-posix.o
 block-obj-$(CONFIG_WIN32) += aio-win32.o
 block-obj-y += block/
 block-obj-y += qemu-io-cmds.o
+block-obj-$(CONFIG_REPLICATION) += replication.o
 
 block-obj-m = block/
 
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 8c92918..8c250ec 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -2065,6 +2065,19 @@
             '*read-pattern': 'QuorumReadPattern' } }
 
 ##
+# @ReplicationMode
+#
+# An enumeration of replication modes.
+#
+# @primary: Primary mode, the vm's state will be sent to secondary QEMU.
+#
+# @secondary: Secondary mode, receive the vm's state from primary QEMU.
+#
+# Since: 2.8
+##
+{ 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ] }
+
+##
 # @BlockdevOptions
 #
 # Options for creating a block device.  Many options are available for all
diff --git a/replication.c b/replication.c
new file mode 100644
index 0000000..be3a42f
--- /dev/null
+++ b/replication.c
@@ -0,0 +1,107 @@
+/*
+ * Replication filter
+ *
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ * Copyright (c) 2016 Intel Corporation
+ * Copyright (c) 2016 FUJITSU LIMITED
+ *
+ * Author:
+ *   Changlong Xie <xiecl.fnst@cn.fujitsu.com>
+ *
+ * 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 "qemu/osdep.h"
+#include "qapi/error.h"
+#include "replication.h"
+
+static QLIST_HEAD(, ReplicationState) replication_states;
+
+ReplicationState *replication_new(void *opaque, ReplicationOps *ops)
+{
+    ReplicationState *rs;
+
+    assert(ops != NULL);
+    rs = g_new0(ReplicationState, 1);
+    rs->opaque = opaque;
+    rs->ops = ops;
+    QLIST_INSERT_HEAD(&replication_states, rs, node);
+
+    return rs;
+}
+
+void replication_remove(ReplicationState *rs)
+{
+    if (rs) {
+        QLIST_REMOVE(rs, node);
+        g_free(rs);
+    }
+}
+
+/*
+ * The caller of the function MUST make sure vm stopped
+ */
+void replication_start_all(ReplicationMode mode, Error **errp)
+{
+    ReplicationState *rs, *next;
+    Error *local_err = NULL;
+
+    QLIST_FOREACH_SAFE(rs, &replication_states, node, next) {
+        if (rs->ops && rs->ops->start) {
+            rs->ops->start(rs, mode, &local_err);
+        }
+        if (local_err) {
+            error_propagate(errp, local_err);
+            return;
+        }
+    }
+}
+
+void replication_do_checkpoint_all(Error **errp)
+{
+    ReplicationState *rs, *next;
+    Error *local_err = NULL;
+
+    QLIST_FOREACH_SAFE(rs, &replication_states, node, next) {
+        if (rs->ops && rs->ops->checkpoint) {
+            rs->ops->checkpoint(rs, &local_err);
+        }
+        if (local_err) {
+            error_propagate(errp, local_err);
+            return;
+        }
+    }
+}
+
+void replication_get_error_all(Error **errp)
+{
+    ReplicationState *rs, *next;
+    Error *local_err = NULL;
+
+    QLIST_FOREACH_SAFE(rs, &replication_states, node, next) {
+        if (rs->ops && rs->ops->get_error) {
+            rs->ops->get_error(rs, &local_err);
+        }
+        if (local_err) {
+            error_propagate(errp, local_err);
+            return;
+        }
+    }
+}
+
+void replication_stop_all(bool failover, Error **errp)
+{
+    ReplicationState *rs, *next;
+    Error *local_err = NULL;
+
+    QLIST_FOREACH_SAFE(rs, &replication_states, node, next) {
+        if (rs->ops && rs->ops->stop) {
+            rs->ops->stop(rs, failover, &local_err);
+        }
+        if (local_err) {
+            error_propagate(errp, local_err);
+            return;
+        }
+    }
+}
diff --git a/replication.h b/replication.h
new file mode 100644
index 0000000..ece6ca6
--- /dev/null
+++ b/replication.h
@@ -0,0 +1,174 @@
+/*
+ * Replication filter
+ *
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ * Copyright (c) 2016 Intel Corporation
+ * Copyright (c) 2016 FUJITSU LIMITED
+ *
+ * Author:
+ *   Changlong Xie <xiecl.fnst@cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef REPLICATION_H
+#define REPLICATION_H
+
+#include "qemu/queue.h"
+
+typedef struct ReplicationOps ReplicationOps;
+typedef struct ReplicationState ReplicationState;
+
+/**
+ * SECTION:replication.h
+ * @title:Base Replication System
+ * @short_description: interfaces for handling replication
+ *
+ * The Replication Model provides a framework for handling Replication
+ *
+ * <example>
+ *   <title>How to use replication interfaces</title>
+ *   <programlisting>
+ * #include "replication.h"
+ *
+ * typedef struct BDRVReplicationState {
+ *     ReplicationState *rs;
+ * } BDRVReplicationState;
+ *
+ * static void replication_start(ReplicationState *rs, ReplicationMode mode,
+ *                               Error **errp);
+ * static void replication_do_checkpoint(ReplicationState *rs, Error **errp);
+ * static void replication_get_error(ReplicationState *rs, Error **errp);
+ * static void replication_stop(ReplicationState *rs, bool failover,
+ *                              Error **errp);
+ *
+ * static ReplicationOps replication_ops = {
+ *     .start = replication_start,
+ *     .checkpoint = replication_do_checkpoint,
+ *     .get_error = replication_get_error,
+ *     .stop = replication_stop,
+ * }
+ *
+ * static int replication_open(BlockDriverState *bs, QDict *options,
+ *                             int flags, Error **errp)
+ * {
+ *     BDRVReplicationState *s = bs->opaque;
+ *     s->rs = replication_new(bs, &replication_ops);
+ *     return 0;
+ * }
+ *
+ * static void replication_close(BlockDriverState *bs)
+ * {
+ *     BDRVReplicationState *s = bs->opaque;
+ *     replication_remove(s->rs);
+ * }
+ *
+ * BlockDriver bdrv_replication = {
+ *     .format_name                = "replication",
+ *     .protocol_name              = "replication",
+ *     .instance_size              = sizeof(BDRVReplicationState),
+ *
+ *     .bdrv_open                  = replication_open,
+ *     .bdrv_close                 = replication_close,
+ * };
+ *
+ * static void bdrv_replication_init(void)
+ * {
+ *     bdrv_register(&bdrv_replication);
+ * }
+ *
+ * block_init(bdrv_replication_init);
+ *   </programlisting>
+ * </example>
+ *
+ * We create an example about how to use replication interfaces in above.
+ * Then in migration, we can use replication_(start/stop/do_checkpoint/
+ * get_error)_all to handle all replication operations.
+ */
+
+/**
+ * ReplicationState:
+ * @opaque: opaque pointer value passed to this ReplicationState
+ * @ops: replication operation of this ReplicationState
+ * @node: node that we will insert into @replication_states QLIST
+ */
+struct ReplicationState {
+    void *opaque;
+    ReplicationOps *ops;
+    QLIST_ENTRY(ReplicationState) node;
+};
+
+/**
+ * ReplicationOps:
+ * @start: callback to start replication
+ * @stop: callback to stop replication
+ * @checkpoint: callback to do checkpoint
+ * @get_error: callback to check if error occurred during replication
+ */
+struct ReplicationOps {
+    void (*start)(ReplicationState *rs, ReplicationMode mode, Error **errp);
+    void (*stop)(ReplicationState *rs, bool failover, Error **errp);
+    void (*checkpoint)(ReplicationState *rs, Error **errp);
+    void (*get_error)(ReplicationState *rs, Error **errp);
+};
+
+/**
+ * replication_new:
+ * @opaque: opaque pointer value passed to ReplicationState
+ * @ops: replication operation of the new relevant ReplicationState
+ *
+ * Called to create a new ReplicationState instance, and then insert it
+ * into @replication_states QLIST
+ *
+ * Returns: the new ReplicationState instance
+ */
+ReplicationState *replication_new(void *opaque, ReplicationOps *ops);
+
+/**
+ * replication_remove:
+ * @rs: the ReplicationState instance to remove
+ *
+ * Called to remove a ReplicationState instance, and then delete it from
+ * @replication_states QLIST
+ */
+void replication_remove(ReplicationState *rs);
+
+/**
+ * replication_start_all:
+ * @mode: replication mode that could be "primary" or "secondary"
+ * @errp: returns an error if this function fails
+ *
+ * Start replication, called in migration/checkpoint thread
+ *
+ * Note: the caller of the function MUST make sure vm stopped
+ */
+void replication_start_all(ReplicationMode mode, Error **errp);
+
+/**
+ * replication_do_checkpoint_all:
+ * @errp: returns an error if this function fails
+ *
+ * This interface is called after all VM state is transferred to Secondary QEMU
+ */
+void replication_do_checkpoint_all(Error **errp);
+
+/**
+ * replication_get_error_all:
+ * @errp: returns an error if this function fails
+ *
+ * This interface is called to check if error occurred during replication
+ */
+void replication_get_error_all(Error **errp);
+
+/**
+ * replication_stop_all:
+ * @failover: boolean value that indicates if we need do failover or not
+ * @errp: returns an error if this function fails
+ *
+ * It is called on failover. The vm should be stopped before calling it, if you
+ * use this API to shutdown the guest, or other things except failover
+ */
+void replication_stop_all(bool failover, Error **errp);
+
+#endif /* REPLICATION_H */
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH v24 09/12] Implement new driver for block replication
  2016-07-27  7:01 [Qemu-devel] [PATCH v24 00/12] Block replication for continuous checkpoints Changlong Xie
                   ` (7 preceding siblings ...)
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 08/12] Introduce new APIs to do replication operation Changlong Xie
@ 2016-07-27  7:01 ` Changlong Xie
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 10/12] tests: add unit test case for replication Changlong Xie
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 29+ messages in thread
From: Changlong Xie @ 2016-07-27  7:01 UTC (permalink / raw)
  To: qemu devel, qemu block, Stefan Hajnoczi, Fam Zheng, Max Reitz,
	Kevin Wolf, Jeff Cody
  Cc: Paolo Bonzini, John Snow, Eric Blake, Markus Armbruster,
	Dr. David Alan Gilbert, Dong Eddie, Jiang Yunhong, zhanghailiang,
	Gonglei, Wen Congyang, Changlong Xie, Wang Weiwei

From: Wen Congyang <wency@cn.fujitsu.com>

Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
Signed-off-by: Wang WeiWei <wangww.fnst@cn.fujitsu.com>
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Gonglei <arei.gonglei@huawei.com>
---
 block/Makefile.objs |   1 +
 block/replication.c | 659 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 660 insertions(+)
 create mode 100644 block/replication.c

diff --git a/block/Makefile.objs b/block/Makefile.objs
index 8a3270b..55da626 100644
--- a/block/Makefile.objs
+++ b/block/Makefile.objs
@@ -23,6 +23,7 @@ block-obj-$(CONFIG_LIBSSH2) += ssh.o
 block-obj-y += accounting.o dirty-bitmap.o
 block-obj-y += write-threshold.o
 block-obj-y += backup.o
+block-obj-$(CONFIG_REPLICATION) += replication.o
 
 block-obj-y += crypto.o
 
diff --git a/block/replication.c b/block/replication.c
new file mode 100644
index 0000000..1117f02
--- /dev/null
+++ b/block/replication.c
@@ -0,0 +1,659 @@
+/*
+ * Replication Block filter
+ *
+ * Copyright (c) 2016 HUAWEI TECHNOLOGIES CO., LTD.
+ * Copyright (c) 2016 Intel Corporation
+ * Copyright (c) 2016 FUJITSU LIMITED
+ *
+ * Author:
+ *   Wen Congyang <wency@cn.fujitsu.com>
+ *
+ * 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 "qemu/osdep.h"
+#include "qemu-common.h"
+#include "block/nbd.h"
+#include "block/blockjob.h"
+#include "block/block_int.h"
+#include "block/block_backup.h"
+#include "sysemu/block-backend.h"
+#include "qapi/error.h"
+#include "replication.h"
+
+typedef struct BDRVReplicationState {
+    ReplicationMode mode;
+    int replication_state;
+    BdrvChild *active_disk;
+    BdrvChild *hidden_disk;
+    BdrvChild *secondary_disk;
+    char *top_id;
+    ReplicationState *rs;
+    Error *blocker;
+    int orig_hidden_flags;
+    int orig_secondary_flags;
+    int error;
+} BDRVReplicationState;
+
+enum {
+    BLOCK_REPLICATION_NONE,             /* block replication is not started */
+    BLOCK_REPLICATION_RUNNING,          /* block replication is running */
+    BLOCK_REPLICATION_FAILOVER,         /* failover is running in background */
+    BLOCK_REPLICATION_FAILOVER_FAILED,  /* failover failed */
+    BLOCK_REPLICATION_DONE,             /* block replication is done */
+};
+
+static void replication_start(ReplicationState *rs, ReplicationMode mode,
+                              Error **errp);
+static void replication_do_checkpoint(ReplicationState *rs, Error **errp);
+static void replication_get_error(ReplicationState *rs, Error **errp);
+static void replication_stop(ReplicationState *rs, bool failover,
+                             Error **errp);
+
+#define REPLICATION_MODE        "mode"
+#define REPLICATION_TOP_ID      "top-id"
+static QemuOptsList replication_runtime_opts = {
+    .name = "replication",
+    .head = QTAILQ_HEAD_INITIALIZER(replication_runtime_opts.head),
+    .desc = {
+        {
+            .name = REPLICATION_MODE,
+            .type = QEMU_OPT_STRING,
+        },
+        {
+            .name = REPLICATION_TOP_ID,
+            .type = QEMU_OPT_STRING,
+        },
+        { /* end of list */ }
+    },
+};
+
+static ReplicationOps replication_ops = {
+    .start = replication_start,
+    .checkpoint = replication_do_checkpoint,
+    .get_error = replication_get_error,
+    .stop = replication_stop,
+};
+
+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;
+    const char *top_id;
+
+    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;
+        top_id = qemu_opt_get(opts, REPLICATION_TOP_ID);
+        s->top_id = g_strdup(top_id);
+        if (!s->top_id) {
+            error_setg(&local_err, "Missing the option top-id");
+            goto fail;
+        }
+    } else {
+        error_setg(&local_err,
+                   "The option mode's value should be primary or secondary");
+        goto fail;
+    }
+
+    s->rs = replication_new(bs, &replication_ops);
+
+    ret = 0;
+
+fail:
+    qemu_opts_del(opts);
+    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(s->rs, false, NULL);
+    }
+
+    if (s->mode == REPLICATION_MODE_SECONDARY) {
+        g_free(s->top_id);
+    }
+
+    replication_remove(s->rs);
+}
+
+static int64_t replication_getlength(BlockDriverState *bs)
+{
+    return bdrv_getlength(bs->file->bs);
+}
+
+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_FAILOVER:
+        return s->mode == REPLICATION_MODE_PRIMARY ? -EIO : 0;
+    case BLOCK_REPLICATION_FAILOVER_FAILED:
+        return s->mode == REPLICATION_MODE_PRIMARY ? -EIO : 1;
+    case BLOCK_REPLICATION_DONE:
+        /*
+         * active commit job completes, and active disk and secondary_disk
+         * is swapped, so we can operate bs->file directly
+         */
+        return s->mode == REPLICATION_MODE_PRIMARY ? -EIO : 0;
+    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,
+                                             QEMUIOVector *qiov)
+{
+    BDRVReplicationState *s = bs->opaque;
+    BdrvChild *child = s->secondary_disk;
+    BlockJob *job = NULL;
+    CowRequest req;
+    int ret;
+
+    if (s->mode == REPLICATION_MODE_PRIMARY) {
+        /* We only use it to forward primary write requests */
+        return -EIO;
+    }
+
+    ret = replication_get_io_status(s);
+    if (ret < 0) {
+        return ret;
+    }
+
+    if (child && child->bs) {
+        job = child->bs->job;
+    }
+
+    if (job) {
+        backup_wait_for_overlapping_requests(child->bs->job, sector_num,
+                                             remaining_sectors);
+        backup_cow_request_begin(&req, child->bs->job, sector_num,
+                                 remaining_sectors);
+        ret = bdrv_co_readv(bs->file, sector_num, remaining_sectors,
+                            qiov);
+        backup_cow_request_end(&req);
+        goto out;
+    }
+
+    ret = bdrv_co_readv(bs->file, sector_num, remaining_sectors, qiov);
+out:
+    return replication_return_value(s, ret);
+}
+
+static coroutine_fn int replication_co_writev(BlockDriverState *bs,
+                                              int64_t sector_num,
+                                              int remaining_sectors,
+                                              QEMUIOVector *qiov)
+{
+    BDRVReplicationState *s = bs->opaque;
+    QEMUIOVector hd_qiov;
+    uint64_t bytes_done = 0;
+    BdrvChild *top = bs->file;
+    BdrvChild *base = s->secondary_disk;
+    BdrvChild *target;
+    int ret, n;
+
+    ret = replication_get_io_status(s);
+    if (ret < 0) {
+        goto out;
+    }
+
+    if (ret == 0) {
+        ret = bdrv_co_writev(top, sector_num,
+                             remaining_sectors, qiov);
+        return replication_return_value(s, ret);
+    }
+
+    /*
+     * Failover failed, only write to active disk if the sectors
+     * have already been allocated in active disk/hidden disk.
+     */
+    qemu_iovec_init(&hd_qiov, qiov->niov);
+    while (remaining_sectors > 0) {
+        ret = bdrv_is_allocated_above(top->bs, base->bs, sector_num,
+                                      remaining_sectors, &n);
+        if (ret < 0) {
+            goto out1;
+        }
+
+        qemu_iovec_reset(&hd_qiov);
+        qemu_iovec_concat(&hd_qiov, qiov, bytes_done, n * BDRV_SECTOR_SIZE);
+
+        target = ret ? top : base;
+        ret = bdrv_co_writev(target, sector_num, n, &hd_qiov);
+        if (ret < 0) {
+            goto out1;
+        }
+
+        remaining_sectors -= n;
+        sector_num += n;
+        bytes_done += n * BDRV_SECTOR_SIZE;
+    }
+
+out1:
+    qemu_iovec_destroy(&hd_qiov);
+out:
+    return ret;
+}
+
+static bool replication_recurse_is_first_non_filter(BlockDriverState *bs,
+                                                    BlockDriverState *candidate)
+{
+    return bdrv_recurse_is_first_non_filter(bs->file->bs, candidate);
+}
+
+static void secondary_do_checkpoint(BDRVReplicationState *s, Error **errp)
+{
+    Error *local_err = NULL;
+    int ret;
+
+    if (!s->secondary_disk->bs->job) {
+        error_setg(errp, "Backup job was cancelled unexpectedly");
+        return;
+    }
+
+    backup_do_checkpoint(s->secondary_disk->bs->job, &local_err);
+    if (local_err) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    ret = s->active_disk->bs->drv->bdrv_make_empty(s->active_disk->bs);
+    if (ret < 0) {
+        error_setg(errp, "Cannot make active disk empty");
+        return;
+    }
+
+    ret = s->hidden_disk->bs->drv->bdrv_make_empty(s->hidden_disk->bs);
+    if (ret < 0) {
+        error_setg(errp, "Cannot make hidden disk empty");
+        return;
+    }
+}
+
+static void reopen_backing_file(BDRVReplicationState *s, bool writable,
+                                Error **errp)
+{
+    BlockReopenQueue *reopen_queue = NULL;
+    int orig_hidden_flags, orig_secondary_flags;
+    int new_hidden_flags, new_secondary_flags;
+    Error *local_err = NULL;
+
+    if (writable) {
+        orig_hidden_flags = s->orig_hidden_flags =
+                                bdrv_get_flags(s->hidden_disk->bs);
+        new_hidden_flags = (orig_hidden_flags | BDRV_O_RDWR) &
+                                                    ~BDRV_O_INACTIVE;
+        orig_secondary_flags = s->orig_secondary_flags =
+                                bdrv_get_flags(s->secondary_disk->bs);
+        new_secondary_flags = (orig_secondary_flags | BDRV_O_RDWR) &
+                                                     ~BDRV_O_INACTIVE;
+    } else {
+        orig_hidden_flags = (s->orig_hidden_flags | BDRV_O_RDWR) &
+                                                    ~BDRV_O_INACTIVE;
+        new_hidden_flags = s->orig_hidden_flags;
+        orig_secondary_flags = (s->orig_secondary_flags | BDRV_O_RDWR) &
+                                                    ~BDRV_O_INACTIVE;
+        new_secondary_flags = s->orig_secondary_flags;
+    }
+
+    if (orig_hidden_flags != new_hidden_flags) {
+        reopen_queue = bdrv_reopen_queue(reopen_queue, s->hidden_disk->bs, NULL,
+                                         new_hidden_flags);
+    }
+
+    if (!(orig_secondary_flags & BDRV_O_RDWR)) {
+        reopen_queue = bdrv_reopen_queue(reopen_queue, s->secondary_disk->bs,
+                                         NULL, new_secondary_flags);
+    }
+
+    if (reopen_queue) {
+        bdrv_reopen_multiple(reopen_queue, &local_err);
+        error_propagate(errp, local_err);
+    }
+}
+
+static void backup_job_cleanup(BDRVReplicationState *s)
+{
+    BlockDriverState *top_bs;
+
+    top_bs = bdrv_lookup_bs(s->top_id, s->top_id, NULL);
+    if (!top_bs) {
+        return;
+    }
+    bdrv_op_unblock_all(top_bs, s->blocker);
+    error_free(s->blocker);
+    reopen_backing_file(s, false, NULL);
+}
+
+static void backup_job_completed(void *opaque, int ret)
+{
+    BDRVReplicationState *s = opaque;
+
+    if (s->replication_state != BLOCK_REPLICATION_FAILOVER) {
+        /* The backup job is cancelled unexpectedly */
+        s->error = -EIO;
+    }
+
+    backup_job_cleanup(s);
+}
+
+static bool check_top_bs(BlockDriverState *top_bs, BlockDriverState *bs)
+{
+    BdrvChild *child;
+
+    /* The bs itself is the top_bs */
+    if (top_bs == bs) {
+        return true;
+    }
+
+    /* Iterate over top_bs's children */
+    QLIST_FOREACH(child, &top_bs->children, next) {
+        if (child->bs == bs || check_top_bs(child->bs, bs)) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+static void replication_start(ReplicationState *rs, ReplicationMode mode,
+                              Error **errp)
+{
+    BlockDriverState *bs = rs->opaque;
+    BDRVReplicationState *s;
+    BlockDriverState *top_bs;
+    int64_t active_length, hidden_length, disk_length;
+    AioContext *aio_context;
+    Error *local_err = NULL;
+
+    aio_context = bdrv_get_aio_context(bs);
+    aio_context_acquire(aio_context);
+    s = bs->opaque;
+
+    if (s->replication_state != BLOCK_REPLICATION_NONE) {
+        error_setg(errp, "Block replication is running or done");
+        aio_context_release(aio_context);
+        return;
+    }
+
+    if (s->mode != mode) {
+        error_setg(errp, "The parameter mode's value is invalid, needs %d,"
+                   " but got %d", s->mode, mode);
+        aio_context_release(aio_context);
+        return;
+    }
+
+    switch (s->mode) {
+    case REPLICATION_MODE_PRIMARY:
+        break;
+    case REPLICATION_MODE_SECONDARY:
+        s->active_disk = bs->file;
+        if (!s->active_disk || !s->active_disk->bs ||
+                                    !s->active_disk->bs->backing) {
+            error_setg(errp, "Active disk doesn't have backing file");
+            aio_context_release(aio_context);
+            return;
+        }
+
+        s->hidden_disk = s->active_disk->bs->backing;
+        if (!s->hidden_disk->bs || !s->hidden_disk->bs->backing) {
+            error_setg(errp, "Hidden disk doesn't have backing file");
+            aio_context_release(aio_context);
+            return;
+        }
+
+        s->secondary_disk = s->hidden_disk->bs->backing;
+        if (!s->secondary_disk->bs || !bdrv_has_blk(s->secondary_disk->bs)) {
+            error_setg(errp, "The secondary disk doesn't have block backend");
+            aio_context_release(aio_context);
+            return;
+        }
+
+        /* verify the length */
+        active_length = bdrv_getlength(s->active_disk->bs);
+        hidden_length = bdrv_getlength(s->hidden_disk->bs);
+        disk_length = bdrv_getlength(s->secondary_disk->bs);
+        if (active_length < 0 || hidden_length < 0 || disk_length < 0 ||
+            active_length != hidden_length || hidden_length != disk_length) {
+            error_setg(errp, "Active disk, hidden disk, secondary disk's length"
+                       " are not the same");
+            aio_context_release(aio_context);
+            return;
+        }
+
+        if (!s->active_disk->bs->drv->bdrv_make_empty ||
+            !s->hidden_disk->bs->drv->bdrv_make_empty) {
+            error_setg(errp,
+                       "Active disk or hidden disk doesn't support make_empty");
+            aio_context_release(aio_context);
+            return;
+        }
+
+        /* reopen the backing file in r/w mode */
+        reopen_backing_file(s, true, &local_err);
+        if (local_err) {
+            error_propagate(errp, local_err);
+            aio_context_release(aio_context);
+            return;
+        }
+
+        /* start backup job now */
+        error_setg(&s->blocker,
+                   "Block device is in use by internal backup job");
+
+        top_bs = bdrv_lookup_bs(s->top_id, s->top_id, NULL);
+        if (!top_bs || !bdrv_is_root_node(top_bs) ||
+            !check_top_bs(top_bs, bs)) {
+            error_setg(errp, "No top_bs or it is invalid");
+            reopen_backing_file(s, false, NULL);
+            aio_context_release(aio_context);
+            return;
+        }
+        bdrv_op_block_all(top_bs, s->blocker);
+        bdrv_op_unblock(top_bs, BLOCK_OP_TYPE_DATAPLANE, s->blocker);
+
+        backup_start("replication-backup", s->secondary_disk->bs,
+                     s->hidden_disk->bs, 0, MIRROR_SYNC_MODE_NONE, NULL,
+                     BLOCKDEV_ON_ERROR_REPORT, BLOCKDEV_ON_ERROR_REPORT,
+                     backup_job_completed, s, NULL, &local_err);
+        if (local_err) {
+            error_propagate(errp, local_err);
+            backup_job_cleanup(s);
+            aio_context_release(aio_context);
+            return;
+        }
+        break;
+    default:
+        aio_context_release(aio_context);
+        abort();
+    }
+
+    s->replication_state = BLOCK_REPLICATION_RUNNING;
+
+    if (s->mode == REPLICATION_MODE_SECONDARY) {
+        secondary_do_checkpoint(s, errp);
+    }
+
+    s->error = 0;
+    aio_context_release(aio_context);
+}
+
+static void replication_do_checkpoint(ReplicationState *rs, Error **errp)
+{
+    BlockDriverState *bs = rs->opaque;
+    BDRVReplicationState *s;
+    AioContext *aio_context;
+
+    aio_context = bdrv_get_aio_context(bs);
+    aio_context_acquire(aio_context);
+    s = bs->opaque;
+
+    if (s->mode == REPLICATION_MODE_SECONDARY) {
+        secondary_do_checkpoint(s, errp);
+    }
+    aio_context_release(aio_context);
+}
+
+static void replication_get_error(ReplicationState *rs, Error **errp)
+{
+    BlockDriverState *bs = rs->opaque;
+    BDRVReplicationState *s;
+    AioContext *aio_context;
+
+    aio_context = bdrv_get_aio_context(bs);
+    aio_context_acquire(aio_context);
+    s = bs->opaque;
+
+    if (s->replication_state != BLOCK_REPLICATION_RUNNING) {
+        error_setg(errp, "Block replication is not running");
+        aio_context_release(aio_context);
+        return;
+    }
+
+    if (s->error) {
+        error_setg(errp, "I/O error occurred");
+        aio_context_release(aio_context);
+        return;
+    }
+    aio_context_release(aio_context);
+}
+
+static void replication_done(void *opaque, int ret)
+{
+    BlockDriverState *bs = opaque;
+    BDRVReplicationState *s = bs->opaque;
+
+    if (ret == 0) {
+        s->replication_state = BLOCK_REPLICATION_DONE;
+
+        /* refresh top bs's filename */
+        bdrv_refresh_filename(bs);
+        s->active_disk = NULL;
+        s->secondary_disk = NULL;
+        s->hidden_disk = NULL;
+        s->error = 0;
+    } else {
+        s->replication_state = BLOCK_REPLICATION_FAILOVER_FAILED;
+        s->error = -EIO;
+    }
+}
+
+static void replication_stop(ReplicationState *rs, bool failover, Error **errp)
+{
+    BlockDriverState *bs = rs->opaque;
+    BDRVReplicationState *s;
+    AioContext *aio_context;
+
+    aio_context = bdrv_get_aio_context(bs);
+    aio_context_acquire(aio_context);
+    s = bs->opaque;
+
+    if (s->replication_state != BLOCK_REPLICATION_RUNNING) {
+        error_setg(errp, "Block replication is not running");
+        aio_context_release(aio_context);
+        return;
+    }
+
+    switch (s->mode) {
+    case REPLICATION_MODE_PRIMARY:
+        s->replication_state = BLOCK_REPLICATION_DONE;
+        s->error = 0;
+        break;
+    case REPLICATION_MODE_SECONDARY:
+        /*
+         * This BDS will be closed, and the job should be completed
+         * before the BDS is closed, because we will access hidden
+         * disk, secondary disk in backup_job_completed().
+         */
+        if (s->secondary_disk->bs->job) {
+            block_job_cancel_sync(s->secondary_disk->bs->job);
+        }
+
+        if (!failover) {
+            secondary_do_checkpoint(s, errp);
+            s->replication_state = BLOCK_REPLICATION_DONE;
+            aio_context_release(aio_context);
+            return;
+        }
+
+        s->replication_state = BLOCK_REPLICATION_FAILOVER;
+        commit_active_start("replication-commit", s->active_disk->bs,
+                            s->secondary_disk->bs, 0, BLOCKDEV_ON_ERROR_REPORT,
+                            replication_done,
+                            bs, errp, true);
+        break;
+    default:
+        aio_context_release(aio_context);
+        abort();
+    }
+    aio_context_release(aio_context);
+}
+
+BlockDriver bdrv_replication = {
+    .format_name                = "replication",
+    .protocol_name              = "replication",
+    .instance_size              = sizeof(BDRVReplicationState),
+
+    .bdrv_open                  = replication_open,
+    .bdrv_close                 = replication_close,
+
+    .bdrv_getlength             = replication_getlength,
+    .bdrv_co_readv              = replication_co_readv,
+    .bdrv_co_writev             = replication_co_writev,
+
+    .is_filter                  = true,
+    .bdrv_recurse_is_first_non_filter = replication_recurse_is_first_non_filter,
+
+    .has_variable_length        = true,
+};
+
+static void bdrv_replication_init(void)
+{
+    bdrv_register(&bdrv_replication);
+}
+
+block_init(bdrv_replication_init);
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH v24 10/12] tests: add unit test case for replication
  2016-07-27  7:01 [Qemu-devel] [PATCH v24 00/12] Block replication for continuous checkpoints Changlong Xie
                   ` (8 preceding siblings ...)
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 09/12] Implement new driver for block replication Changlong Xie
@ 2016-07-27  7:01 ` Changlong Xie
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 11/12] support replication driver in blockdev-add Changlong Xie
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 29+ messages in thread
From: Changlong Xie @ 2016-07-27  7:01 UTC (permalink / raw)
  To: qemu devel, qemu block, Stefan Hajnoczi, Fam Zheng, Max Reitz,
	Kevin Wolf, Jeff Cody
  Cc: Paolo Bonzini, John Snow, Eric Blake, Markus Armbruster,
	Dr. David Alan Gilbert, Dong Eddie, Jiang Yunhong, zhanghailiang,
	Gonglei, Wen Congyang, Changlong Xie, Wang Weiwei

Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
Signed-off-by: Wang WeiWei <wangww.fnst@cn.fujitsu.com>
---
 tests/.gitignore         |   1 +
 tests/Makefile.include   |   4 +
 tests/test-replication.c | 575 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 580 insertions(+)
 create mode 100644 tests/test-replication.c

diff --git a/tests/.gitignore b/tests/.gitignore
index dbb5263..b4a9cfc 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -63,6 +63,7 @@ test-qmp-introspect.[ch]
 test-qmp-marshal.c
 test-qmp-output-visitor
 test-rcu-list
+test-replication
 test-rfifolock
 test-string-input-visitor
 test-string-output-visitor
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 2010b11..34fc840 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -111,6 +111,7 @@ check-unit-y += tests/test-crypto-xts$(EXESUF)
 check-unit-y += tests/test-crypto-block$(EXESUF)
 gcov-files-test-logging-y = tests/test-logging.c
 check-unit-y += tests/test-logging$(EXESUF)
+check-unit-$(CONFIG_REPLICATION) += tests/test-replication$(EXESUF)
 
 check-block-$(CONFIG_POSIX) += tests/qemu-iotests-quick.sh
 
@@ -472,6 +473,9 @@ tests/test-base64$(EXESUF): tests/test-base64.o \
 
 tests/test-logging$(EXESUF): tests/test-logging.o $(test-util-obj-y)
 
+tests/test-replication$(EXESUF): tests/test-replication.o $(test-util-obj-y) \
+	$(test-block-obj-y)
+
 tests/test-qapi-types.c tests/test-qapi-types.h :\
 $(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py \
diff --git a/tests/test-replication.c b/tests/test-replication.c
new file mode 100644
index 0000000..b63f1ef
--- /dev/null
+++ b/tests/test-replication.c
@@ -0,0 +1,575 @@
+/*
+ * Block replication tests
+ *
+ * Copyright (c) 2016 FUJITSU LIMITED
+ * Author: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
+ *
+ * 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 "qemu/osdep.h"
+
+#include "qapi/error.h"
+#include "replication.h"
+#include "block/block_int.h"
+#include "sysemu/block-backend.h"
+
+#define IMG_SIZE (64 * 1024 * 1024)
+
+/* primary */
+#define P_ID "primary-id"
+static char p_local_disk[] = "/tmp/p_local_disk.XXXXXX";
+
+/* secondary */
+#define S_ID "secondary-id"
+#define S_LOCAL_DISK_ID "secondary-local-disk-id"
+static char s_local_disk[] = "/tmp/s_local_disk.XXXXXX";
+static char s_active_disk[] = "/tmp/s_active_disk.XXXXXX";
+static char s_hidden_disk[] = "/tmp/s_hidden_disk.XXXXXX";
+
+/* FIXME: steal from blockdev.c */
+QemuOptsList qemu_drive_opts = {
+    .name = "drive",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_drive_opts.head),
+    .desc = {
+        { /* end of list */ }
+    },
+};
+
+#define NOT_DONE 0x7fffffff
+
+static void blk_rw_done(void *opaque, int ret)
+{
+    *(int *)opaque = ret;
+}
+
+static void test_blk_read(BlockBackend *blk, long pattern,
+                          int64_t pattern_offset, int64_t pattern_count,
+                          int64_t offset, int64_t count,
+                          bool expect_failed)
+{
+    void *pattern_buf = NULL;
+    QEMUIOVector qiov;
+    void *cmp_buf = NULL;
+    int async_ret = NOT_DONE;
+
+    if (pattern) {
+        cmp_buf = g_malloc(pattern_count);
+        memset(cmp_buf, pattern, pattern_count);
+    }
+
+    pattern_buf = g_malloc(count);
+    if (pattern) {
+        memset(pattern_buf, pattern, count);
+    } else {
+        memset(pattern_buf, 0x00, count);
+    }
+
+    qemu_iovec_init(&qiov, 1);
+    qemu_iovec_add(&qiov, pattern_buf, count);
+
+    blk_aio_preadv(blk, offset, &qiov, 0, blk_rw_done, &async_ret);
+    while (async_ret == NOT_DONE) {
+        main_loop_wait(false);
+    }
+
+    if (expect_failed) {
+        g_assert(async_ret != 0);
+    } else {
+        g_assert(async_ret == 0);
+        if (pattern) {
+            g_assert(memcmp(pattern_buf + pattern_offset,
+                            cmp_buf, pattern_count) <= 0);
+        }
+    }
+
+    g_free(pattern_buf);
+}
+
+static void test_blk_write(BlockBackend *blk, long pattern, int64_t offset,
+                           int64_t count, bool expect_failed)
+{
+    void *pattern_buf = NULL;
+    QEMUIOVector qiov;
+    int async_ret = NOT_DONE;
+
+    pattern_buf = g_malloc(count);
+    if (pattern) {
+        memset(pattern_buf, pattern, count);
+    } else {
+        memset(pattern_buf, 0x00, count);
+    }
+
+    qemu_iovec_init(&qiov, 1);
+    qemu_iovec_add(&qiov, pattern_buf, count);
+
+    blk_aio_pwritev(blk, offset, &qiov, 0, blk_rw_done, &async_ret);
+    while (async_ret == NOT_DONE) {
+        main_loop_wait(false);
+    }
+
+    if (expect_failed) {
+        g_assert(async_ret != 0);
+    } else {
+        g_assert(async_ret == 0);
+    }
+
+    g_free(pattern_buf);
+}
+
+/*
+ * Create a uniquely-named empty temporary file.
+ */
+static void make_temp(char *template)
+{
+    int fd;
+
+    fd = mkstemp(template);
+    g_assert(fd >= 0);
+    close(fd);
+}
+
+static void prepare_imgs(void)
+{
+    Error *local_err = NULL;
+
+    make_temp(p_local_disk);
+    make_temp(s_local_disk);
+    make_temp(s_active_disk);
+    make_temp(s_hidden_disk);
+
+    /* Primary */
+    bdrv_img_create(p_local_disk, "qcow2", NULL, NULL, NULL, IMG_SIZE,
+                    BDRV_O_RDWR, &local_err, true);
+    g_assert(!local_err);
+
+    /* Secondary */
+    bdrv_img_create(s_local_disk, "qcow2", NULL, NULL, NULL, IMG_SIZE,
+                    BDRV_O_RDWR, &local_err, true);
+    g_assert(!local_err);
+    bdrv_img_create(s_active_disk, "qcow2", NULL, NULL, NULL, IMG_SIZE,
+                    BDRV_O_RDWR, &local_err, true);
+    g_assert(!local_err);
+    bdrv_img_create(s_hidden_disk, "qcow2", NULL, NULL, NULL, IMG_SIZE,
+                    BDRV_O_RDWR, &local_err, true);
+    g_assert(!local_err);
+}
+
+static void cleanup_imgs(void)
+{
+    /* Primary */
+    unlink(p_local_disk);
+
+    /* Secondary */
+    unlink(s_local_disk);
+    unlink(s_active_disk);
+    unlink(s_hidden_disk);
+}
+
+static BlockBackend *start_primary(void)
+{
+    BlockBackend *blk;
+    QemuOpts *opts;
+    QDict *qdict;
+    Error *local_err = NULL;
+    char *cmdline;
+
+    cmdline = g_strdup_printf("driver=replication,mode=primary,node-name=xxx,"
+                              "file.driver=qcow2,file.file.filename=%s"
+                              , p_local_disk);
+    opts = qemu_opts_parse_noisily(&qemu_drive_opts, cmdline, false);
+    g_free(cmdline);
+
+    qdict = qemu_opts_to_qdict(opts, NULL);
+    qdict_set_default_str(qdict, BDRV_OPT_CACHE_DIRECT, "off");
+    qdict_set_default_str(qdict, BDRV_OPT_CACHE_NO_FLUSH, "off");
+
+    blk = blk_new_open(NULL, NULL, qdict, BDRV_O_RDWR, &local_err);
+    g_assert(blk);
+    g_assert(!local_err);
+
+    monitor_add_blk(blk, P_ID, &local_err);
+    g_assert(!local_err);
+
+    qemu_opts_del(opts);
+
+    return blk;
+}
+
+static void teardown_primary(void)
+{
+    BlockBackend *blk;
+
+    /* remove P_ID */
+    blk = blk_by_name(P_ID);
+    assert(blk);
+
+    monitor_remove_blk(blk);
+    blk_unref(blk);
+}
+
+static void test_primary_read(void)
+{
+    BlockBackend *blk;
+
+    blk = start_primary();
+
+    /* read from 0 to IMG_SIZE */
+    test_blk_read(blk, 0, 0, IMG_SIZE, 0, IMG_SIZE, true);
+
+    teardown_primary();
+}
+
+static void test_primary_write(void)
+{
+    BlockBackend *blk;
+
+    blk = start_primary();
+
+    /* write from 0 to IMG_SIZE */
+    test_blk_write(blk, 0, 0, IMG_SIZE, true);
+
+    teardown_primary();
+}
+
+static void test_primary_start(void)
+{
+    BlockBackend *blk = NULL;
+    Error *local_err = NULL;
+
+    blk = start_primary();
+
+    replication_start_all(REPLICATION_MODE_PRIMARY, &local_err);
+    g_assert(!local_err);
+
+    /* read from 0 to IMG_SIZE */
+    test_blk_read(blk, 0, 0, IMG_SIZE, 0, IMG_SIZE, true);
+
+    /* write 0x22 from 0 to IMG_SIZE */
+    test_blk_write(blk, 0x22, 0, IMG_SIZE, false);
+
+    teardown_primary();
+}
+
+static void test_primary_stop(void)
+{
+    Error *local_err = NULL;
+    bool failover = true;
+
+    start_primary();
+
+    replication_start_all(REPLICATION_MODE_PRIMARY, &local_err);
+    g_assert(!local_err);
+
+    replication_stop_all(failover, &local_err);
+    g_assert(!local_err);
+
+    teardown_primary();
+}
+
+static void test_primary_do_checkpoint(void)
+{
+    Error *local_err = NULL;
+
+    start_primary();
+
+    replication_start_all(REPLICATION_MODE_PRIMARY, &local_err);
+    g_assert(!local_err);
+
+    replication_do_checkpoint_all(&local_err);
+    g_assert(!local_err);
+
+    teardown_primary();
+}
+
+static void test_primary_get_error(void)
+{
+    Error *local_err = NULL;
+
+    start_primary();
+
+    replication_start_all(REPLICATION_MODE_PRIMARY, &local_err);
+    g_assert(!local_err);
+
+    replication_get_error_all(&local_err);
+    g_assert(!local_err);
+
+    teardown_primary();
+}
+
+static BlockBackend *start_secondary(void)
+{
+    QemuOpts *opts;
+    QDict *qdict;
+    BlockBackend *blk;
+    char *cmdline;
+    Error *local_err = NULL;
+
+    /* add s_local_disk and forge S_LOCAL_DISK_ID */
+    cmdline = g_strdup_printf("file.filename=%s,driver=qcow2", s_local_disk);
+    opts = qemu_opts_parse_noisily(&qemu_drive_opts, cmdline, false);
+    g_free(cmdline);
+
+    qdict = qemu_opts_to_qdict(opts, NULL);
+    qdict_set_default_str(qdict, BDRV_OPT_CACHE_DIRECT, "off");
+    qdict_set_default_str(qdict, BDRV_OPT_CACHE_NO_FLUSH, "off");
+
+    blk = blk_new_open(NULL, NULL, qdict, BDRV_O_RDWR, &local_err);
+    assert(blk);
+    monitor_add_blk(blk, S_LOCAL_DISK_ID, &local_err);
+    g_assert(!local_err);
+
+    /* format s_local_disk with pattern "0x11" */
+    test_blk_write(blk, 0x11, 0, IMG_SIZE, false);
+
+    qemu_opts_del(opts);
+
+    /* add S_(ACTIVE/HIDDEN)_DISK and forge S_ID */
+    cmdline = g_strdup_printf("driver=replication,mode=secondary,top-id=%s,"
+                              "file.driver=qcow2,file.file.filename=%s,"
+                              "file.backing.driver=qcow2,"
+                              "file.backing.file.filename=%s,"
+                              "file.backing.backing=%s"
+                              , S_ID, s_active_disk, s_hidden_disk
+                              , S_LOCAL_DISK_ID);
+    opts = qemu_opts_parse_noisily(&qemu_drive_opts, cmdline, false);
+    g_free(cmdline);
+
+    qdict = qemu_opts_to_qdict(opts, NULL);
+    qdict_set_default_str(qdict, BDRV_OPT_CACHE_DIRECT, "off");
+    qdict_set_default_str(qdict, BDRV_OPT_CACHE_NO_FLUSH, "off");
+
+    blk = blk_new_open(NULL, NULL, qdict, BDRV_O_RDWR, &local_err);
+    assert(blk);
+    monitor_add_blk(blk, S_ID, &local_err);
+    g_assert(!local_err);
+
+    qemu_opts_del(opts);
+
+    return blk;
+}
+
+static void teardown_secondary(void)
+{
+    /* only need to destroy two BBs */
+    BlockBackend *blk;
+
+    /* remove S_LOCAL_DISK_ID */
+    blk = blk_by_name(S_LOCAL_DISK_ID);
+    assert(blk);
+
+    monitor_remove_blk(blk);
+    blk_unref(blk);
+
+    /* remove S_ID */
+    blk = blk_by_name(S_ID);
+    assert(blk);
+
+    monitor_remove_blk(blk);
+    blk_unref(blk);
+}
+
+static void test_secondary_read(void)
+{
+    BlockBackend *blk;
+
+    blk = start_secondary();
+
+    /* read from 0 to IMG_SIZE */
+    test_blk_read(blk, 0, 0, IMG_SIZE, 0, IMG_SIZE, true);
+
+    teardown_secondary();
+}
+
+static void test_secondary_write(void)
+{
+    BlockBackend *blk;
+
+    blk = start_secondary();
+
+    /* write from 0 to IMG_SIZE */
+    test_blk_write(blk, 0, 0, IMG_SIZE, true);
+
+    teardown_secondary();
+}
+
+static void test_secondary_start(void)
+{
+    BlockBackend *top_blk, *local_blk;
+    Error *local_err = NULL;
+    bool failover = true;
+
+    top_blk = start_secondary();
+    replication_start_all(REPLICATION_MODE_SECONDARY, &local_err);
+    g_assert(!local_err);
+
+    /* read from s_local_disk (0, IMG_SIZE) */
+    test_blk_read(top_blk, 0x11, 0, IMG_SIZE, 0, IMG_SIZE, false);
+
+    /* write 0x22 to s_local_disk (IMG_SIZE / 2, IMG_SIZE) */
+    local_blk = blk_by_name(S_LOCAL_DISK_ID);
+    test_blk_write(local_blk, 0x22, IMG_SIZE / 2, IMG_SIZE / 2, false);
+
+    /* replication will backup s_local_disk to s_hidden_disk */
+    test_blk_read(top_blk, 0x11, IMG_SIZE / 2,
+                  IMG_SIZE / 2, 0, IMG_SIZE, false);
+
+    /* write 0x33 to s_active_disk (0, IMG_SIZE / 2) */
+    test_blk_write(top_blk, 0x33, 0, IMG_SIZE / 2, false);
+
+    /* read from s_active_disk (0, IMG_SIZE/2) */
+    test_blk_read(top_blk, 0x33, 0, IMG_SIZE / 2,
+                  0, IMG_SIZE / 2, false);
+
+    /* unblock top_bs */
+    replication_stop_all(failover, &local_err);
+    g_assert(!local_err);
+
+    teardown_secondary();
+}
+
+
+static void test_secondary_stop(void)
+{
+    BlockBackend *top_blk, *local_blk;
+    Error *local_err = NULL;
+    bool failover = true;
+
+    top_blk = start_secondary();
+    replication_start_all(REPLICATION_MODE_SECONDARY, &local_err);
+    g_assert(!local_err);
+
+    /* write 0x22 to s_local_disk (IMG_SIZE / 2, IMG_SIZE) */
+    local_blk = blk_by_name(S_LOCAL_DISK_ID);
+    test_blk_write(local_blk, 0x22, IMG_SIZE / 2, IMG_SIZE / 2, false);
+
+    /* replication will backup s_local_disk to s_hidden_disk */
+    test_blk_read(top_blk, 0x11, IMG_SIZE / 2,
+                  IMG_SIZE / 2, 0, IMG_SIZE, false);
+
+    /* write 0x33 to s_active_disk (0, IMG_SIZE / 2) */
+    test_blk_write(top_blk, 0x33, 0, IMG_SIZE / 2, false);
+
+    /* do active commit */
+    replication_stop_all(failover, &local_err);
+    g_assert(!local_err);
+
+    /* read from s_local_disk (0, IMG_SIZE / 2) */
+    test_blk_read(top_blk, 0x33, 0, IMG_SIZE / 2,
+                  0, IMG_SIZE / 2, false);
+
+
+    /* read from s_local_disk (IMG_SIZE / 2, IMG_SIZE) */
+    test_blk_read(top_blk, 0x22, IMG_SIZE / 2,
+                  IMG_SIZE / 2, 0, IMG_SIZE, false);
+
+    teardown_secondary();
+}
+
+static void test_secondary_do_checkpoint(void)
+{
+    BlockBackend *top_blk, *local_blk;
+    Error *local_err = NULL;
+    bool failover = true;
+
+    top_blk = start_secondary();
+    replication_start_all(REPLICATION_MODE_SECONDARY, &local_err);
+    g_assert(!local_err);
+
+    /* write 0x22 to s_local_disk (IMG_SIZE / 2, IMG_SIZE) */
+    local_blk = blk_by_name(S_LOCAL_DISK_ID);
+    test_blk_write(local_blk, 0x22, IMG_SIZE / 2,
+                   IMG_SIZE / 2, false);
+
+    /* replication will backup s_local_disk to s_hidden_disk */
+    test_blk_read(top_blk, 0x11, IMG_SIZE / 2,
+                  IMG_SIZE / 2, 0, IMG_SIZE, false);
+
+    replication_do_checkpoint_all(&local_err);
+    g_assert(!local_err);
+
+    /* after checkpoint, read pattern 0x22 from s_local_disk */
+    test_blk_read(top_blk, 0x22, IMG_SIZE / 2,
+                  IMG_SIZE / 2, 0, IMG_SIZE, false);
+
+    /* unblock top_bs */
+    replication_stop_all(failover, &local_err);
+    g_assert(!local_err);
+
+    teardown_secondary();
+}
+
+static void test_secondary_get_error(void)
+{
+    Error *local_err = NULL;
+    bool failover = true;
+
+    start_secondary();
+    replication_start_all(REPLICATION_MODE_SECONDARY, &local_err);
+    g_assert(!local_err);
+
+    replication_get_error_all(&local_err);
+    g_assert(!local_err);
+
+    /* unblock top_bs */
+    replication_stop_all(failover, &local_err);
+    g_assert(!local_err);
+
+    teardown_secondary();
+}
+
+static void sigabrt_handler(int signo)
+{
+    cleanup_imgs();
+}
+
+static void setup_sigabrt_handler(void)
+{
+    struct sigaction sigact;
+
+    sigact = (struct sigaction) {
+        .sa_handler = sigabrt_handler,
+        .sa_flags = SA_RESETHAND,
+    };
+    sigemptyset(&sigact.sa_mask);
+    sigaction(SIGABRT, &sigact, NULL);
+}
+
+int main(int argc, char **argv)
+{
+    int ret;
+    qemu_init_main_loop(&error_fatal);
+    bdrv_init();
+
+    g_test_init(&argc, &argv, NULL);
+    setup_sigabrt_handler();
+
+    prepare_imgs();
+
+    /* Primary */
+    g_test_add_func("/replication/primary/read",    test_primary_read);
+    g_test_add_func("/replication/primary/write",   test_primary_write);
+    g_test_add_func("/replication/primary/start",   test_primary_start);
+    g_test_add_func("/replication/primary/stop",    test_primary_stop);
+    g_test_add_func("/replication/primary/do_checkpoint",
+                    test_primary_do_checkpoint);
+    g_test_add_func("/replication/primary/get_error",
+                    test_primary_get_error);
+
+    /* Secondary */
+    g_test_add_func("/replication/secondary/read",  test_secondary_read);
+    g_test_add_func("/replication/secondary/write", test_secondary_write);
+    g_test_add_func("/replication/secondary/start", test_secondary_start);
+    g_test_add_func("/replication/secondary/stop",  test_secondary_stop);
+    g_test_add_func("/replication/secondary/do_checkpoint",
+                    test_secondary_do_checkpoint);
+    g_test_add_func("/replication/secondary/get_error",
+                    test_secondary_get_error);
+
+    ret = g_test_run();
+
+    cleanup_imgs();
+
+    return ret;
+}
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH v24 11/12] support replication driver in blockdev-add
  2016-07-27  7:01 [Qemu-devel] [PATCH v24 00/12] Block replication for continuous checkpoints Changlong Xie
                   ` (9 preceding siblings ...)
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 10/12] tests: add unit test case for replication Changlong Xie
@ 2016-07-27  7:01 ` Changlong Xie
  2016-08-09  9:08   ` Kevin Wolf
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 12/12] MAINTAINERS: add maintainer for replication Changlong Xie
  2016-08-08 14:50 ` [Qemu-devel] [Qemu-block] [PATCH v24 00/12] Block replication for continuous checkpoints Stefan Hajnoczi
  12 siblings, 1 reply; 29+ messages in thread
From: Changlong Xie @ 2016-07-27  7:01 UTC (permalink / raw)
  To: qemu devel, qemu block, Stefan Hajnoczi, Fam Zheng, Max Reitz,
	Kevin Wolf, Jeff Cody
  Cc: Paolo Bonzini, John Snow, Eric Blake, Markus Armbruster,
	Dr. David Alan Gilbert, Dong Eddie, Jiang Yunhong, zhanghailiang,
	Gonglei, Wen Congyang, Changlong Xie, Wang Weiwei

From: Wen Congyang <wency@cn.fujitsu.com>

Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
Signed-off-by: Wang WeiWei <wangww.fnst@cn.fujitsu.com>
Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
Signed-off-by: Gonglei <arei.gonglei@huawei.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
---
 qapi/block-core.json | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/qapi/block-core.json b/qapi/block-core.json
index 8c250ec..aadc75a 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -248,6 +248,7 @@
 #       2.3: 'host_floppy' deprecated
 #       2.5: 'host_floppy' dropped
 #       2.6: 'luks' added
+#       2.8: 'replication' added
 #
 # @backing_file: #optional the name of the backing file (for copy-on-write)
 #
@@ -1671,8 +1672,8 @@
   'data': [ 'archipelago', 'blkdebug', 'blkverify', 'bochs', 'cloop',
             'dmg', 'file', 'ftp', 'ftps', 'host_cdrom', 'host_device',
             'http', 'https', 'luks', 'null-aio', 'null-co', 'parallels',
-            'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'tftp', 'vdi', 'vhdx',
-            'vmdk', 'vpc', 'vvfat' ] }
+            'qcow', 'qcow2', 'qed', 'quorum', 'raw', 'replication', 'tftp',
+            'vdi', 'vhdx', 'vmdk', 'vpc', 'vvfat' ] }
 
 ##
 # @BlockdevOptionsFile
@@ -2078,6 +2079,23 @@
 { 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ] }
 
 ##
+# @BlockdevOptionsReplication
+#
+# Driver specific block device options for replication
+#
+# @mode: the replication mode
+#
+# @top-id: #optional In secondary mode, node name or device ID of the root
+#          node who owns the replication node chain. Ignored in primary mode.
+#
+# Since: 2.8
+##
+{ 'struct': 'BlockdevOptionsReplication',
+  'base': 'BlockdevOptionsGenericFormat',
+  'data': { 'mode': 'ReplicationMode',
+            '*top-id': 'str' } }
+
+##
 # @BlockdevOptions
 #
 # Options for creating a block device.  Many options are available for all
@@ -2142,6 +2160,7 @@
       'quorum':     'BlockdevOptionsQuorum',
       'raw':        'BlockdevOptionsGenericFormat',
 # TODO rbd: Wait for structured options
+      'replication':'BlockdevOptionsReplication',
 # TODO sheepdog: Wait for structured options
 # TODO ssh: Should take InetSocketAddress for 'host'?
       'tftp':       'BlockdevOptionsFile',
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* [Qemu-devel] [PATCH v24 12/12] MAINTAINERS: add maintainer for replication
  2016-07-27  7:01 [Qemu-devel] [PATCH v24 00/12] Block replication for continuous checkpoints Changlong Xie
                   ` (10 preceding siblings ...)
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 11/12] support replication driver in blockdev-add Changlong Xie
@ 2016-07-27  7:01 ` Changlong Xie
  2016-08-08 14:50 ` [Qemu-devel] [Qemu-block] [PATCH v24 00/12] Block replication for continuous checkpoints Stefan Hajnoczi
  12 siblings, 0 replies; 29+ messages in thread
From: Changlong Xie @ 2016-07-27  7:01 UTC (permalink / raw)
  To: qemu devel, qemu block, Stefan Hajnoczi, Fam Zheng, Max Reitz,
	Kevin Wolf, Jeff Cody
  Cc: Paolo Bonzini, John Snow, Eric Blake, Markus Armbruster,
	Dr. David Alan Gilbert, Dong Eddie, Jiang Yunhong, zhanghailiang,
	Gonglei, Wen Congyang, Changlong Xie, Wang Weiwei

As per Stefan's suggestion, add Wen and I as co-maintainers
of replication.

Cc: Stefan Hajnoczi <stefanha@redhat.com>
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
---
 MAINTAINERS | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index 1d0e2c3..25b9438 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1619,6 +1619,15 @@ L: qemu-block@nongnu.org
 S: Supported
 F: tests/image-fuzzer/
 
+Replication
+M: Wen Congyang <wency@cn.fujitsu.com>
+M: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
+S: Supported
+F: replication*
+F: block/replication.c
+F: tests/test-replication.c
+F: docs/block-replication.txt
+
 Build and test automation
 -------------------------
 M: Alex Bennée <alex.bennee@linaro.org>
-- 
1.9.3

^ permalink raw reply related	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH v24 01/12] unblock backup operations in backing file
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 01/12] unblock backup operations in backing file Changlong Xie
@ 2016-08-04  9:46   ` Stefan Hajnoczi
  2016-08-16 13:13   ` Kashyap Chamarthy
  1 sibling, 0 replies; 29+ messages in thread
From: Stefan Hajnoczi @ 2016-08-04  9:46 UTC (permalink / raw)
  To: Changlong Xie
  Cc: qemu devel, qemu block, Fam Zheng, Max Reitz, Kevin Wolf,
	Jeff Cody, Paolo Bonzini, John Snow, Eric Blake,
	Markus Armbruster, Dr. David Alan Gilbert, Dong Eddie,
	Jiang Yunhong, zhanghailiang, Gonglei, Wen Congyang, Wang Weiwei

[-- Attachment #1: Type: text/plain, Size: 419 bytes --]

On Wed, Jul 27, 2016 at 03:01:42PM +0800, Changlong Xie wrote:
> From: Wen Congyang <wency@cn.fujitsu.com>
> 
> Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
> Signed-off-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
> Signed-off-by: Wang WeiWei <wangww.fnst@cn.fujitsu.com>
> ---
>  block.c | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)

Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH v24 02/12] Backup: clear all bitmap when doing block checkpoint
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 02/12] Backup: clear all bitmap when doing block checkpoint Changlong Xie
@ 2016-08-04  9:47   ` Stefan Hajnoczi
  2016-08-16 12:55   ` Kashyap Chamarthy
  1 sibling, 0 replies; 29+ messages in thread
From: Stefan Hajnoczi @ 2016-08-04  9:47 UTC (permalink / raw)
  To: Changlong Xie
  Cc: qemu devel, qemu block, Fam Zheng, Max Reitz, Kevin Wolf,
	Jeff Cody, Paolo Bonzini, John Snow, Eric Blake,
	Markus Armbruster, Dr. David Alan Gilbert, Dong Eddie,
	Jiang Yunhong, zhanghailiang, Gonglei, Wen Congyang, Wang Weiwei

[-- Attachment #1: Type: text/plain, Size: 675 bytes --]

On Wed, Jul 27, 2016 at 03:01:43PM +0800, Changlong Xie wrote:
> From: Wen Congyang <wency@cn.fujitsu.com>
> 
> Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
> Signed-off-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
> Signed-off-by: Wang WeiWei <wangww.fnst@cn.fujitsu.com>
> Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
> Signed-off-by: Gonglei <arei.gonglei@huawei.com>
> ---
>  block/backup.c               | 18 ++++++++++++++++++
>  include/block/block_backup.h | 25 +++++++++++++++++++++++++
>  2 files changed, 43 insertions(+)
>  create mode 100644 include/block/block_backup.h

Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH v24 03/12] Backup: export interfaces for extra serialization
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 03/12] Backup: export interfaces for extra serialization Changlong Xie
@ 2016-08-04  9:53   ` Stefan Hajnoczi
  0 siblings, 0 replies; 29+ messages in thread
From: Stefan Hajnoczi @ 2016-08-04  9:53 UTC (permalink / raw)
  To: Changlong Xie
  Cc: qemu devel, qemu block, Fam Zheng, Max Reitz, Kevin Wolf,
	Jeff Cody, Paolo Bonzini, John Snow, Eric Blake,
	Markus Armbruster, Dr. David Alan Gilbert, Dong Eddie,
	Jiang Yunhong, zhanghailiang, Gonglei, Wen Congyang, Wang Weiwei

[-- Attachment #1: Type: text/plain, Size: 2759 bytes --]

On Wed, Jul 27, 2016 at 03:01:44PM +0800, Changlong Xie wrote:
> Normal backup(sync='none') workflow:
> step 1. NBD peformance I/O write from client to server
>    qcow2_co_writev
>     bdrv_co_writev
>      ...
>        bdrv_aligned_pwritev
>         notifier_with_return_list_notify -> backup_do_cow
>          bdrv_driver_pwritev // write new contents
> 
> step 2. drive-backup sync=none
>    backup_do_cow
>    {
>     wait_for_overlapping_requests
>     cow_request_begin
>     for(; start < end; start++) {
>             bdrv_co_readv_no_serialising //read old contents from Secondary disk
>             bdrv_co_writev // write old contents to hidden-disk
>     }
>     cow_request_end
>    }
> 
> step 3. Then roll back to "step 1" to write new contents to Secondary disk.
> 
> And for replication, we must make sure that we only read the old contents from
> Secondary disk in order to keep contents consistent.
> 
> 1) Replication workflow of Secondary
>                                                          virtio-blk
>                                                               ^
> ------->  1 NBD                                               |
>    ||     server                                       3 replication
>    ||        ^                                                ^
>    ||        |           backing                 backing      |
>    ||  Secondary disk 6<-------- hidden-disk 5 <-------- active-disk 4
>    ||        |                         ^
>    ||        '-------------------------'
>    ||           drive-backup sync=none 2
> 
> Hence, we need these interfaces to implement coarse-grained serialization between
> COW of Secondary disk and the read operation of replication.
> 
> Example codes about how to use them:
> 
> *#include "block/block_backup.h"
> 
> static coroutine_fn int xxx_co_readv()
> {
>         CowRequest req;
>         BlockJob *job = secondary_disk->bs->job;
> 
>         if (job) {
>               backup_wait_for_overlapping_requests(job, start, end);
>               backup_cow_request_begin(&req, job, start, end);
>               ret = bdrv_co_readv();
>               backup_cow_request_end(&req);
>               goto out;
>         }
>         ret = bdrv_co_readv();
> out:
>         return ret;
> }
> 
> Signed-off-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
> Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
> Signed-off-by: Wang WeiWei <wangww.fnst@cn.fujitsu.com>
> ---
>  block/backup.c               | 41 ++++++++++++++++++++++++++++++++++-------
>  include/block/block_backup.h | 14 ++++++++++++++
>  2 files changed, 48 insertions(+), 7 deletions(-)

Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH v24 05/12] docs: block replication's description
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 05/12] docs: block replication's description Changlong Xie
@ 2016-08-04  9:55   ` Stefan Hajnoczi
  0 siblings, 0 replies; 29+ messages in thread
From: Stefan Hajnoczi @ 2016-08-04  9:55 UTC (permalink / raw)
  To: Changlong Xie
  Cc: qemu devel, qemu block, Fam Zheng, Max Reitz, Kevin Wolf,
	Jeff Cody, Paolo Bonzini, John Snow, Eric Blake,
	Markus Armbruster, Dr. David Alan Gilbert, Dong Eddie,
	Jiang Yunhong, zhanghailiang, Gonglei, Wen Congyang, Wang Weiwei

[-- Attachment #1: Type: text/plain, Size: 635 bytes --]

On Wed, Jul 27, 2016 at 03:01:46PM +0800, Changlong Xie wrote:
> From: Wen Congyang <wency@cn.fujitsu.com>
> 
> Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
> Signed-off-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
> Signed-off-by: Wang WeiWei <wangww.fnst@cn.fujitsu.com>
> Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
> Signed-off-by: Gonglei <arei.gonglei@huawei.com>
> ---
>  docs/block-replication.txt | 239 +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 239 insertions(+)
>  create mode 100644 docs/block-replication.txt

Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [Qemu-block] [PATCH v24 00/12] Block replication for continuous checkpoints
  2016-07-27  7:01 [Qemu-devel] [PATCH v24 00/12] Block replication for continuous checkpoints Changlong Xie
                   ` (11 preceding siblings ...)
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 12/12] MAINTAINERS: add maintainer for replication Changlong Xie
@ 2016-08-08 14:50 ` Stefan Hajnoczi
  2016-09-12 14:11   ` Stefan Hajnoczi
  12 siblings, 1 reply; 29+ messages in thread
From: Stefan Hajnoczi @ 2016-08-08 14:50 UTC (permalink / raw)
  To: Changlong Xie
  Cc: qemu devel, qemu block, Stefan Hajnoczi, Fam Zheng, Max Reitz,
	Kevin Wolf, Jeff Cody, Wang Weiwei, zhanghailiang, Wen Congyang,
	Jiang Yunhong, Dong Eddie, Markus Armbruster,
	Dr. David Alan Gilbert, Gonglei, Paolo Bonzini

[-- Attachment #1: Type: text/plain, Size: 8153 bytes --]

On Wed, Jul 27, 2016 at 03:01:41PM +0800, Changlong Xie wrote:
> Block replication is a very important feature which is used for
> continuous checkpoints(for example: COLO).
> 
> You can get the detailed information about block replication from here:
> http://wiki.qemu.org/Features/BlockReplication
> 
> Usage:
> Please refer to docs/block-replication.txt
> 
> You can get the patch here:
> https://github.com//Pating/qemu/tree/block-replication-v24
> 
> You can get the patch with framework here:
> https://github.com//Pating/qemu/tree/colo_framework_v23
> 
> TODO:
> 1. Continuous block replication. It will be started after basic functions
>    are accepted.
> 
> Change Log:
> 
> V24:
> 1. Address comments from Max
> p9: pass NULL to bdrv_lookup_bs(), and introduce bdrv_is_root_node() to check top_bs
> p11: perfect @top-id description, and make it #optional 
> p12: "replication" => "Replication", add docs/block-replication.txt
> Note: we need bdrv_is_root_node() in p9, so this patchset is based on kevin/qmp-node-name, 
> V23:
> 1. Address comments from Stefan and Max, this series introduce p7/p12
> p2. add Copyright for block_backup.h 
> p7. support configure --disable-replication
> p8. update 2.7 to 2.8
> p11. update 2.7 to 2.8, add missing "top-id"
> p12. update MAINTAINERS
> V22:
> 1. Rebase to the lastest code
> 2. modify code adapt to the modification of backup_start & commit_active_start
> 3. rewrite io_read & io_write for interface changes 
> V21:
> 1. Rebase to the lastest code
> 2. use bdrv_pwrite_zeroes() and BDRV_SECTOR_BITS for p9
> V20 Resend:
> 1. Resend to avoid bothering qemu-trivial maintainers
> 2. Address comments from Eric, fix header file issue and add a brief commit message for p7
> V20:
> 1. Rebase to the lastest code
> 2. Address comments from stefan
> p8: 
> 1. error_setg() with an error message when check_top_bs() fails. 
> 2. remove bdrv_ref(s->hidden_disk->bs) since commit 5c438bc6
> 3. use bloc_job_cancel_sync() before active commit
> p9: 
> 1. fix uninitialized 'pattern_buf'
> 2. introduce mkstemp(3) to fix unique filenames
> 3. use qemu_vfree() for qemu_blockalign() memory
> 4. add missing replication_start_all()
> 5. remove useless pattern for io_write()
> V19:
> 1. Rebase to v2.6.0
> 2. Address comments from stefan
> p3: a new patch that export interfaces for extra serialization
> p8: 
> 1. call replication_stop() before freeing s->top_id
> 2. check top_bs
> 3. reopen file readonly in error return paths
> 4. enable extra serialization between read and COW
> p9: try to hanlde SIGABRT
> V18:
> p6: add local_err in all replication callbacks to prevent "errp == NULL"
> p7: add missing qemu_iovec_destroy(xxx)
> V17:
> 1. Rebase to the lastest codes 
> p2: refactor backup_do_checkpoint addressed comments from Jeff Cody
> p4: fix bugs in "drive_add buddy xxx" hmp commands
> p6: add "since: 2.7"
> p7: fix bug in replication_close(), add missing "qapi/error.h", add test-replication 
> p8: add "since: 2.7"
> V16:
> 1. Rebase to the newest codes
> 2. Address comments from Stefan & hailiang
> p3: we don't need this patch now
> p4: add "top-id" parameters for secondary
> p6: fix NULL pointer in replication callbacks, remove unnecessary typedefs, 
> add doc comments that explain the semantics of Replication
> p7: Refactor AioContext for thread-safe, remove unnecessary get_top_bs()
> *Note*: I'm working on replication testcase now, will send out in V17
> V15:
> 1. Rebase to the newest codes
> 2. Fix typos and coding style addresed Eric's comments
> 3. Address Stefan's comments
>    1) Make backup_do_checkpoint public, drop the changes on BlockJobDriver
>    2) Update the message and description for [PATCH 4/9]
>    3) Make replication_(start/stop/do_checkpoint)_all as global interfaces
>    4) Introduce AioContext lock to protect start/stop/do_checkpoint callbacks
>    5) Use BdrvChild instead of holding on to BlockDriverState * pointers
> 4. Clear BDRV_O_INACTIVE for hidden disk's open_flags since commit 09e0c771  
> 5. Introduce replication_get_error_all to check replication status
> 6. Remove useless discard interface
> V14:
> 1. Implement auto complete active commit
> 2. Implement active commit block job for replication.c
> 3. Address the comments from Stefan, add replication-specific API and data
>    structure, also remove old block layer APIs
> V13:
> 1. Rebase to the newest codes
> 2. Remove redundant marcos and semicolon in replication.c 
> 3. Fix typos in block-replication.txt
> V12:
> 1. Rebase to the newest codes
> 2. Use backing reference to replcace 'allow-write-backing-file'
> V11:
> 1. Reopen the backing file when starting blcok replication if it is not
>    opened in R/W mode
> 2. Unblock BLOCK_OP_TYPE_BACKUP_SOURCE and BLOCK_OP_TYPE_BACKUP_TARGET
>    when opening backing file
> 3. Block the top BDS so there is only one block job for the top BDS and
>    its backing chain.
> V10:
> 1. Use blockdev-remove-medium and blockdev-insert-medium to replace backing
>    reference.
> 2. Address the comments from Eric Blake
> V9:
> 1. Update the error messages
> 2. Rebase to the newest qemu
> 3. Split child add/delete support. These patches are sent in another patchset.
> V8:
> 1. Address Alberto Garcia's comments
> V7:
> 1. Implement adding/removing quorum child. Remove the option non-connect.
> 2. Simplify the backing refrence option according to Stefan Hajnoczi's suggestion
> V6:
> 1. Rebase to the newest qemu.
> V5:
> 1. Address the comments from Gong Lei
> 2. Speed the failover up. The secondary vm can take over very quickly even
>    if there are too many I/O requests.
> V4:
> 1. Introduce a new driver replication to avoid touch nbd and qcow2.
> V3:
> 1: use error_setg() instead of error_set()
> 2. Add a new block job API
> 3. Active disk, hidden disk and nbd target uses the same AioContext
> 4. Add a testcase to test new hbitmap API
> V2:
> 1. Redesign the secondary qemu(use image-fleecing)
> 2. Use Error objects to return error message
> 3. Address the comments from Max Reitz and Eric Blake
> 
> Changlong Xie (5):
>   Backup: export interfaces for extra serialization
>   configure: support replication
>   Introduce new APIs to do replication operation
>   tests: add unit test case for replication
>   MAINTAINERS: add maintainer for replication
> 
> Wen Congyang (7):
>   unblock backup operations in backing file
>   Backup: clear all bitmap when doing block checkpoint
>   Link backup into block core
>   docs: block replication's description
>   auto complete active commit
>   Implement new driver for block replication
>   support replication driver in blockdev-add
> 
>  MAINTAINERS                  |   9 +
>  Makefile.objs                |   1 +
>  block.c                      |  17 ++
>  block/Makefile.objs          |   3 +-
>  block/backup.c               |  59 +++-
>  block/mirror.c               |  13 +-
>  block/replication.c          | 659 +++++++++++++++++++++++++++++++++++++++++++
>  blockdev.c                   |   2 +-
>  configure                    |  11 +
>  docs/block-replication.txt   | 239 ++++++++++++++++
>  include/block/block_backup.h |  39 +++
>  include/block/block_int.h    |   3 +-
>  qapi/block-core.json         |  36 ++-
>  qemu-img.c                   |   2 +-
>  replication.c                | 107 +++++++
>  replication.h                | 174 ++++++++++++
>  tests/.gitignore             |   1 +
>  tests/Makefile.include       |   4 +
>  tests/test-replication.c     | 575 +++++++++++++++++++++++++++++++++++++
>  19 files changed, 1937 insertions(+), 17 deletions(-)
>  create mode 100644 block/replication.c
>  create mode 100644 docs/block-replication.txt
>  create mode 100644 include/block/block_backup.h
>  create mode 100644 replication.c
>  create mode 100644 replication.h
>  create mode 100644 tests/test-replication.c
> 
> -- 
> 1.9.3
> 
> 
> 
> 

Thanks, applied to my block-next tree:
https://github.com/stefanha/qemu/commits/block-next

Stefan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH v24 11/12] support replication driver in blockdev-add
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 11/12] support replication driver in blockdev-add Changlong Xie
@ 2016-08-09  9:08   ` Kevin Wolf
  2016-08-15  1:49     ` Changlong Xie
  0 siblings, 1 reply; 29+ messages in thread
From: Kevin Wolf @ 2016-08-09  9:08 UTC (permalink / raw)
  To: Changlong Xie
  Cc: qemu devel, qemu block, Stefan Hajnoczi, Fam Zheng, Max Reitz,
	Jeff Cody, Paolo Bonzini, John Snow, Eric Blake,
	Markus Armbruster, Dr. David Alan Gilbert, Dong Eddie,
	Jiang Yunhong, zhanghailiang, Gonglei, Wen Congyang, Wang Weiwei

Am 27.07.2016 um 09:01 hat Changlong Xie geschrieben:
> From: Wen Congyang <wency@cn.fujitsu.com>
> 
> Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
> Signed-off-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
> Signed-off-by: Wang WeiWei <wangww.fnst@cn.fujitsu.com>
> Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
> Signed-off-by: Gonglei <arei.gonglei@huawei.com>
> Reviewed-by: Eric Blake <eblake@redhat.com>

> @@ -2078,6 +2079,23 @@
>  { 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ] }
>  
>  ##
> +# @BlockdevOptionsReplication
> +#
> +# Driver specific block device options for replication
> +#
> +# @mode: the replication mode
> +#
> +# @top-id: #optional In secondary mode, node name or device ID of the root
> +#          node who owns the replication node chain. Ignored in primary mode.

Can we change this to "Must not be given in primary mode"? Not sure what
the code currently does, but I think it should error out if top-id is
given there.

> +#
> +# Since: 2.8
> +##
> +{ 'struct': 'BlockdevOptionsReplication',
> +  'base': 'BlockdevOptionsGenericFormat',
> +  'data': { 'mode': 'ReplicationMode',
> +            '*top-id': 'str' } }

Kevin

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH v24 11/12] support replication driver in blockdev-add
  2016-08-09  9:08   ` Kevin Wolf
@ 2016-08-15  1:49     ` Changlong Xie
  2016-08-15  8:37       ` Kevin Wolf
  0 siblings, 1 reply; 29+ messages in thread
From: Changlong Xie @ 2016-08-15  1:49 UTC (permalink / raw)
  To: Kevin Wolf
  Cc: qemu devel, qemu block, Stefan Hajnoczi, Fam Zheng, Max Reitz,
	Jeff Cody, Paolo Bonzini, John Snow, Eric Blake,
	Markus Armbruster, Dr. David Alan Gilbert, Dong Eddie,
	Jiang Yunhong, zhanghailiang, Gonglei, Wen Congyang, Wang Weiwei

On 08/09/2016 05:08 PM, Kevin Wolf wrote:
> Am 27.07.2016 um 09:01 hat Changlong Xie geschrieben:
>> From: Wen Congyang <wency@cn.fujitsu.com>
>>
>> Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
>> Signed-off-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
>> Signed-off-by: Wang WeiWei <wangww.fnst@cn.fujitsu.com>
>> Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
>> Signed-off-by: Gonglei <arei.gonglei@huawei.com>
>> Reviewed-by: Eric Blake <eblake@redhat.com>
>
>> @@ -2078,6 +2079,23 @@
>>   { 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ] }
>>
>>   ##
>> +# @BlockdevOptionsReplication
>> +#
>> +# Driver specific block device options for replication
>> +#
>> +# @mode: the replication mode
>> +#
>> +# @top-id: #optional In secondary mode, node name or device ID of the root
>> +#          node who owns the replication node chain. Ignored in primary mode.
>
> Can we change this to "Must not be given in primary mode"? Not sure what
> the code currently does, but I think it should error out if top-id is

Replication driver will ignore "top-id" parameter in Primary mode.

> given there.
>
>> +#
>> +# Since: 2.8
>> +##
>> +{ 'struct': 'BlockdevOptionsReplication',
>> +  'base': 'BlockdevOptionsGenericFormat',
>> +  'data': { 'mode': 'ReplicationMode',
>> +            '*top-id': 'str' } }
>
> Kevin
>
>
> .
>

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH v24 11/12] support replication driver in blockdev-add
  2016-08-15  1:49     ` Changlong Xie
@ 2016-08-15  8:37       ` Kevin Wolf
  2016-08-15  9:32         ` Changlong Xie
  0 siblings, 1 reply; 29+ messages in thread
From: Kevin Wolf @ 2016-08-15  8:37 UTC (permalink / raw)
  To: Changlong Xie
  Cc: qemu devel, qemu block, Stefan Hajnoczi, Fam Zheng, Max Reitz,
	Jeff Cody, Paolo Bonzini, John Snow, Eric Blake,
	Markus Armbruster, Dr. David Alan Gilbert, Dong Eddie,
	Jiang Yunhong, zhanghailiang, Gonglei, Wen Congyang, Wang Weiwei

Am 15.08.2016 um 03:49 hat Changlong Xie geschrieben:
> On 08/09/2016 05:08 PM, Kevin Wolf wrote:
> >Am 27.07.2016 um 09:01 hat Changlong Xie geschrieben:
> >>From: Wen Congyang <wency@cn.fujitsu.com>
> >>
> >>Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
> >>Signed-off-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
> >>Signed-off-by: Wang WeiWei <wangww.fnst@cn.fujitsu.com>
> >>Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
> >>Signed-off-by: Gonglei <arei.gonglei@huawei.com>
> >>Reviewed-by: Eric Blake <eblake@redhat.com>
> >
> >>@@ -2078,6 +2079,23 @@
> >>  { 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ] }
> >>
> >>  ##
> >>+# @BlockdevOptionsReplication
> >>+#
> >>+# Driver specific block device options for replication
> >>+#
> >>+# @mode: the replication mode
> >>+#
> >>+# @top-id: #optional In secondary mode, node name or device ID of the root
> >>+#          node who owns the replication node chain. Ignored in primary mode.
> >
> >Can we change this to "Must not be given in primary mode"? Not sure what
> >the code currently does, but I think it should error out if top-id is
> 
> Replication driver will ignore "top-id" parameter in Primary mode.

This is not good behaviour, which is why I requested a change.

Kevin

> >given there.
> >
> >>+#
> >>+# Since: 2.8
> >>+##
> >>+{ 'struct': 'BlockdevOptionsReplication',
> >>+  'base': 'BlockdevOptionsGenericFormat',
> >>+  'data': { 'mode': 'ReplicationMode',
> >>+            '*top-id': 'str' } }
> >
> >Kevin

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH v24 11/12] support replication driver in blockdev-add
  2016-08-15  8:37       ` Kevin Wolf
@ 2016-08-15  9:32         ` Changlong Xie
  2016-09-12 14:01           ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi
  0 siblings, 1 reply; 29+ messages in thread
From: Changlong Xie @ 2016-08-15  9:32 UTC (permalink / raw)
  To: Kevin Wolf
  Cc: qemu devel, qemu block, Stefan Hajnoczi, Fam Zheng, Max Reitz,
	Jeff Cody, Paolo Bonzini, John Snow, Eric Blake,
	Markus Armbruster, Dr. David Alan Gilbert, Dong Eddie,
	Jiang Yunhong, zhanghailiang, Gonglei, Wen Congyang, Wang Weiwei

On 08/15/2016 04:37 PM, Kevin Wolf wrote:
> Am 15.08.2016 um 03:49 hat Changlong Xie geschrieben:
>> On 08/09/2016 05:08 PM, Kevin Wolf wrote:
>>> Am 27.07.2016 um 09:01 hat Changlong Xie geschrieben:
>>>> From: Wen Congyang <wency@cn.fujitsu.com>
>>>>
>>>> Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
>>>> Signed-off-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
>>>> Signed-off-by: Wang WeiWei <wangww.fnst@cn.fujitsu.com>
>>>> Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
>>>> Signed-off-by: Gonglei <arei.gonglei@huawei.com>
>>>> Reviewed-by: Eric Blake <eblake@redhat.com>
>>>
>>>> @@ -2078,6 +2079,23 @@
>>>>   { 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ] }
>>>>
>>>>   ##
>>>> +# @BlockdevOptionsReplication
>>>> +#
>>>> +# Driver specific block device options for replication
>>>> +#
>>>> +# @mode: the replication mode
>>>> +#
>>>> +# @top-id: #optional In secondary mode, node name or device ID of the root
>>>> +#          node who owns the replication node chain. Ignored in primary mode.
>>>
>>> Can we change this to "Must not be given in primary mode"? Not sure what
>>> the code currently does, but I think it should error out if top-id is
>>
>> Replication driver will ignore "top-id" parameter in Primary mode.
>
> This is not good behaviour, which is why I requested a change.
>

Hi stefan

Would you like me send another [PATCH v25] based your block-next? Or a 
separate patch until your tree is merged.

Thanks
	-Xie

> Kevin
>
>>> given there.
>>>
>>>> +#
>>>> +# Since: 2.8
>>>> +##
>>>> +{ 'struct': 'BlockdevOptionsReplication',
>>>> +  'base': 'BlockdevOptionsGenericFormat',
>>>> +  'data': { 'mode': 'ReplicationMode',
>>>> +            '*top-id': 'str' } }
>>>
>>> Kevin
>
>
> .
>

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH v24 02/12] Backup: clear all bitmap when doing block checkpoint
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 02/12] Backup: clear all bitmap when doing block checkpoint Changlong Xie
  2016-08-04  9:47   ` Stefan Hajnoczi
@ 2016-08-16 12:55   ` Kashyap Chamarthy
  2016-08-16 13:10     ` Kashyap Chamarthy
  1 sibling, 1 reply; 29+ messages in thread
From: Kashyap Chamarthy @ 2016-08-16 12:55 UTC (permalink / raw)
  To: Changlong Xie
  Cc: qemu devel, qemu block, Stefan Hajnoczi, Fam Zheng, Max Reitz,
	Kevin Wolf, Jeff Cody, Wang Weiwei, zhanghailiang, Jiang Yunhong,
	Dong Eddie, Markus Armbruster, Dr. David Alan Gilbert, Gonglei,
	Paolo Bonzini, John Snow

On Wed, Jul 27, 2016 at 03:01:43PM +0800, Changlong Xie wrote:
> From: Wen Congyang <wency@cn.fujitsu.com>
> 
> Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
> Signed-off-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
> Signed-off-by: Wang WeiWei <wangww.fnst@cn.fujitsu.com>
> Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
> Signed-off-by: Gonglei <arei.gonglei@huawei.com>
> ---
>  block/backup.c               | 18 ++++++++++++++++++
>  include/block/block_backup.h | 25 +++++++++++++++++++++++++
>  2 files changed, 43 insertions(+)
>  create mode 100644 include/block/block_backup.h

[...]
Tested-by: Kashyap Chamarthy <kchamart@redhat.com>

Test case:

Without this patch applied
==========================

Create an empty target image:

	$ qemu-img create -f qcow2 target.qcow2 1G

$ ./qmp-shell -v -p ./qmp-sock

(QEMU) blockdev-add options={"id":"drive-ide1-0-0","driver":"qcow2","file":{"driver":"file","filename":"/export/target.qcow2"},"backing":"drive-ide0-0-0"}

(QEMU) blockdev-backup device=drive-ide0-0-0 target=drive-ide1-0-0 sync=none
{
    "execute": "blockdev-backup",
    "arguments": {
        "device": "drive-ide0-0-0",
        "target": "drive-ide1-0-0",
        "sync": "none"
    }                                                                                                                                                                                         
}                                                                                                                                                                                             
{
    "error": {
        "class": "GenericError",
        "desc": "Node 'drive-ide0-0-0' is busy: node is used as backing hd of '#block360'"
    }                                                                                                                                                                                         
}                                                                                                                                                                                             


With this patch applied
=======================

`blockdev-backup` of an image to its immediate overlay succeds:

-----------------------------------------------------------------------
(QEMU) blockdev-backup device=drive-ide0-0-0 target=drive-ide1-0-0 sync=none
{
    "execute": "blockdev-backup", 
    "arguments": {
        "device": "drive-ide0-0-0", 
        "target": "drive-ide1-0-0", 
        "sync": "none"
    }
}
{
    "return": {}
}
(QEMU) query-block-jobs
{
    "execute": "query-block-jobs", 
    "arguments": {}
}
{
    "return": [
        {
            "busy": false, 
            "type": "backup", 
            "len": 41126400, 
            "paused": false, 
            "ready": false, 
            "io-status": "ok", 
            "offset": 0, 
            "device": "drive-ide0-0-0", 
            "speed": 0
        }
    ]
}
-----------------------------------------------------------------------

-- 
/kashyap

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH v24 02/12] Backup: clear all bitmap when doing block checkpoint
  2016-08-16 12:55   ` Kashyap Chamarthy
@ 2016-08-16 13:10     ` Kashyap Chamarthy
  0 siblings, 0 replies; 29+ messages in thread
From: Kashyap Chamarthy @ 2016-08-16 13:10 UTC (permalink / raw)
  To: Changlong Xie
  Cc: qemu devel, qemu block, Stefan Hajnoczi, Fam Zheng, Max Reitz,
	Kevin Wolf, Jeff Cody, Wang Weiwei, zhanghailiang, Jiang Yunhong,
	Dong Eddie, Markus Armbruster, Dr. David Alan Gilbert, Gonglei,
	Paolo Bonzini, John Snow

On Tue, Aug 16, 2016 at 02:55:41PM +0200, Kashyap Chamarthy wrote:
> On Wed, Jul 27, 2016 at 03:01:43PM +0800, Changlong Xie wrote:
> > From: Wen Congyang <wency@cn.fujitsu.com>
> > 
> > Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
> > Signed-off-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
> > Signed-off-by: Wang WeiWei <wangww.fnst@cn.fujitsu.com>
> > Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
> > Signed-off-by: Gonglei <arei.gonglei@huawei.com>
> > ---
> >  block/backup.c               | 18 ++++++++++++++++++
> >  include/block/block_backup.h | 25 +++++++++++++++++++++++++
> >  2 files changed, 43 insertions(+)
> >  create mode 100644 include/block/block_backup.h
> 
> [...]
> Tested-by: Kashyap Chamarthy <kchamart@redhat.com>

I meant to give the Tested-by to this patch:

    [PATCH v24 01/12] unblock backup operations in backing file
    https://lists.gnu.org/archive/html/qemu-devel/2016-07/msg06096.html

(I erroneously mixed up 01/12 02/12, sorry for the noise.)

I'll respond on the correct patch, for archives' sake.

[...]

-- 
/kashyap

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [PATCH v24 01/12] unblock backup operations in backing file
  2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 01/12] unblock backup operations in backing file Changlong Xie
  2016-08-04  9:46   ` Stefan Hajnoczi
@ 2016-08-16 13:13   ` Kashyap Chamarthy
  1 sibling, 0 replies; 29+ messages in thread
From: Kashyap Chamarthy @ 2016-08-16 13:13 UTC (permalink / raw)
  To: Changlong Xie
  Cc: qemu devel, qemu block, Stefan Hajnoczi, Fam Zheng, Max Reitz,
	Kevin Wolf, Jeff Cody, Wang Weiwei, zhanghailiang, Jiang Yunhong,
	Dong Eddie, Markus Armbruster, Dr. David Alan Gilbert, Gonglei,
	Paolo Bonzini, John Snow

[I erroneously gave a Tested-by to the next patch (02/12) in this
series, instead of this one.]

On Wed, Jul 27, 2016 at 03:01:42PM +0800, Changlong Xie wrote:
> From: Wen Congyang <wency@cn.fujitsu.com>
> 
> Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
> Signed-off-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
> Signed-off-by: Wang WeiWei <wangww.fnst@cn.fujitsu.com>
> ---
>  block.c | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)

Tested-by: Kashyap Chamarthy <address@hidden>

Test case:

Without this patch applied
==========================

Create an empty target image:

        $ qemu-img create -f qcow2 target.qcow2 1G

$ ./qmp-shell -v -p ./qmp-sock

(QEMU) blockdev-add 
options={"id":"drive-ide1-0-0","driver":"qcow2","file":{"driver":"file","filename":"/export/target.qcow2"},"backing":"drive-ide0-0-0"}

(QEMU) blockdev-backup device=drive-ide0-0-0 target=drive-ide1-0-0 sync=none
{
    "execute": "blockdev-backup",
    "arguments": {
        "device": "drive-ide0-0-0",
        "target": "drive-ide1-0-0",
        "sync": "none"
    }                                                                           
                                                                                
                              
}                                                                               
{
    "error": {
        "class": "GenericError",
        "desc": "Node 'drive-ide0-0-0' is busy: node is used as backing hd of 
'#block360'"
    }                                                                           
                                                                                
                              
}                                                                               

With this patch applied
=======================

`blockdev-backup` of an image to its immediate overlay succeds:

-----------------------------------------------------------------------
(QEMU) blockdev-backup device=drive-ide0-0-0 target=drive-ide1-0-0 sync=none
{
    "execute": "blockdev-backup", 
    "arguments": {
        "device": "drive-ide0-0-0", 
        "target": "drive-ide1-0-0", 
        "sync": "none"
    }
}
{
    "return": {}
}
(QEMU) query-block-jobs
{
    "execute": "query-block-jobs", 
    "arguments": {}
}
{
    "return": [
        {
            "busy": false, 
            "type": "backup", 
            "len": 41126400, 
            "paused": false, 
            "ready": false, 
            "io-status": "ok", 
            "offset": 0, 
            "device": "drive-ide0-0-0", 
            "speed": 0
        }
    ]
}
-----------------------------------------------------------------------

-- 
/kashyap

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [Qemu-block] [PATCH v24 11/12] support replication driver in blockdev-add
  2016-08-15  9:32         ` Changlong Xie
@ 2016-09-12 14:01           ` Stefan Hajnoczi
  2016-09-28  1:53             ` wangweiwei
  0 siblings, 1 reply; 29+ messages in thread
From: Stefan Hajnoczi @ 2016-09-12 14:01 UTC (permalink / raw)
  To: Changlong Xie
  Cc: Kevin Wolf, Wen Congyang, Wang Weiwei, Fam Zheng, zhanghailiang,
	qemu block, Jiang Yunhong, Dong Eddie, qemu devel, Max Reitz,
	Gonglei, Dr. David Alan Gilbert, Stefan Hajnoczi, Paolo Bonzini,
	Markus Armbruster

[-- Attachment #1: Type: text/plain, Size: 1824 bytes --]

On Mon, Aug 15, 2016 at 05:32:19PM +0800, Changlong Xie wrote:
> On 08/15/2016 04:37 PM, Kevin Wolf wrote:
> > Am 15.08.2016 um 03:49 hat Changlong Xie geschrieben:
> > > On 08/09/2016 05:08 PM, Kevin Wolf wrote:
> > > > Am 27.07.2016 um 09:01 hat Changlong Xie geschrieben:
> > > > > From: Wen Congyang <wency@cn.fujitsu.com>
> > > > > 
> > > > > Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
> > > > > Signed-off-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
> > > > > Signed-off-by: Wang WeiWei <wangww.fnst@cn.fujitsu.com>
> > > > > Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
> > > > > Signed-off-by: Gonglei <arei.gonglei@huawei.com>
> > > > > Reviewed-by: Eric Blake <eblake@redhat.com>
> > > > 
> > > > > @@ -2078,6 +2079,23 @@
> > > > >   { 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ] }
> > > > > 
> > > > >   ##
> > > > > +# @BlockdevOptionsReplication
> > > > > +#
> > > > > +# Driver specific block device options for replication
> > > > > +#
> > > > > +# @mode: the replication mode
> > > > > +#
> > > > > +# @top-id: #optional In secondary mode, node name or device ID of the root
> > > > > +#          node who owns the replication node chain. Ignored in primary mode.
> > > > 
> > > > Can we change this to "Must not be given in primary mode"? Not sure what
> > > > the code currently does, but I think it should error out if top-id is
> > > 
> > > Replication driver will ignore "top-id" parameter in Primary mode.
> > 
> > This is not good behaviour, which is why I requested a change.
> > 
> 
> Hi stefan
> 
> Would you like me send another [PATCH v25] based your block-next? Or a
> separate patch until your tree is merged.

Sorry for the slow response.  Please send a new patch on top of my
block-next tree.

Stefan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 455 bytes --]

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [Qemu-block] [PATCH v24 00/12] Block replication for continuous checkpoints
  2016-08-08 14:50 ` [Qemu-devel] [Qemu-block] [PATCH v24 00/12] Block replication for continuous checkpoints Stefan Hajnoczi
@ 2016-09-12 14:11   ` Stefan Hajnoczi
  2016-09-28  1:30     ` wangweiwei
  0 siblings, 1 reply; 29+ messages in thread
From: Stefan Hajnoczi @ 2016-09-12 14:11 UTC (permalink / raw)
  To: Changlong Xie
  Cc: qemu devel, qemu block, Stefan Hajnoczi, Fam Zheng, Max Reitz,
	Kevin Wolf, Jeff Cody, Wang Weiwei, zhanghailiang, Wen Congyang,
	Jiang Yunhong, Dong Eddie, Markus Armbruster,
	Dr. David Alan Gilbert, Gonglei, Paolo Bonzini

[-- Attachment #1: Type: text/plain, Size: 8951 bytes --]

On Mon, Aug 08, 2016 at 03:50:27PM +0100, Stefan Hajnoczi wrote:
> On Wed, Jul 27, 2016 at 03:01:41PM +0800, Changlong Xie wrote:
> > Block replication is a very important feature which is used for
> > continuous checkpoints(for example: COLO).
> > 
> > You can get the detailed information about block replication from here:
> > http://wiki.qemu.org/Features/BlockReplication
> > 
> > Usage:
> > Please refer to docs/block-replication.txt
> > 
> > You can get the patch here:
> > https://github.com//Pating/qemu/tree/block-replication-v24
> > 
> > You can get the patch with framework here:
> > https://github.com//Pating/qemu/tree/colo_framework_v23
> > 
> > TODO:
> > 1. Continuous block replication. It will be started after basic functions
> >    are accepted.
> > 
> > Change Log:
> > 
> > V24:
> > 1. Address comments from Max
> > p9: pass NULL to bdrv_lookup_bs(), and introduce bdrv_is_root_node() to check top_bs
> > p11: perfect @top-id description, and make it #optional 
> > p12: "replication" => "Replication", add docs/block-replication.txt
> > Note: we need bdrv_is_root_node() in p9, so this patchset is based on kevin/qmp-node-name, 
> > V23:
> > 1. Address comments from Stefan and Max, this series introduce p7/p12
> > p2. add Copyright for block_backup.h 
> > p7. support configure --disable-replication
> > p8. update 2.7 to 2.8
> > p11. update 2.7 to 2.8, add missing "top-id"
> > p12. update MAINTAINERS
> > V22:
> > 1. Rebase to the lastest code
> > 2. modify code adapt to the modification of backup_start & commit_active_start
> > 3. rewrite io_read & io_write for interface changes 
> > V21:
> > 1. Rebase to the lastest code
> > 2. use bdrv_pwrite_zeroes() and BDRV_SECTOR_BITS for p9
> > V20 Resend:
> > 1. Resend to avoid bothering qemu-trivial maintainers
> > 2. Address comments from Eric, fix header file issue and add a brief commit message for p7
> > V20:
> > 1. Rebase to the lastest code
> > 2. Address comments from stefan
> > p8: 
> > 1. error_setg() with an error message when check_top_bs() fails. 
> > 2. remove bdrv_ref(s->hidden_disk->bs) since commit 5c438bc6
> > 3. use bloc_job_cancel_sync() before active commit
> > p9: 
> > 1. fix uninitialized 'pattern_buf'
> > 2. introduce mkstemp(3) to fix unique filenames
> > 3. use qemu_vfree() for qemu_blockalign() memory
> > 4. add missing replication_start_all()
> > 5. remove useless pattern for io_write()
> > V19:
> > 1. Rebase to v2.6.0
> > 2. Address comments from stefan
> > p3: a new patch that export interfaces for extra serialization
> > p8: 
> > 1. call replication_stop() before freeing s->top_id
> > 2. check top_bs
> > 3. reopen file readonly in error return paths
> > 4. enable extra serialization between read and COW
> > p9: try to hanlde SIGABRT
> > V18:
> > p6: add local_err in all replication callbacks to prevent "errp == NULL"
> > p7: add missing qemu_iovec_destroy(xxx)
> > V17:
> > 1. Rebase to the lastest codes 
> > p2: refactor backup_do_checkpoint addressed comments from Jeff Cody
> > p4: fix bugs in "drive_add buddy xxx" hmp commands
> > p6: add "since: 2.7"
> > p7: fix bug in replication_close(), add missing "qapi/error.h", add test-replication 
> > p8: add "since: 2.7"
> > V16:
> > 1. Rebase to the newest codes
> > 2. Address comments from Stefan & hailiang
> > p3: we don't need this patch now
> > p4: add "top-id" parameters for secondary
> > p6: fix NULL pointer in replication callbacks, remove unnecessary typedefs, 
> > add doc comments that explain the semantics of Replication
> > p7: Refactor AioContext for thread-safe, remove unnecessary get_top_bs()
> > *Note*: I'm working on replication testcase now, will send out in V17
> > V15:
> > 1. Rebase to the newest codes
> > 2. Fix typos and coding style addresed Eric's comments
> > 3. Address Stefan's comments
> >    1) Make backup_do_checkpoint public, drop the changes on BlockJobDriver
> >    2) Update the message and description for [PATCH 4/9]
> >    3) Make replication_(start/stop/do_checkpoint)_all as global interfaces
> >    4) Introduce AioContext lock to protect start/stop/do_checkpoint callbacks
> >    5) Use BdrvChild instead of holding on to BlockDriverState * pointers
> > 4. Clear BDRV_O_INACTIVE for hidden disk's open_flags since commit 09e0c771  
> > 5. Introduce replication_get_error_all to check replication status
> > 6. Remove useless discard interface
> > V14:
> > 1. Implement auto complete active commit
> > 2. Implement active commit block job for replication.c
> > 3. Address the comments from Stefan, add replication-specific API and data
> >    structure, also remove old block layer APIs
> > V13:
> > 1. Rebase to the newest codes
> > 2. Remove redundant marcos and semicolon in replication.c 
> > 3. Fix typos in block-replication.txt
> > V12:
> > 1. Rebase to the newest codes
> > 2. Use backing reference to replcace 'allow-write-backing-file'
> > V11:
> > 1. Reopen the backing file when starting blcok replication if it is not
> >    opened in R/W mode
> > 2. Unblock BLOCK_OP_TYPE_BACKUP_SOURCE and BLOCK_OP_TYPE_BACKUP_TARGET
> >    when opening backing file
> > 3. Block the top BDS so there is only one block job for the top BDS and
> >    its backing chain.
> > V10:
> > 1. Use blockdev-remove-medium and blockdev-insert-medium to replace backing
> >    reference.
> > 2. Address the comments from Eric Blake
> > V9:
> > 1. Update the error messages
> > 2. Rebase to the newest qemu
> > 3. Split child add/delete support. These patches are sent in another patchset.
> > V8:
> > 1. Address Alberto Garcia's comments
> > V7:
> > 1. Implement adding/removing quorum child. Remove the option non-connect.
> > 2. Simplify the backing refrence option according to Stefan Hajnoczi's suggestion
> > V6:
> > 1. Rebase to the newest qemu.
> > V5:
> > 1. Address the comments from Gong Lei
> > 2. Speed the failover up. The secondary vm can take over very quickly even
> >    if there are too many I/O requests.
> > V4:
> > 1. Introduce a new driver replication to avoid touch nbd and qcow2.
> > V3:
> > 1: use error_setg() instead of error_set()
> > 2. Add a new block job API
> > 3. Active disk, hidden disk and nbd target uses the same AioContext
> > 4. Add a testcase to test new hbitmap API
> > V2:
> > 1. Redesign the secondary qemu(use image-fleecing)
> > 2. Use Error objects to return error message
> > 3. Address the comments from Max Reitz and Eric Blake
> > 
> > Changlong Xie (5):
> >   Backup: export interfaces for extra serialization
> >   configure: support replication
> >   Introduce new APIs to do replication operation
> >   tests: add unit test case for replication
> >   MAINTAINERS: add maintainer for replication
> > 
> > Wen Congyang (7):
> >   unblock backup operations in backing file
> >   Backup: clear all bitmap when doing block checkpoint
> >   Link backup into block core
> >   docs: block replication's description
> >   auto complete active commit
> >   Implement new driver for block replication
> >   support replication driver in blockdev-add
> > 
> >  MAINTAINERS                  |   9 +
> >  Makefile.objs                |   1 +
> >  block.c                      |  17 ++
> >  block/Makefile.objs          |   3 +-
> >  block/backup.c               |  59 +++-
> >  block/mirror.c               |  13 +-
> >  block/replication.c          | 659 +++++++++++++++++++++++++++++++++++++++++++
> >  blockdev.c                   |   2 +-
> >  configure                    |  11 +
> >  docs/block-replication.txt   | 239 ++++++++++++++++
> >  include/block/block_backup.h |  39 +++
> >  include/block/block_int.h    |   3 +-
> >  qapi/block-core.json         |  36 ++-
> >  qemu-img.c                   |   2 +-
> >  replication.c                | 107 +++++++
> >  replication.h                | 174 ++++++++++++
> >  tests/.gitignore             |   1 +
> >  tests/Makefile.include       |   4 +
> >  tests/test-replication.c     | 575 +++++++++++++++++++++++++++++++++++++
> >  19 files changed, 1937 insertions(+), 17 deletions(-)
> >  create mode 100644 block/replication.c
> >  create mode 100644 docs/block-replication.txt
> >  create mode 100644 include/block/block_backup.h
> >  create mode 100644 replication.c
> >  create mode 100644 replication.h
> >  create mode 100644 tests/test-replication.c
> > 
> > -- 
> > 1.9.3
> > 
> > 
> > 
> > 
> 
> Thanks, applied to my block-next tree:
> https://github.com/stefanha/qemu/commits/block-next

I have sent the pull request so this can be merged into qemu.git.

In the future please use a prefix on each commit message.  For example
"block: unblock backup operations in backing file".  You can find a good
prefix to use by checking git-log(1) for the main file touched by the
patch and seeing what other people used.

Stefan

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 455 bytes --]

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [Qemu-block] [PATCH v24 00/12] Block replication for continuous checkpoints
  2016-09-12 14:11   ` Stefan Hajnoczi
@ 2016-09-28  1:30     ` wangweiwei
  0 siblings, 0 replies; 29+ messages in thread
From: wangweiwei @ 2016-09-28  1:30 UTC (permalink / raw)
  To: Stefan Hajnoczi, Changlong Xie
  Cc: qemu devel, qemu block, Stefan Hajnoczi, Fam Zheng, Max Reitz,
	Kevin Wolf, Jeff Cody, zhanghailiang, Wen Congyang, Jiang Yunhong,
	Dong Eddie, Markus Armbruster, Dr. David Alan Gilbert, Gonglei,
	Paolo Bonzini

在 2016年09月12日 22:11, Stefan Hajnoczi 写道:
> On Mon, Aug 08, 2016 at 03:50:27PM +0100, Stefan Hajnoczi wrote:
>> On Wed, Jul 27, 2016 at 03:01:41PM +0800, Changlong Xie wrote:
>>> Block replication is a very important feature which is used for
>>> continuous checkpoints(for example: COLO).
>>>
>>> You can get the detailed information about block replication from here:
>>> http://wiki.qemu.org/Features/BlockReplication
>>>
>>> Usage:
>>> Please refer to docs/block-replication.txt
>>>
>>> You can get the patch here:
>>> https://github.com//Pating/qemu/tree/block-replication-v24
>>>
>>> You can get the patch with framework here:
>>> https://github.com//Pating/qemu/tree/colo_framework_v23
>>>
>>> TODO:
>>> 1. Continuous block replication. It will be started after basic functions
>>>     are accepted.
>>>
>>> Change Log:
>>>
>>> V24:
>>> 1. Address comments from Max
>>> p9: pass NULL to bdrv_lookup_bs(), and introduce bdrv_is_root_node() to check top_bs
>>> p11: perfect @top-id description, and make it #optional
>>> p12: "replication" => "Replication", add docs/block-replication.txt
>>> Note: we need bdrv_is_root_node() in p9, so this patchset is based on kevin/qmp-node-name,
>>> V23:
>>> 1. Address comments from Stefan and Max, this series introduce p7/p12
>>> p2. add Copyright for block_backup.h
>>> p7. support configure --disable-replication
>>> p8. update 2.7 to 2.8
>>> p11. update 2.7 to 2.8, add missing "top-id"
>>> p12. update MAINTAINERS
>>> V22:
>>> 1. Rebase to the lastest code
>>> 2. modify code adapt to the modification of backup_start & commit_active_start
>>> 3. rewrite io_read & io_write for interface changes
>>> V21:
>>> 1. Rebase to the lastest code
>>> 2. use bdrv_pwrite_zeroes() and BDRV_SECTOR_BITS for p9
>>> V20 Resend:
>>> 1. Resend to avoid bothering qemu-trivial maintainers
>>> 2. Address comments from Eric, fix header file issue and add a brief commit message for p7
>>> V20:
>>> 1. Rebase to the lastest code
>>> 2. Address comments from stefan
>>> p8:
>>> 1. error_setg() with an error message when check_top_bs() fails.
>>> 2. remove bdrv_ref(s->hidden_disk->bs) since commit 5c438bc6
>>> 3. use bloc_job_cancel_sync() before active commit
>>> p9:
>>> 1. fix uninitialized 'pattern_buf'
>>> 2. introduce mkstemp(3) to fix unique filenames
>>> 3. use qemu_vfree() for qemu_blockalign() memory
>>> 4. add missing replication_start_all()
>>> 5. remove useless pattern for io_write()
>>> V19:
>>> 1. Rebase to v2.6.0
>>> 2. Address comments from stefan
>>> p3: a new patch that export interfaces for extra serialization
>>> p8:
>>> 1. call replication_stop() before freeing s->top_id
>>> 2. check top_bs
>>> 3. reopen file readonly in error return paths
>>> 4. enable extra serialization between read and COW
>>> p9: try to hanlde SIGABRT
>>> V18:
>>> p6: add local_err in all replication callbacks to prevent "errp == NULL"
>>> p7: add missing qemu_iovec_destroy(xxx)
>>> V17:
>>> 1. Rebase to the lastest codes
>>> p2: refactor backup_do_checkpoint addressed comments from Jeff Cody
>>> p4: fix bugs in "drive_add buddy xxx" hmp commands
>>> p6: add "since: 2.7"
>>> p7: fix bug in replication_close(), add missing "qapi/error.h", add test-replication
>>> p8: add "since: 2.7"
>>> V16:
>>> 1. Rebase to the newest codes
>>> 2. Address comments from Stefan & hailiang
>>> p3: we don't need this patch now
>>> p4: add "top-id" parameters for secondary
>>> p6: fix NULL pointer in replication callbacks, remove unnecessary typedefs,
>>> add doc comments that explain the semantics of Replication
>>> p7: Refactor AioContext for thread-safe, remove unnecessary get_top_bs()
>>> *Note*: I'm working on replication testcase now, will send out in V17
>>> V15:
>>> 1. Rebase to the newest codes
>>> 2. Fix typos and coding style addresed Eric's comments
>>> 3. Address Stefan's comments
>>>     1) Make backup_do_checkpoint public, drop the changes on BlockJobDriver
>>>     2) Update the message and description for [PATCH 4/9]
>>>     3) Make replication_(start/stop/do_checkpoint)_all as global interfaces
>>>     4) Introduce AioContext lock to protect start/stop/do_checkpoint callbacks
>>>     5) Use BdrvChild instead of holding on to BlockDriverState * pointers
>>> 4. Clear BDRV_O_INACTIVE for hidden disk's open_flags since commit 09e0c771
>>> 5. Introduce replication_get_error_all to check replication status
>>> 6. Remove useless discard interface
>>> V14:
>>> 1. Implement auto complete active commit
>>> 2. Implement active commit block job for replication.c
>>> 3. Address the comments from Stefan, add replication-specific API and data
>>>     structure, also remove old block layer APIs
>>> V13:
>>> 1. Rebase to the newest codes
>>> 2. Remove redundant marcos and semicolon in replication.c
>>> 3. Fix typos in block-replication.txt
>>> V12:
>>> 1. Rebase to the newest codes
>>> 2. Use backing reference to replcace 'allow-write-backing-file'
>>> V11:
>>> 1. Reopen the backing file when starting blcok replication if it is not
>>>     opened in R/W mode
>>> 2. Unblock BLOCK_OP_TYPE_BACKUP_SOURCE and BLOCK_OP_TYPE_BACKUP_TARGET
>>>     when opening backing file
>>> 3. Block the top BDS so there is only one block job for the top BDS and
>>>     its backing chain.
>>> V10:
>>> 1. Use blockdev-remove-medium and blockdev-insert-medium to replace backing
>>>     reference.
>>> 2. Address the comments from Eric Blake
>>> V9:
>>> 1. Update the error messages
>>> 2. Rebase to the newest qemu
>>> 3. Split child add/delete support. These patches are sent in another patchset.
>>> V8:
>>> 1. Address Alberto Garcia's comments
>>> V7:
>>> 1. Implement adding/removing quorum child. Remove the option non-connect.
>>> 2. Simplify the backing refrence option according to Stefan Hajnoczi's suggestion
>>> V6:
>>> 1. Rebase to the newest qemu.
>>> V5:
>>> 1. Address the comments from Gong Lei
>>> 2. Speed the failover up. The secondary vm can take over very quickly even
>>>     if there are too many I/O requests.
>>> V4:
>>> 1. Introduce a new driver replication to avoid touch nbd and qcow2.
>>> V3:
>>> 1: use error_setg() instead of error_set()
>>> 2. Add a new block job API
>>> 3. Active disk, hidden disk and nbd target uses the same AioContext
>>> 4. Add a testcase to test new hbitmap API
>>> V2:
>>> 1. Redesign the secondary qemu(use image-fleecing)
>>> 2. Use Error objects to return error message
>>> 3. Address the comments from Max Reitz and Eric Blake
>>>
>>> Changlong Xie (5):
>>>    Backup: export interfaces for extra serialization
>>>    configure: support replication
>>>    Introduce new APIs to do replication operation
>>>    tests: add unit test case for replication
>>>    MAINTAINERS: add maintainer for replication
>>>
>>> Wen Congyang (7):
>>>    unblock backup operations in backing file
>>>    Backup: clear all bitmap when doing block checkpoint
>>>    Link backup into block core
>>>    docs: block replication's description
>>>    auto complete active commit
>>>    Implement new driver for block replication
>>>    support replication driver in blockdev-add
>>>
>>>   MAINTAINERS                  |   9 +
>>>   Makefile.objs                |   1 +
>>>   block.c                      |  17 ++
>>>   block/Makefile.objs          |   3 +-
>>>   block/backup.c               |  59 +++-
>>>   block/mirror.c               |  13 +-
>>>   block/replication.c          | 659 +++++++++++++++++++++++++++++++++++++++++++
>>>   blockdev.c                   |   2 +-
>>>   configure                    |  11 +
>>>   docs/block-replication.txt   | 239 ++++++++++++++++
>>>   include/block/block_backup.h |  39 +++
>>>   include/block/block_int.h    |   3 +-
>>>   qapi/block-core.json         |  36 ++-
>>>   qemu-img.c                   |   2 +-
>>>   replication.c                | 107 +++++++
>>>   replication.h                | 174 ++++++++++++
>>>   tests/.gitignore             |   1 +
>>>   tests/Makefile.include       |   4 +
>>>   tests/test-replication.c     | 575 +++++++++++++++++++++++++++++++++++++
>>>   19 files changed, 1937 insertions(+), 17 deletions(-)
>>>   create mode 100644 block/replication.c
>>>   create mode 100644 docs/block-replication.txt
>>>   create mode 100644 include/block/block_backup.h
>>>   create mode 100644 replication.c
>>>   create mode 100644 replication.h
>>>   create mode 100644 tests/test-replication.c
>>>
>>> --
>>> 1.9.3
>>>
>>>
>>>
>>>
>>
>> Thanks, applied to my block-next tree:
>> https://github.com/stefanha/qemu/commits/block-next
>
> I have sent the pull request so this can be merged into qemu.git.
>
> In the future please use a prefix on each commit message.  For example
> "block: unblock backup operations in backing file".  You can find a good
> prefix to use by checking git-log(1) for the main file touched by the
> patch and seeing what other people used.
>
> Stefan
>
ok, thanks.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [Qemu-devel] [Qemu-block] [PATCH v24 11/12] support replication driver in blockdev-add
  2016-09-12 14:01           ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi
@ 2016-09-28  1:53             ` wangweiwei
  0 siblings, 0 replies; 29+ messages in thread
From: wangweiwei @ 2016-09-28  1:53 UTC (permalink / raw)
  To: Stefan Hajnoczi, Changlong Xie
  Cc: Kevin Wolf, Wen Congyang, Fam Zheng, zhanghailiang, qemu block,
	Jiang Yunhong, Dong Eddie, qemu devel, Max Reitz, Gonglei,
	Dr. David Alan Gilbert, Stefan Hajnoczi, Paolo Bonzini,
	Markus Armbruster

在 2016年09月12日 22:01, Stefan Hajnoczi 写道:
> On Mon, Aug 15, 2016 at 05:32:19PM +0800, Changlong Xie wrote:
>> On 08/15/2016 04:37 PM, Kevin Wolf wrote:
>>> Am 15.08.2016 um 03:49 hat Changlong Xie geschrieben:
>>>> On 08/09/2016 05:08 PM, Kevin Wolf wrote:
>>>>> Am 27.07.2016 um 09:01 hat Changlong Xie geschrieben:
>>>>>> From: Wen Congyang <wency@cn.fujitsu.com>
>>>>>>
>>>>>> Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
>>>>>> Signed-off-by: Changlong Xie <xiecl.fnst@cn.fujitsu.com>
>>>>>> Signed-off-by: Wang WeiWei <wangww.fnst@cn.fujitsu.com>
>>>>>> Signed-off-by: zhanghailiang <zhang.zhanghailiang@huawei.com>
>>>>>> Signed-off-by: Gonglei <arei.gonglei@huawei.com>
>>>>>> Reviewed-by: Eric Blake <eblake@redhat.com>
>>>>>
>>>>>> @@ -2078,6 +2079,23 @@
>>>>>>    { 'enum' : 'ReplicationMode', 'data' : [ 'primary', 'secondary' ] }
>>>>>>
>>>>>>    ##
>>>>>> +# @BlockdevOptionsReplication
>>>>>> +#
>>>>>> +# Driver specific block device options for replication
>>>>>> +#
>>>>>> +# @mode: the replication mode
>>>>>> +#
>>>>>> +# @top-id: #optional In secondary mode, node name or device ID of the root
>>>>>> +#          node who owns the replication node chain. Ignored in primary mode.
>>>>>
>>>>> Can we change this to "Must not be given in primary mode"? Not sure what
>>>>> the code currently does, but I think it should error out if top-id is
>>>>
>>>> Replication driver will ignore "top-id" parameter in Primary mode.
>>>
>>> This is not good behaviour, which is why I requested a change.
>>>
>>
>> Hi stefan
>>
>> Would you like me send another [PATCH v25] based your block-next? Or a
>> separate patch until your tree is merged.
>
> Sorry for the slow response.  Please send a new patch on top of my
> block-next tree.
>
> Stefan
>
ok, I will send a new patch on the top of block-next tree.

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2016-09-28  1:54 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-07-27  7:01 [Qemu-devel] [PATCH v24 00/12] Block replication for continuous checkpoints Changlong Xie
2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 01/12] unblock backup operations in backing file Changlong Xie
2016-08-04  9:46   ` Stefan Hajnoczi
2016-08-16 13:13   ` Kashyap Chamarthy
2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 02/12] Backup: clear all bitmap when doing block checkpoint Changlong Xie
2016-08-04  9:47   ` Stefan Hajnoczi
2016-08-16 12:55   ` Kashyap Chamarthy
2016-08-16 13:10     ` Kashyap Chamarthy
2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 03/12] Backup: export interfaces for extra serialization Changlong Xie
2016-08-04  9:53   ` Stefan Hajnoczi
2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 04/12] Link backup into block core Changlong Xie
2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 05/12] docs: block replication's description Changlong Xie
2016-08-04  9:55   ` Stefan Hajnoczi
2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 06/12] auto complete active commit Changlong Xie
2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 07/12] configure: support replication Changlong Xie
2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 08/12] Introduce new APIs to do replication operation Changlong Xie
2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 09/12] Implement new driver for block replication Changlong Xie
2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 10/12] tests: add unit test case for replication Changlong Xie
2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 11/12] support replication driver in blockdev-add Changlong Xie
2016-08-09  9:08   ` Kevin Wolf
2016-08-15  1:49     ` Changlong Xie
2016-08-15  8:37       ` Kevin Wolf
2016-08-15  9:32         ` Changlong Xie
2016-09-12 14:01           ` [Qemu-devel] [Qemu-block] " Stefan Hajnoczi
2016-09-28  1:53             ` wangweiwei
2016-07-27  7:01 ` [Qemu-devel] [PATCH v24 12/12] MAINTAINERS: add maintainer for replication Changlong Xie
2016-08-08 14:50 ` [Qemu-devel] [Qemu-block] [PATCH v24 00/12] Block replication for continuous checkpoints Stefan Hajnoczi
2016-09-12 14:11   ` Stefan Hajnoczi
2016-09-28  1:30     ` wangweiwei

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).