mirror of https://gitee.com/openkylin/qemu.git
replication: Introduce new APIs to do replication operation
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> Message-id: 1469602913-20979-9-git-send-email-xiecl.fnst@cn.fujitsu.com Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
This commit is contained in:
parent
a6b1d4c081
commit
190b9a8b55
|
@ -15,6 +15,7 @@ block-obj-$(CONFIG_POSIX) += aio-posix.o
|
||||||
block-obj-$(CONFIG_WIN32) += aio-win32.o
|
block-obj-$(CONFIG_WIN32) += aio-win32.o
|
||||||
block-obj-y += block/
|
block-obj-y += block/
|
||||||
block-obj-y += qemu-io-cmds.o
|
block-obj-y += qemu-io-cmds.o
|
||||||
|
block-obj-$(CONFIG_REPLICATION) += replication.o
|
||||||
|
|
||||||
block-obj-m = block/
|
block-obj-m = block/
|
||||||
|
|
||||||
|
|
|
@ -2162,6 +2162,19 @@
|
||||||
'server': ['GlusterServer'],
|
'server': ['GlusterServer'],
|
||||||
'*debug-level': 'int' } }
|
'*debug-level': 'int' } }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @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
|
# @BlockdevOptions
|
||||||
#
|
#
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 */
|
Loading…
Reference in New Issue