From: Ori Mamluk <omamluk@zerto.com>
To: qemu-devel@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>,
Roni Luxenberg <rluxenbe@redhat.com>,
Stefan Hajnoczi <stefanha@gmail.com>,
dlaor@redhat.com, Anthony Liguori <anthony@codemonkey.ws>,
Oded Kedem <oded@zerto.com>, Yair Kuszpet <yairk@zerto.com>,
Paolo Bonzini <pbonzini@redhat.com>
Subject: [Qemu-devel] [RFC PATCH v3 3/9] repagent: moved the module into block subdir, use REPAGENT instead of REPLICATION in configure
Date: Thu, 5 Apr 2012 15:17:52 +0300 [thread overview]
Message-ID: <9a75ff0ba418292c14268031ae7c000f@mail.gmail.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 96870 bytes --]
Sent as repagent patch v2
---
Makefile | 4 +-
Makefile.objs | 10 +-
block.c | 8 +-
block/repagent/qemu-repagent.txt | 104 ++++++++++++
block/repagent/repagent.c | 327
++++++++++++++++++++++++++++++++++++++
block/repagent/repagent.h | 46 ++++++
block/repagent/repagent_client.c | 162 +++++++++++++++++++
block/repagent/repagent_client.h | 36 ++++
block/repagent/repcmd.h | 59 +++++++
block/repagent/repcmd_listener.c | 173 ++++++++++++++++++++
block/repagent/repcmd_listener.h | 34 ++++
block/repagent/rephub_cmds.h | 151 ++++++++++++++++++
block/repagent/rephub_defs.h | 40 +++++
configure | 14 +-
replication/qemu-repagent.txt | 104 ------------
replication/repagent.c | 327
--------------------------------------
replication/repagent.h | 46 ------
replication/repagent_client.c | 160 -------------------
replication/repagent_client.h | 36 ----
replication/repcmd.h | 59 -------
replication/repcmd_listener.c | 173 --------------------
replication/repcmd_listener.h | 34 ----
replication/rephub_cmds.h | 151 ------------------
replication/rephub_defs.h | 40 -----
vl.c | 6 +-
25 files changed, 1153 insertions(+), 1151 deletions(-)
create mode 100644 block/repagent/qemu-repagent.txt
create mode 100644 block/repagent/repagent.c
create mode 100644 block/repagent/repagent.h
create mode 100644 block/repagent/repagent_client.c
create mode 100644 block/repagent/repagent_client.h
create mode 100644 block/repagent/repcmd.h
create mode 100644 block/repagent/repcmd_listener.c
create mode 100644 block/repagent/repcmd_listener.h
create mode 100644 block/repagent/rephub_cmds.h
create mode 100644 block/repagent/rephub_defs.h
delete mode 100644 replication/qemu-repagent.txt
delete mode 100644 replication/repagent.c
delete mode 100644 replication/repagent.h
delete mode 100644 replication/repagent_client.c
delete mode 100644 replication/repagent_client.h
delete mode 100644 replication/repcmd.h
delete mode 100644 replication/repcmd_listener.c
delete mode 100644 replication/repcmd_listener.h
delete mode 100644 replication/rephub_cmds.h
delete mode 100644 replication/rephub_defs.h
diff --git a/Makefile b/Makefile
index b6379fb..f7966f8 100644
--- a/Makefile
+++ b/Makefile
@@ -224,7 +224,7 @@ clean:
rm -f $(GENERATED_SOURCES)
rm -rf $(qapi-dir)
$(MAKE) -C tests/tcg clean
- rm -f replication/*.{o,d}
+ rm -f block/repagent/*.{o,d}
for d in $(ALL_SUBDIRS) $(QEMULIBS) libcacard; do \
if test -d $$d; then $(MAKE) -C $$d $@ || exit 1; fi; \
rm -f $$d/qemu-options.def; \
@@ -391,4 +391,4 @@ tar:
rm -rf /tmp/$(FILE)
# Include automatically generated dependency files
--include $(wildcard *.d audio/*.d slirp/*.d block/*.d net/*.d ui/*.d
qapi/*.d qga/*.d replication/*.d)
+-include $(wildcard *.d audio/*.d slirp/*.d block/*.d net/*.d ui/*.d
qapi/*.d qga/*.d block/repagent/*.d)
diff --git a/Makefile.objs b/Makefile.objs
index 01413a2..86fad8a 100755
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -30,10 +30,10 @@ block-obj-y += $(coroutine-obj-y) $(qobject-obj-y)
$(version-obj-y)
block-obj-$(CONFIG_POSIX) += posix-aio-compat.o
block-obj-$(CONFIG_LINUX_AIO) += linux-aio.o
-# Replication agent
-replication-nested-y = repagent_client.o repagent.o repcmd_listener.o
-replication-obj-y = $(addprefix replication/, $(replication-nested-y))
-block-obj-y += $(replication-obj-y)
+# Replication agent block driver - repagent
+repagent-nested-y = repagent_client.o repagent.o repcmd_listener.o
+repagent-obj-y = $(addprefix block/repagent/, $(repagent-nested-y))
+block-obj-y += $(repagent-obj-y)
block-nested-y += raw.o cow.o qcow.o vdi.o vmdk.o cloop.o dmg.o bochs.o
vpc.o vvfat.o
block-nested-y += qcow2.o qcow2-refcount.o qcow2-cluster.o qcow2-snapshot.o
qcow2-cache.o
@@ -80,7 +80,7 @@ fsdev-obj-$(CONFIG_VIRTFS) += $(addprefix fsdev/,
$(fsdev-nested-y))
# single QEMU executable should support all CPUs and machines.
common-obj-y = $(block-obj-y) blockdev.o
-common-obj-y += $(replication-obj-$(CONFIG_REPLICATION))
+common-obj-y += $(repagent-obj-$(CONFIG_REPAGENT))
common-obj-y += $(net-obj-y)
common-obj-y += $(qobject-obj-y)
common-obj-$(CONFIG_LINUX) += $(fsdev-obj-$(CONFIG_LINUX))
diff --git a/block.c b/block.c
index 4809416..78756d8 100644
--- a/block.c
+++ b/block.c
@@ -32,8 +32,8 @@
#include "qmp-commands.h"
#include "qemu-timer.h"
-#ifdef CONFIG_REPLICATION
-#include "replication/repagent.h"
+#ifdef CONFIG_REPAGENT
+#include "block/repagent/repagent.h"
#endif
#ifdef CONFIG_BSD
@@ -753,7 +753,7 @@ int bdrv_open(BlockDriverState *bs, const char
*filename, int flags,
goto unlink_and_fail;
}
-#ifdef CONFIG_REPLICATION
+#ifdef CONFIG_REPAGENT
repagent_register_drive(filename, bs);
#endif
/* Open the image */
@@ -1850,7 +1850,7 @@ static int coroutine_fn
bdrv_co_do_writev(BlockDriverState *bs,
}
-#ifdef CONFIG_REPLICATION
+#ifdef CONFIG_REPAGENT
if (bs->device_name[0] != '\0') {
/* We split the IO only at the highest stack driver layer.
Currently we know that by checking device_name - only
diff --git a/block/repagent/qemu-repagent.txt
b/block/repagent/qemu-repagent.txt
new file mode 100644
index 0000000..e3b0c1e
--- /dev/null
+++ b/block/repagent/qemu-repagent.txt
@@ -0,0 +1,104 @@
+ repagent - replication agent - a Qemu module for enabling
continuous async replication of VM volumes
+
+Introduction
+ This document describes a feature in Qemu - a replication
agent (AKA Repagent).
+ The Repagent is a new module that exposes an API to an
external replication system (AKA Rephub).
+ This API allows a Rephub to communicate with a Qemu VM and
continuously replicate its volumes.
+ The imlementation of a Rephub is outside of the scope of this
document. There may be several various Rephub
+ implenetations using the same repagent in Qemu.
+
+Main feature of Repagent
+ Repagent does the following:
+ * Report volumes - report a list of all volumes in a VM to
the Rephub.
+ * Report writes to a volume - send all writes made to a
protected volume to the Rephub.
+ The reporting of an IO is asyncronuous - i.e.
the IO is not delayed by the Repagent to get any acknowledgement from the
Rephub.
+ It is only copied to the Rephub.
+ * Read a protected volume - allows the Rephub to read a
protected volume, to enable the protected hub to syncronize the content of
a protected volume.
+
+Description of the Repagent module
+
+Build and run options
+ New configure option: --enable-replication
+ New command line option:
+ -repagent [hub IP/name]
+
Enable replication support for disks
+
hub is the ip or name of the machine running the replication hub.
+
+Module APIs
+ The Repagent module interfaces two main components:
+ 1. The Rephub - An external API based on socket messages
+ 2. The generic block layer- block.c
+
+ Rephub message API
+ The external replication API is a message
based API.
+ We won't go into the structure of the
messages here - just the sematics.
+
+ Messages list
+ (The updated list and
comments are in Rephub_cmds.h)
+
+ Messages from the Repagent to
the Rephub:
+ * Protected write
+ The Repagent
sends each write to a protected volume to the hub with the IO status.
+ In case the
status is bad the write content is not sent
+ * Report VM volumes
+ The agent
reports all the volumes of the VM to the hub.
+ * Read Volume Response
+ A response to
a Read Volume Request
+ Sends the
data read from a protected volume to the hub
+ * Agent shutdown
+ Notifies the
hub that the agent is about to shutdown.
+ This allows a
graceful shutdown. Any disconnection of an agent without
+ sending this
command will result in a full sync of the VM volumes.
+
+ Messages from the Rephub to
the Repagent:
+ * Start protect
+ The hub
instructs the agent to start protecting a volume. When a volume is protected
+ all its
writes are sent to to the hub.
+ With this
command the hub also assigns a volume ID to the given volume name.
+ * Read volume request
+ The hub
issues a read IO to a protected volume.
+ This command
is used during sync - when the hub needs to read unsyncronized
+ sections of a
protected volume.
+ This command
is a request, the read data is returned by the read volume response message
(see above).
+ block.c API
+ The API to the generic block storage layer
contains 3 functionalities:
+ 1. Handle writes to protected volumes
+ In bdrv_co_do_writev, each
write is reported to the Repagent module.
+ 2. Handle each new volume that registers
+ In bdrv_open - each new
bottom-level block driver that registers is reported.
+ 2. Read from a volume
+ Repagent calls bdrv_aio_readv
to handle read requests coming from the hub.
+
+
+General description of a Rephub - a replication system the repagent
connects to
+ This section describes in high level a sample Rephub - a
replication system that uses the repagent API
+ to replicate disks.
+ It describes a simple Rephub that comntinuously maintains a
mirror of the volumes of a VM.
+
+ Say we have a VM we want to protect - call it PVM, say it has
2 volumes - V1, V2.
+ Our Rephub is called SingleRephub - a Rephub protecting a
single VM.
+
+ Preparations
+ 1. The user chooses a host to rub SingleRephub - a different
host than PVM, call it Host2
+ 2. The user creates two volumes on Host2 - same sizes of V1
and V2, call them V1R (V1 recovery) and V2R.
+ 3. The user runs SingleRephub process on Host2, and gives V1R
and V2R as command line arguments.
+ From now on SingleRephub waits for the
protected VM repagent to connect.
+ 4. The user runs the protected VM PVM - and uses the switch
-repagent <Host2 IP>.
+
+ Runtime
+ 1. The repagent module connects to SingleRephub on startup.
+ 2. repagent reports V1 and V2 to SingleRephub.
+ 3. SingleRephub starts to perform an initial synchronization
of the protected volumes-
+ it reads each protected volume (V1 and V2) -
using read volume requests - and copies the data into the
+ recovery volume V1R and V2R.
+ 4. SingleRephub enters 'protection' mode - each write to the
protected volume is sent by the repagent to the Rephub,
+ and the Rephub performs the write on the
matching recovery volume.
+
+ * Note that during stage 3 writes to the protected volumes
are not ignored - they're kept in a bitmap,
+ and will be read again when stage 3 ends, in
an interative convergin process.
+
+ This flow continuously maintains an updated recovery volume.
+ If the protected system is damaged, the user can create a new
VM on Host2 with the replicated volumes attached to it.
+ The new VM is a replica of the protected system.
+
+
diff --git a/block/repagent/repagent.c b/block/repagent/repagent.c
new file mode 100644
index 0000000..c291915
--- /dev/null
+++ b/block/repagent/repagent.c
@@ -0,0 +1,327 @@
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <stdint.h>
+
+#include "block.h"
+#include "rephub_defs.h"
+#include "block_int.h"
+#include "repagent_client.h"
+#include "repagent.h"
+#include "rephub_cmds.h"
+
+#define ZERO_MEM_OBJ(pObj) memset(pObj, 0, sizeof(*pObj))
+#define REPAGENT_MAX_NUM_VOLUMES (64)
+#define REPAGENT_VOLUME_ID_NONE (0)
+
+typedef struct RepagentVolume {
+ uint64_t vol_id;
+ const char *vol_path;
+ BlockDriverState *driver_ptr;
+} RepagentVolume;
+
+struct RepAgentState {
+ int is_init;
+ int num_volumes;
+ RepagentVolume *volumes[REPAGENT_MAX_NUM_VOLUMES];
+};
+
+typedef struct RepagentReadVolIo {
+ QEMUIOVector qiov;
+ RepCmdReadVolReq rep_cmd;
+ uint8_t *buf;
+ struct timeval start_time;
+} RepagentReadVolIo;
+
+static int repagent_get_volume_by_name(const char *name);
+static void repagent_report_volumes_to_hub(void);
+static void repagent_vol_read_done(void *opaque, int ret);
+static struct timeval tsub(struct timeval t1, struct timeval t2);
+
+RepAgentState g_rep_agent = { 0 };
+
+void repagent_init(const char *hubname, int port)
+{
+ /* It is the responsibility of the thread to free this struct */
+ rephub_params *pParams = (rephub_params
*)g_malloc(sizeof(rephub_params));
+ if (hubname == NULL) {
+ hubname = "127.0.0.1";
+ }
+ if (port == 0) {
+ port = 9010;
+ }
+
+ printf("repagent_init %s\n", hubname);
+
+ pParams->port = port;
+ pParams->name = g_strdup(hubname);
+
+ pthread_t thread_id = 0;
+
+ /* Create the repagent client listener thread */
+ pthread_create(&thread_id, 0, repagent_listen, (void *) pParams);
+ pthread_detach(thread_id);
+}
+
+void repagent_register_drive(const char *drive_path,
+ BlockDriverState *driver_ptr)
+{
+ int i;
+ for (i = 0; i < g_rep_agent.num_volumes ; i++) {
+ RepagentVolume *vol = g_rep_agent.volumes[i];
+ if (vol != NULL) {
+ assert(
+ strcmp(drive_path, vol->vol_path) != 0
+ && driver_ptr != vol->driver_ptr);
+ }
+ }
+
+ assert(g_rep_agent.num_volumes < REPAGENT_MAX_NUM_VOLUMES);
+
+ printf("zerto repagent: Registering drive. Num drives %d, path %s\n",
+ g_rep_agent.num_volumes, drive_path);
+ g_rep_agent.volumes[i] =
+ (RepagentVolume *)g_malloc(sizeof(RepagentVolume));
+ g_rep_agent.volumes[i]->driver_ptr = driver_ptr;
+ /* orim todo strcpy? */
+ g_rep_agent.volumes[i]->vol_path = drive_path;
+
+ /* Orim todo thread-safety? */
+ g_rep_agent.num_volumes++;
+
+ repagent_report_volumes_to_hub();
+}
+
+/* orim todo destruction? */
+
+static RepagentVolume *repagent_get_protected_volume_by_driver(
+ BlockDriverState *bs)
+{
+ /* orim todo optimize search */
+ int i = 0;
+ for (i = 0; i < g_rep_agent.num_volumes ; i++) {
+ RepagentVolume *p_vol = g_rep_agent.volumes[i];
+ if (p_vol != NULL && p_vol->driver_ptr == (void *) bs) {
+ return p_vol;
+ }
+ }
+ return NULL;
+}
+
+void repagent_handle_protected_write(BlockDriverState *bs, int64_t
sector_num,
+ int nb_sectors, QEMUIOVector *qiov, int ret_status)
+{
+ printf("zerto Protected write offset %lld, size %d, IO return status
%d",
+ (long long int) sector_num, nb_sectors, ret_status);
+ if (bs->filename != NULL) {
+ printf(", filename %s", bs->filename);
+ }
+
+ printf("\n");
+
+ RepagentVolume *p_vol = repagent_get_protected_volume_by_driver(bs);
+ if (p_vol == NULL || p_vol->vol_id == REPAGENT_VOLUME_ID_NONE) {
+ /* Unprotected */
+ printf("Got a write to an unprotected volume.\n");
+ return;
+ }
+
+ /* Report IO to rephub */
+
+ int data_size = qiov->size;
+ if (ret_status < 0) {
+ /* On failed ios we don't send the data to the hub */
+ data_size = 0;
+ }
+ uint8_t *pdata = NULL;
+ RepCmdProtectedWrite *p_cmd = (RepCmdProtectedWrite *) repcmd_new(
+ REPHUB_CMD_PROTECTED_WRITE, data_size, (uint8_t **) &pdata);
+
+ if (ret_status >= 0) {
+ qemu_iovec_to_buffer(qiov, pdata);
+ }
+
+ p_cmd->volume_id = p_vol->vol_id;
+ p_cmd->offset_sectors = sector_num;
+ p_cmd->size_sectors = nb_sectors;
+ p_cmd->ret_status = ret_status;
+
+ if (repagent_client_send((RepCmd *) p_cmd) != 0) {
+ printf("Error sending command\n");
+ }
+}
+
+static void repagent_report_volumes_to_hub(void)
+{
+ /* Report IO to rephub */
+ int i;
+ RepCmdDataReportVmVolumes *p_cmd_data = NULL;
+ RepCmdReportVmVolumes *p_cmd = (RepCmdReportVmVolumes *) repcmd_new(
+ REPHUB_CMD_REPORT_VM_VOLUMES,
+ g_rep_agent.num_volumes * sizeof(RepVmVolumeInfo),
+ (uint8_t **) &p_cmd_data);
+ p_cmd->num_volumes = g_rep_agent.num_volumes;
+ printf("reporting %u volumes\n", g_rep_agent.num_volumes);
+ for (i = 0; i < g_rep_agent.num_volumes ; i++) {
+ assert(g_rep_agent.volumes[i] != NULL);
+ printf("reporting volume %s size %u\n",
+ g_rep_agent.volumes[i]->vol_path,
+ (uint32_t) sizeof(p_cmd_data->volumes[i].name));
+ strncpy((char *) p_cmd_data->volumes[i].name,
+ g_rep_agent.volumes[i]->vol_path,
+ sizeof(p_cmd_data->volumes[i].name));
+ p_cmd_data->volumes[i].volume_id = g_rep_agent.volumes[i]->vol_id;
+ }
+ if (repagent_client_send((RepCmd *) p_cmd) != 0) {
+ printf("Error sending command\n");
+ }
+}
+
+int repaget_start_protect(RepCmdStartProtect *pcmd,
+ RepCmdDataStartProtect *pcmd_data)
+{
+ printf("Start protect vol %s, ID %llu\n", pcmd_data->volume_name,
+ (unsigned long long) pcmd->volume_id);
+ int vol_index = repagent_get_volume_by_name(pcmd_data->volume_name);
+ if (g_rep_agent.num_volumes > 0
+ && strcmp(pcmd_data->volume_name, "stam") == 0) {
+ /* Choose the first one for rephub */
+ vol_index = 0;
+ }
+ if (vol_index < 0) {
+ printf("The volume doesn't exist\n");
+ return TRUE;
+ }
+ /* orim todo protect */
+ g_rep_agent.volumes[vol_index]->vol_id = pcmd->volume_id;
+
+ return TRUE;
+}
+
+static int repagent_get_volume_by_name(const char *name)
+{
+ int i = 0;
+ for (i = 0; i < g_rep_agent.num_volumes ; i++) {
+ if (g_rep_agent.volumes[i] != NULL
+ && strcmp(name, g_rep_agent.volumes[i]->vol_path) == 0) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+static int repagent_get_volume_by_id(uint64_t vol_id)
+{
+ int i = 0;
+ for (i = 0; i < g_rep_agent.num_volumes ; i++) {
+ if (g_rep_agent.volumes[i] != NULL
+ && g_rep_agent.volumes[i]->vol_id == vol_id) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+int repaget_read_vol(RepCmdReadVolReq *pcmd, uint8_t *pdata)
+{
+ int index = repagent_get_volume_by_id(pcmd->volume_id);
+ int size_bytes = pcmd->size_sectors * 512;
+ if (index < 0) {
+ printf("Vol read - Could not find vol id %llx\n",
+ (unsigned long long int) pcmd->volume_id);
+ RepCmdReadVolRes *p_res_cmd = (RepCmdReadVolRes *) repcmd_new(
+ REPHUB_CMD_READ_VOL_RES, 0, NULL);
+ p_res_cmd->req_id = pcmd->req_id;
+ p_res_cmd->volume_id = pcmd->volume_id;
+ p_res_cmd->is_status_success = FALSE;
+ repagent_client_send((RepCmd *) p_res_cmd);
+ return TRUE;
+ }
+
+ printf("Vol read - driver %p, volId %llu, offset %llu, size %u\n",
+ g_rep_agent.volumes[index]->driver_ptr,
+ (unsigned long long int) pcmd->volume_id,
+ (unsigned long long int) pcmd->offset_sectors,
pcmd->size_sectors);
+
+ {
+ RepagentReadVolIo *read_xact = calloc(1,
sizeof(RepagentReadVolIo));
+
+/* BlockDriverAIOCB *acb; */
+
+ ZERO_MEM_OBJ(read_xact);
+
+ qemu_iovec_init(&read_xact->qiov, 1);
+
+ /*read_xact->buf =
+ qemu_blockalign(g_rep_agent.volumes[index]->driver_ptr,
size_bytes); */
+ read_xact->buf = (uint8_t *) g_malloc(size_bytes);
+ read_xact->rep_cmd = *pcmd;
+ qemu_iovec_add(&read_xact->qiov, read_xact->buf, size_bytes);
+
+ gettimeofday(&read_xact->start_time, NULL);
+ /* orim TODO - use the returned acb to cancel the request on
shutdown */
+ /*acb = */bdrv_aio_readv(g_rep_agent.volumes[index]->driver_ptr,
+ read_xact->rep_cmd.offset_sectors, &read_xact->qiov,
+ read_xact->rep_cmd.size_sectors, repagent_vol_read_done,
+ read_xact);
+ }
+
+ return TRUE;
+}
+
+static void repagent_vol_read_done(void *opaque, int ret)
+{
+ struct timeval t2;
+ RepagentReadVolIo *read_xact = (RepagentReadVolIo *) opaque;
+ uint8_t *pdata = NULL;
+ RepCmdReadVolRes *pcmd = (RepCmdReadVolRes *) repcmd_new(
+ REPHUB_CMD_READ_VOL_RES, read_xact->rep_cmd.size_sectors * 512,
+ &pdata);
+ pcmd->req_id = read_xact->rep_cmd.req_id;
+ pcmd->volume_id = read_xact->rep_cmd.volume_id;
+ pcmd->is_status_success = FALSE;
+
+ printf("Protected vol read - volId %llu, offset %llu, size %u\n",
+ (unsigned long long int) read_xact->rep_cmd.volume_id,
+ (unsigned long long int) read_xact->rep_cmd.offset_sectors,
+ read_xact->rep_cmd.size_sectors);
+ gettimeofday(&t2, NULL);
+
+ if (ret >= 0) {
+ /* Read response - send the data to the hub */
+ t2 = tsub(t2, read_xact->start_time);
+ printf("Read prot vol done. Took %u seconds, %u us.",
+ (uint32_t) t2.tv_sec, (uint32_t) t2.tv_usec);
+
+ pcmd->is_status_success = TRUE;
+ /* orim todo optimize - don't copy, use the qiov buffer */
+ qemu_iovec_to_buffer(&read_xact->qiov, pdata);
+ } else {
+ printf("readv failed: %s\n", strerror(-ret));
+ }
+
+ repagent_client_send((RepCmd *) pcmd);
+
+ /*qemu_vfree(read_xact->buf); */
+ g_free(read_xact->buf);
+
+ g_free(read_xact);
+}
+
+static struct timeval tsub(struct timeval t1, struct timeval t2)
+{
+ t1.tv_usec -= t2.tv_usec;
+ if (t1.tv_usec < 0) {
+ t1.tv_usec += 1000000;
+ t1.tv_sec--;
+ }
+ t1.tv_sec -= t2.tv_sec;
+ return t1;
+}
+
+void repagent_client_connected(void)
+{
+ /* orim todo thread protection */
+ repagent_report_volumes_to_hub();
+}
diff --git a/block/repagent/repagent.h b/block/repagent/repagent.h
new file mode 100644
index 0000000..98ccbf2
--- /dev/null
+++ b/block/repagent/repagent.h
@@ -0,0 +1,46 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
copy
+ * of this software and associated documentation files (the "Software"),
to deal
+ * in the Software without restriction, including without limitation the
rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN
+ * THE SOFTWARE.
+ */
+#ifndef REPAGENT_H
+#define REPAGENT_H
+#include <stdint.h>
+
+#include "qemu-common.h"
+
+typedef struct RepAgentState RepAgentState;
+typedef struct RepCmdStartProtect RepCmdStartProtect;
+typedef struct RepCmdDataStartProtect RepCmdDataStartProtect;
+struct RepCmdReadVolReq;
+
+void repagent_init(const char *hubname, int port);
+void repagent_handle_protected_write(BlockDriverState *bs,
+ int64_t sector_num, int nb_sectors, QEMUIOVector *qiov, int
ret_status);
+void repagent_register_drive(const char *drive_path,
+ BlockDriverState *driver_ptr);
+int repaget_start_protect(RepCmdStartProtect *pcmd,
+ RepCmdDataStartProtect *pcmd_data);
+int repaget_read_vol(struct RepCmdReadVolReq *pcmd, uint8_t *pdata);
+void repagent_client_connected(void);
+
+
+#endif /* REPAGENT_H */
diff --git a/block/repagent/repagent_client.c
b/block/repagent/repagent_client.c
new file mode 100644
index 0000000..9ed8485
--- /dev/null
+++ b/block/repagent/repagent_client.c
@@ -0,0 +1,162 @@
+#include "repcmd.h"
+#include "rephub_cmds.h"
+#include "repcmd_listener.h"
+#include "repagent_client.h"
+#include "repagent.h"
+#include "main-loop.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stdio.h>
+#include <resolv.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <unistd.h>
+
+#define ZERO_MEM_OBJ(pObj) memset(pObj, 0, sizeof(*pObj))
+
+static void repagent_process_cmd(RepCmd *pCmd, uint8_t *pData, void
*clientPtr);
+
+typedef struct repagent_client_state {
+ int is_connected;
+ int is_terminate_receive;
+ int hsock;
+} repagent_client_state;
+
+static repagent_client_state g_client_state = { 0 };
+
+static void repagent_client_read(void *opaque)
+{
+ printf("repagent_client_read\n");
+ int bytes_read =
repcmd_listener_socket_read_next_buf(g_client_state.hsock);
+ if (bytes_read <= 0) {
+ printf("repagent_client_read failed (%d), errno=%d\n",
+ bytes_read, errno);
+ g_client_state.is_connected = 0;
+ }
+}
+
+void *repagent_listen(void *pParam)
+{
+ rephub_params *pServerParams = (rephub_params *) pParam;
+ int host_port = pServerParams->port;
+ const char *host_name = pServerParams->name;
+
+ printf("Creating repagent listener thread...\n");
+ g_free(pServerParams);
+
+ struct sockaddr_in my_addr;
+
+ int err;
+ int retries = 0;
+
+ g_client_state.hsock = socket(AF_INET, SOCK_STREAM, 0);
+ if (g_client_state.hsock == -1) {
+ printf("Error initializing socket %d\n", errno);
+ return (void *) -1;
+ }
+
+ int param = 1;
+
+ if ((setsockopt(g_client_state.hsock, SOL_SOCKET, SO_REUSEADDR,
+ (char *) ¶m, sizeof(int)) == -1)
+ || (setsockopt(g_client_state.hsock, SOL_SOCKET, SO_KEEPALIVE,
+ (char *) ¶m, sizeof(int)) == -1)) {
+ printf("Error setting options %d\n", errno);
+ return (void *) -1;
+ }
+
+ my_addr.sin_family = AF_INET;
+ my_addr.sin_port = htons(host_port);
+ memset(&(my_addr.sin_zero), 0, 8);
+
+ my_addr.sin_addr.s_addr = inet_addr(host_name);
+
+ /* Reconnect loop */
+ while (!g_client_state.is_terminate_receive) {
+
+ if (connect(g_client_state.hsock, (struct sockaddr *) &my_addr,
+ sizeof(my_addr)) == -1) {
+ err = errno;
+ if (err != EINPROGRESS) {
+ retries++;
+ fprintf(
+ stderr,
+ "Error connecting socket %d. Host %s, port %u.
Retry count %d\n",
+ errno, host_name, host_port, retries);
+ usleep(5 * 1000 * 1000);
+ continue;
+ }
+ }
+ retries = 0;
+
+ printf("After connect\n");
+ g_client_state.is_connected = 1;
+ repagent_client_connected();
+ repcmd_listener_init(repagent_process_cmd, NULL);
+ static int c;
+ /* repcmd_listener_socket_thread_listener(g_client_state.hsock); */
+ qemu_set_fd_handler(g_client_state.hsock, repagent_client_read,
NULL,
+ NULL);
+ while (g_client_state.is_connected) {
+ printf("Connected (%d)...\n", c++);
+ usleep(1 * 1000 * 1000);
+ }
+ /* Unregister */
+ qemu_set_fd_handler(g_client_state.hsock, NULL, NULL, NULL);
+
+ printf("Disconnected\n");
+ g_client_state.is_connected = 0;
+ close(g_client_state.hsock);
+
+ }
+ return 0;
+}
+
+void repagent_process_cmd(RepCmd *pcmd, uint8_t *pdata, void *clientPtr)
+{
+ int is_free_data = 1;
+ printf("Repagent got cmd %d\n", pcmd->hdr.cmdid);
+ switch (pcmd->hdr.cmdid) {
+ case REPHUB_CMD_START_PROTECT: {
+ is_free_data = repaget_start_protect((RepCmdStartProtect *) pcmd,
+ (RepCmdDataStartProtect *) pdata);
+ }
+ break;
+ case REPHUB_CMD_READ_VOL_REQ: {
+ is_free_data = repaget_read_vol((RepCmdReadVolReq *) pcmd, pdata);
+ }
+ break;
+ default:
+ assert(0);
+ break;
+
+ }
+
+ if (is_free_data) {
+ g_free(pdata);
+ }
+}
+
+int repagent_client_send(RepCmd *p_cmd)
+{
+ int bytecount = 0;
+ printf("Send cmd %u, data size %u\n", p_cmd->hdr.cmdid,
+ p_cmd->hdr.data_size_bytes);
+ if (!g_client_state.is_connected) {
+ printf("Not connected to hub\n");
+ return -1;
+ }
+
+ bytecount = send(g_client_state.hsock, p_cmd,
+ sizeof(RepCmd) + p_cmd->hdr.data_size_bytes, 0);
+ if (bytecount < sizeof(RepCmd) + p_cmd->hdr.data_size_bytes) {
+ printf("Bad send %d, errno %d\n", bytecount, errno);
+ return bytecount;
+ }
+
+ /* Success */
+ return 0;
+}
diff --git a/block/repagent/repagent_client.h
b/block/repagent/repagent_client.h
new file mode 100644
index 0000000..62a5377
--- /dev/null
+++ b/block/repagent/repagent_client.h
@@ -0,0 +1,36 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
copy
+ * of this software and associated documentation files (the "Software"),
to deal
+ * in the Software without restriction, including without limitation the
rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN
+ * THE SOFTWARE.
+ */
+#ifndef REPAGENT_CLIENT_H
+#define REPAGENT_CLIENT_H
+#include "repcmd.h"
+
+typedef struct rephub_params {
+ char *name;
+ int port;
+} rephub_params;
+
+void *repagent_listen(void *pParam);
+int repagent_client_send(RepCmd *p_cmd);
+
+#endif /* REPAGENT_CLIENT_H */
diff --git a/block/repagent/repcmd.h b/block/repagent/repcmd.h
new file mode 100644
index 0000000..8c6cf1b
--- /dev/null
+++ b/block/repagent/repcmd.h
@@ -0,0 +1,59 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
copy
+ * of this software and associated documentation files (the "Software"),
to deal
+ * in the Software without restriction, including without limitation the
rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN
+ * THE SOFTWARE.
+ */
+#ifndef REPCMD_H
+#define REPCMD_H
+
+#include <stdint.h>
+
+#define REPCMD_MAGIC1 (0x1122)
+#define REPCMD_MAGIC2 (0x3344)
+#define REPCMD_NUM_U32_PARAMS (11)
+
+enum RepCmds {
+ REPCMD_FIRST_INVALID = 0,
+ REPCMD_FIRST_HUBCMD = 1,
+ REPHUB_CMD_PROTECTED_WRITE = 2,
+ REPHUB_CMD_REPORT_VM_VOLUMES = 3,
+ REPHUB_CMD_START_PROTECT = 4,
+ REPHUB_CMD_READ_VOL_REQ = 5,
+ REPHUB_CMD_READ_VOL_RES = 6,
+ REPHUB_CMD_AGENT_SHUTDOWN = 7,
+};
+
+typedef struct RepCmdHdr {
+ uint16_t magic1;
+ uint16_t cmdid;
+ uint32_t data_size_bytes;
+} RepCmdHdr;
+
+typedef struct RepCmd {
+ RepCmdHdr hdr;
+ unsigned int parameters[REPCMD_NUM_U32_PARAMS];
+ unsigned int magic2;
+ uint8_t data[0];
+} RepCmd;
+
+RepCmd *repcmd_new(int cmd_id, int data_size, uint8_t **p_out_pdata);
+
+#endif /* REPCMD_H */
diff --git a/block/repagent/repcmd_listener.c
b/block/repagent/repcmd_listener.c
new file mode 100644
index 0000000..54d3f60
--- /dev/null
+++ b/block/repagent/repcmd_listener.c
@@ -0,0 +1,173 @@
+#include <fcntl.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <stdio.h>
+#include <netinet/in.h>
+#include <resolv.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <assert.h>
+
+/* Use the CONFIG_REPAGENT flag to determine whether
+ * we're under qemu build or a hub When under
+ * qemu use g_malloc */
+#ifdef CONFIG_REPAGENT
+#include <glib.h>
+#define REPCMD_MALLOC g_malloc
+#else
+#define REPCMD_MALLOC malloc
+#endif
+
+#include "repcmd.h"
+#include "repcmd_listener.h"
+
+#define ZERO_MEM_OBJ(pObj) memset((void *)pObj, 0, sizeof(*pObj))
+
+
+typedef struct RepCmdRxCmdState {
+ RepCmd curCmd;
+ uint8_t *pReadBuf;
+ int bytesToGet;
+ int bytesGotten;
+ int isGotHeader;
+ uint8_t *pdata;
+} RepCmdRxCmdState;
+
+typedef struct RepCmdListenerState {
+ int is_terminate_receive;
+ pfn_received_cmd_cb receive_cb;
+ void *opaque;
+ int hsock;
+ RepCmdRxCmdState cur_cmd;
+} RepCmdListenerState;
+
+static RepCmdListenerState g_listenerState = { 0 };
+
+static int repcmd_listener_process_rx(int bytecount);
+
+void repcmd_listener_init(pfn_received_cmd_cb callback, void *opaque)
+{
+ ZERO_MEM_OBJ(&g_listenerState);
+ g_listenerState.receive_cb = callback;
+ g_listenerState.opaque = opaque;
+
+ g_listenerState.cur_cmd.bytesToGet = sizeof(RepCmd);
+ g_listenerState.cur_cmd.pReadBuf =
+ (uint8_t *) &g_listenerState.cur_cmd.curCmd;
+}
+
+int repcmd_listener_socket_read_next_buf(int hsock)
+{
+ RepCmdRxCmdState *cmd_state = &g_listenerState.cur_cmd;
+ int bytecount = recv(hsock, cmd_state->pReadBuf +
cmd_state->bytesGotten,
+ cmd_state->bytesToGet - cmd_state->bytesGotten, 0);
+ return repcmd_listener_process_rx(bytecount);
+}
+
+/* Returns 0 for initiated termination or socket error value on error */
+int repcmd_listener_socket_thread_listener(int hsock)
+{
+ int ret = 0;
+ /* receive loop */
+ while (!g_listenerState.is_terminate_receive) {
+ ret = repcmd_listener_socket_read_next_buf(hsock);
+ if (ret <= 0) {
+ return ret;
+ }
+ }
+ return 0;
+}
+
+static int repcmd_listener_process_rx(int bytecount)
+{
+ RepCmdRxCmdState *cmd_state = &g_listenerState.cur_cmd;
+ if (bytecount == -1) {
+ fprintf(stderr, "Error receiving data %d\n", errno);
+ return errno;
+ }
+
+ if (bytecount == 0) {
+ printf("Disconnected\n");
+ return 0;
+ }
+ cmd_state->bytesGotten += bytecount;
+/* printf("Recieved bytes %d, got %d/%d\n",
+ bytecount, cmd_state->bytesGotten, cmd_state->bytesToGet); */
+ /* print content */
+ if (0) {
+ int i;
+ for (i = 0; i < bytecount ; i += 4) {
+ /*printf("%d/%d", i, bytecount/4); */
+ printf(
+ "%#x ",
+ *(int *) (&cmd_state->pReadBuf[cmd_state->bytesGotten
+ - bytecount + i]));
+
+ }
+ printf("\n");
+ }
+ assert(cmd_state->bytesGotten <= cmd_state->bytesToGet);
+ if (cmd_state->bytesGotten == cmd_state->bytesToGet) {
+ int isGotData = 0;
+ cmd_state->bytesGotten = 0;
+ if (!cmd_state->isGotHeader) {
+ /* We just got the header */
+ cmd_state->isGotHeader = 1;
+
+ assert(cmd_state->curCmd.hdr.magic1 == REPCMD_MAGIC1);
+ assert(cmd_state->curCmd.magic2 == REPCMD_MAGIC2);
+ if (cmd_state->curCmd.hdr.data_size_bytes > 0) {
+ cmd_state->pdata = (uint8_t *)REPCMD_MALLOC(
+ cmd_state->curCmd.hdr.data_size_bytes);
+/* printf("malloc %p\n", cmd_state->pdata); */
+ cmd_state->pReadBuf = cmd_state->pdata;
+ } else {
+ /* no data */
+ isGotData = 1;
+ cmd_state->pdata = NULL;
+ }
+ cmd_state->bytesToGet = cmd_state->curCmd.hdr.data_size_bytes;
+ } else {
+ isGotData = 1;
+ }
+
+ if (isGotData) {
+ /* Got command and data */
+ (*g_listenerState.receive_cb)(&cmd_state->curCmd,
cmd_state->pdata,
+ g_listenerState.opaque);
+
+ /* It's the callee responsibility to free cmd_state->pdata */
+ cmd_state->pdata = NULL;
+ ZERO_MEM_OBJ(&cmd_state->curCmd);
+ cmd_state->pReadBuf = (uint8_t *) &cmd_state->curCmd;
+ cmd_state->bytesGotten = 0;
+ cmd_state->bytesToGet = sizeof(RepCmd);
+ cmd_state->isGotHeader = 0;
+ }
+ }
+ return bytecount;
+}
+
+RepCmd *repcmd_new(int cmd_id, int data_size, uint8_t **p_out_pdata)
+{
+ RepCmd *p_cmd = (RepCmd *)REPCMD_MALLOC(sizeof(RepCmd) + data_size);
+ assert(p_cmd != NULL);
+
+ /* Zero the CMD (not the data) */
+ ZERO_MEM_OBJ(p_cmd);
+
+ p_cmd->hdr.cmdid = cmd_id;
+ p_cmd->hdr.magic1 = REPCMD_MAGIC1;
+ p_cmd->magic2 = REPCMD_MAGIC2;
+ p_cmd->hdr.data_size_bytes = data_size;
+
+ if (p_out_pdata != NULL) {
+ *p_out_pdata = p_cmd->data;
+ }
+
+ return p_cmd;
+}
+
diff --git a/block/repagent/repcmd_listener.h
b/block/repagent/repcmd_listener.h
new file mode 100644
index 0000000..19b9ea9
--- /dev/null
+++ b/block/repagent/repcmd_listener.h
@@ -0,0 +1,34 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
copy
+ * of this software and associated documentation files (the "Software"),
to deal
+ * in the Software without restriction, including without limitation the
rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN
+ * THE SOFTWARE.
+ */
+#ifndef REPCMD_LISTENER_H
+#define REPCMD_LISTENER_H
+#include <stdint.h>
+typedef void (*pfn_received_cmd_cb)(RepCmd *pcmd,
+ uint8_t *pdata, void *opaque);
+
+void repcmd_listener_init(pfn_received_cmd_cb callback, void *opaque);
+int repcmd_listener_socket_read_next_buf(int hsock);
+int repcmd_listener_socket_thread_listener(int hsock);
+
+#endif /* REPCMD_LISTENER_H */
diff --git a/block/repagent/rephub_cmds.h b/block/repagent/rephub_cmds.h
new file mode 100644
index 0000000..3bd4eb4
--- /dev/null
+++ b/block/repagent/rephub_cmds.h
@@ -0,0 +1,151 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
copy
+ * of this software and associated documentation files (the "Software"),
to deal
+ * in the Software without restriction, including without limitation the
rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN
+ * THE SOFTWARE.
+ */
+#ifndef REPHUB_CMDS_H
+#define REPHUB_CMDS_H
+
+#include <stdint.h>
+#include "repcmd.h"
+#include "rephub_defs.h"
+
+/*********************************************************
+ * RepCmd Report a protected IO
+ *
+ * REPHUB_CMD_PROTECTED_WRITE
+ * Direction: agent->hub
+ *
+ * Any write of a protected volume is send with this
+ * message to the hub, with its status.
+ * When case the status is bad no data is sent
+ *********************************************************/
+typedef struct RepCmdProtectedWrite {
+ RepCmdHdr hdr;
+ uint64_t volume_id;
+ uint64_t offset_sectors;
+ /* The size field duplicates the RepCmd size,
+ * but it is needed for reporting failed IOs' sizes */
+ uint32_t size_sectors;
+ int ret_status;
+} RepCmdProtectedWrite;
+
+/*********************************************************
+ * RepCmd Report VM volumes
+ *
+ * REPHUB_CMD_REPORT_VM_VOLUMES
+ * Direction: agent->hub
+ *
+ * The agent reports all the volumes of the VM
+ * to the hub.
+ *********************************************************/
+typedef struct RepVmVolumeInfo {
+ char name[REPHUB_MAX_VOL_NAME_LEN];
+ uint64_t volume_id;
+ uint32_t size_mb;
+ uint32_t padding;
+} RepVmVolumeInfo;
+
+typedef struct RepCmdReportVmVolumes {
+ RepCmdHdr hdr;
+ int num_volumes;
+} RepCmdReportVmVolumes;
+
+typedef struct RepCmdDataReportVmVolumes {
+ RepVmVolumeInfo volumes[0];
+} RepCmdDataReportVmVolumes;
+
+
+/*********************************************************
+ * RepCmd Start protect
+ *
+ * REPHUB_CMD_START_PROTECT
+ * Direction: hub->agent
+ *
+ * The hub instructs the agent to start protecting
+ * a volume. When a volume is protected all its writes
+ * are sent to to the hub.
+ * With this command the hub also assigns a volume ID to
+ * the given volume name.
+ *********************************************************/
+typedef struct RepCmdStartProtect {
+ RepCmdHdr hdr;
+ uint64_t volume_id;
+} RepCmdStartProtect;
+
+typedef struct RepCmdDataStartProtect {
+ char volume_name[REPHUB_MAX_VOL_NAME_LEN];
+} RepCmdDataStartProtect;
+
+
+/*********************************************************
+ * RepCmd Read Volume Request
+ *
+ * REPHUB_CMD_READ_VOL_REQ
+ * Direction: hub->agent
+ *
+ * The hub issues a read IO to a protected volume.
+ * This command is used during sync - when the hub needs
+ * to read unsyncronized sections of a protected volume.
+ * This command is a request, the read data is returned
+ * by the response command REPHUB_CMD_READ_VOL_RES
+ *********************************************************/
+typedef struct RepCmdReadVolReq {
+ RepCmdHdr hdr;
+ int req_id;
+ int size_sectors;
+ uint64_t volume_id;
+ uint64_t offset_sectors;
+} RepCmdReadVolReq;
+
+/*********************************************************
+ * RepCmd Read Volume Response
+ *
+ * REPHUB_CMD_READ_VOL_RES
+ * Direction: agent->hub
+ *
+ * A response to REPHUB_CMD_READ_VOL_REQ.
+ * Sends the data read from a protected volume
+ *********************************************************/
+typedef struct RepCmdReadVolRes {
+ RepCmdHdr hdr;
+ int req_id;
+ int is_status_success;
+ uint64_t volume_id;
+} RepCmdReadVolRes;
+
+/*********************************************************
+ * RepCmd Agent shutdown
+ *
+ * REPHUB_CMD_AGENT_SHUTDOWN
+ * Direction: agent->hub
+ *
+ * Notifies the hub that the agent is about to shutdown.
+ * This allows a graceful shutdown. Any disconnection
+ * of an agent without sending this command will result
+ * in a full sync of the VM volumes.
+ *********************************************************/
+typedef struct RepCmdAgentShutdown {
+ RepCmdHdr hdr;
+} RepCmdAgentShutdown;
+
+
+#endif /* REPHUB_CMDS_H */
diff --git a/block/repagent/rephub_defs.h b/block/repagent/rephub_defs.h
new file mode 100644
index 0000000..e34e0ce
--- /dev/null
+++ b/block/repagent/rephub_defs.h
@@ -0,0 +1,40 @@
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
copy
+ * of this software and associated documentation files (the "Software"),
to deal
+ * in the Software without restriction, including without limitation the
rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN
+ * THE SOFTWARE.
+ */
+#ifndef REP_HUB_DEFS_H
+#define REP_HUB_DEFS_H
+
+#include <stdint.h>
+
+#define REPHUB_MAX_VOL_NAME_LEN (1024)
+#define REPHUB_MAX_NUM_VOLUMES (512)
+
+#ifndef TRUE
+ #define TRUE (1)
+#endif
+
+#ifndef FALSE
+ #define FALSE (0)
+#endif
+
+#endif /* REP_HUB_DEFS_H */
diff --git a/configure b/configure
index 83b74c2..3d17ae5 100755
--- a/configure
+++ b/configure
@@ -189,7 +189,7 @@ spice=""
rbd=""
smartcard=""
smartcard_nss=""
-replication=""
+repagent=""
usb_redir=""
opengl=""
zlib="yes"
@@ -807,9 +807,9 @@ for opt do
;;
--enable-smartcard-nss) smartcard_nss="yes"
;;
- --disable-replication) replication="no"
+ --disable-repagent) repagent="no"
;;
- --enable-replication) replication="yes"
+ --enable-repagent) repagent="yes"
;;
--disable-usb-redir) usb_redir="no"
;;
@@ -1109,7 +1109,7 @@ echo " --disable-usb-redir disable usb network
redirection support"
echo " --enable-usb-redir enable usb network redirection support"
echo " --disable-guest-agent disable building of the QEMU Guest Agent"
echo " --enable-guest-agent enable building of the QEMU Guest Agent"
-echo " --enable-replication enable replication support"
+echo " --enable-repagent enable replication support"
echo ""
echo "NOTE: The object files are built at the place where configure is
launched"
exit 1
@@ -3220,8 +3220,8 @@ if test "$smartcard_nss" = "yes" ; then
echo "libcacard_cflags=$libcacard_cflags" >> $config_host_mak
fi
-if test "$replication" = "yes" ; then
- echo "CONFIG_REPLICATION=y" >> $config_host_mak
+if test "$repagent" = "yes" ; then
+ echo "CONFIG_REPAGENT=y" >> $config_host_mak
fi
if test "$usb_redir" = "yes" ; then
@@ -3904,4 +3904,4 @@ if test "$docs" = "yes" ; then
mkdir -p QMP
fi
-echo "Replication $replication"
+echo "Repagent $repagent"
diff --git a/replication/qemu-repagent.txt b/replication/qemu-repagent.txt
deleted file mode 100644
index e3b0c1e..0000000
--- a/replication/qemu-repagent.txt
+++ /dev/null
@@ -1,104 +0,0 @@
- repagent - replication agent - a Qemu module for enabling
continuous async replication of VM volumes
-
-Introduction
- This document describes a feature in Qemu - a replication
agent (AKA Repagent).
- The Repagent is a new module that exposes an API to an
external replication system (AKA Rephub).
- This API allows a Rephub to communicate with a Qemu VM and
continuously replicate its volumes.
- The imlementation of a Rephub is outside of the scope of
this document. There may be several various Rephub
- implenetations using the same repagent in Qemu.
-
-Main feature of Repagent
- Repagent does the following:
- * Report volumes - report a list of all volumes in a VM to
the Rephub.
- * Report writes to a volume - send all writes made to a
protected volume to the Rephub.
- The reporting of an IO is asyncronuous -
i.e. the IO is not delayed by the Repagent to get any acknowledgement from
the Rephub.
- It is only copied to the Rephub.
- * Read a protected volume - allows the Rephub to read a
protected volume, to enable the protected hub to syncronize the content of
a protected volume.
-
-Description of the Repagent module
-
-Build and run options
- New configure option: --enable-replication
- New command line option:
- -repagent [hub IP/name]
-
Enable replication support for disks
-
hub is the ip or name of the machine running the replication hub.
-
-Module APIs
- The Repagent module interfaces two main components:
- 1. The Rephub - An external API based on socket messages
- 2. The generic block layer- block.c
-
- Rephub message API
- The external replication API is a message
based API.
- We won't go into the structure of the
messages here - just the sematics.
-
- Messages list
- (The updated list and
comments are in Rephub_cmds.h)
-
- Messages from the Repagent
to the Rephub:
- * Protected write
- The Repagent
sends each write to a protected volume to the hub with the IO status.
- In case the
status is bad the write content is not sent
- * Report VM volumes
- The agent
reports all the volumes of the VM to the hub.
- * Read Volume Response
- A response
to a Read Volume Request
- Sends the
data read from a protected volume to the hub
- * Agent shutdown
- Notifies the
hub that the agent is about to shutdown.
- This allows
a graceful shutdown. Any disconnection of an agent without
- sending this
command will result in a full sync of the VM volumes.
-
- Messages from the Rephub to
the Repagent:
- * Start protect
- The hub
instructs the agent to start protecting a volume. When a volume is protected
- all its
writes are sent to to the hub.
- With this
command the hub also assigns a volume ID to the given volume name.
- * Read volume request
- The hub
issues a read IO to a protected volume.
- This command
is used during sync - when the hub needs to read unsyncronized
- sections of
a protected volume.
- This command
is a request, the read data is returned by the read volume response message
(see above).
- block.c API
- The API to the generic block storage layer
contains 3 functionalities:
- 1. Handle writes to protected volumes
- In bdrv_co_do_writev, each
write is reported to the Repagent module.
- 2. Handle each new volume that registers
- In bdrv_open - each new
bottom-level block driver that registers is reported.
- 2. Read from a volume
- Repagent calls
bdrv_aio_readv to handle read requests coming from the hub.
-
-
-General description of a Rephub - a replication system the repagent
connects to
- This section describes in high level a sample Rephub - a
replication system that uses the repagent API
- to replicate disks.
- It describes a simple Rephub that comntinuously maintains a
mirror of the volumes of a VM.
-
- Say we have a VM we want to protect - call it PVM, say it
has 2 volumes - V1, V2.
- Our Rephub is called SingleRephub - a Rephub protecting a
single VM.
-
- Preparations
- 1. The user chooses a host to rub SingleRephub - a different
host than PVM, call it Host2
- 2. The user creates two volumes on Host2 - same sizes of V1
and V2, call them V1R (V1 recovery) and V2R.
- 3. The user runs SingleRephub process on Host2, and gives
V1R and V2R as command line arguments.
- From now on SingleRephub waits for the
protected VM repagent to connect.
- 4. The user runs the protected VM PVM - and uses the switch
-repagent <Host2 IP>.
-
- Runtime
- 1. The repagent module connects to SingleRephub on startup.
- 2. repagent reports V1 and V2 to SingleRephub.
- 3. SingleRephub starts to perform an initial synchronization
of the protected volumes-
- it reads each protected volume (V1 and V2) -
using read volume requests - and copies the data into the
- recovery volume V1R and V2R.
- 4. SingleRephub enters 'protection' mode - each write to the
protected volume is sent by the repagent to the Rephub,
- and the Rephub performs the write on the
matching recovery volume.
-
- * Note that during stage 3 writes to the protected volumes
are not ignored - they're kept in a bitmap,
- and will be read again when stage 3 ends, in
an interative convergin process.
-
- This flow continuously maintains an updated recovery volume.
- If the protected system is damaged, the user can create a
new VM on Host2 with the replicated volumes attached to it.
- The new VM is a replica of the protected system.
-
-
diff --git a/replication/repagent.c b/replication/repagent.c
deleted file mode 100644
index c291915..0000000
--- a/replication/repagent.c
+++ /dev/null
@@ -1,327 +0,0 @@
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <pthread.h>
-#include <stdint.h>
-
-#include "block.h"
-#include "rephub_defs.h"
-#include "block_int.h"
-#include "repagent_client.h"
-#include "repagent.h"
-#include "rephub_cmds.h"
-
-#define ZERO_MEM_OBJ(pObj) memset(pObj, 0, sizeof(*pObj))
-#define REPAGENT_MAX_NUM_VOLUMES (64)
-#define REPAGENT_VOLUME_ID_NONE (0)
-
-typedef struct RepagentVolume {
- uint64_t vol_id;
- const char *vol_path;
- BlockDriverState *driver_ptr;
-} RepagentVolume;
-
-struct RepAgentState {
- int is_init;
- int num_volumes;
- RepagentVolume *volumes[REPAGENT_MAX_NUM_VOLUMES];
-};
-
-typedef struct RepagentReadVolIo {
- QEMUIOVector qiov;
- RepCmdReadVolReq rep_cmd;
- uint8_t *buf;
- struct timeval start_time;
-} RepagentReadVolIo;
-
-static int repagent_get_volume_by_name(const char *name);
-static void repagent_report_volumes_to_hub(void);
-static void repagent_vol_read_done(void *opaque, int ret);
-static struct timeval tsub(struct timeval t1, struct timeval t2);
-
-RepAgentState g_rep_agent = { 0 };
-
-void repagent_init(const char *hubname, int port)
-{
- /* It is the responsibility of the thread to free this struct */
- rephub_params *pParams = (rephub_params
*)g_malloc(sizeof(rephub_params));
- if (hubname == NULL) {
- hubname = "127.0.0.1";
- }
- if (port == 0) {
- port = 9010;
- }
-
- printf("repagent_init %s\n", hubname);
-
- pParams->port = port;
- pParams->name = g_strdup(hubname);
-
- pthread_t thread_id = 0;
-
- /* Create the repagent client listener thread */
- pthread_create(&thread_id, 0, repagent_listen, (void *) pParams);
- pthread_detach(thread_id);
-}
-
-void repagent_register_drive(const char *drive_path,
- BlockDriverState *driver_ptr)
-{
- int i;
- for (i = 0; i < g_rep_agent.num_volumes ; i++) {
- RepagentVolume *vol = g_rep_agent.volumes[i];
- if (vol != NULL) {
- assert(
- strcmp(drive_path, vol->vol_path) != 0
- && driver_ptr != vol->driver_ptr);
- }
- }
-
- assert(g_rep_agent.num_volumes < REPAGENT_MAX_NUM_VOLUMES);
-
- printf("zerto repagent: Registering drive. Num drives %d, path %s\n",
- g_rep_agent.num_volumes, drive_path);
- g_rep_agent.volumes[i] =
- (RepagentVolume *)g_malloc(sizeof(RepagentVolume));
- g_rep_agent.volumes[i]->driver_ptr = driver_ptr;
- /* orim todo strcpy? */
- g_rep_agent.volumes[i]->vol_path = drive_path;
-
- /* Orim todo thread-safety? */
- g_rep_agent.num_volumes++;
-
- repagent_report_volumes_to_hub();
-}
-
-/* orim todo destruction? */
-
-static RepagentVolume *repagent_get_protected_volume_by_driver(
- BlockDriverState *bs)
-{
- /* orim todo optimize search */
- int i = 0;
- for (i = 0; i < g_rep_agent.num_volumes ; i++) {
- RepagentVolume *p_vol = g_rep_agent.volumes[i];
- if (p_vol != NULL && p_vol->driver_ptr == (void *) bs) {
- return p_vol;
- }
- }
- return NULL;
-}
-
-void repagent_handle_protected_write(BlockDriverState *bs, int64_t
sector_num,
- int nb_sectors, QEMUIOVector *qiov, int ret_status)
-{
- printf("zerto Protected write offset %lld, size %d, IO return status
%d",
- (long long int) sector_num, nb_sectors, ret_status);
- if (bs->filename != NULL) {
- printf(", filename %s", bs->filename);
- }
-
- printf("\n");
-
- RepagentVolume *p_vol = repagent_get_protected_volume_by_driver(bs);
- if (p_vol == NULL || p_vol->vol_id == REPAGENT_VOLUME_ID_NONE) {
- /* Unprotected */
- printf("Got a write to an unprotected volume.\n");
- return;
- }
-
- /* Report IO to rephub */
-
- int data_size = qiov->size;
- if (ret_status < 0) {
- /* On failed ios we don't send the data to the hub */
- data_size = 0;
- }
- uint8_t *pdata = NULL;
- RepCmdProtectedWrite *p_cmd = (RepCmdProtectedWrite *) repcmd_new(
- REPHUB_CMD_PROTECTED_WRITE, data_size, (uint8_t **) &pdata);
-
- if (ret_status >= 0) {
- qemu_iovec_to_buffer(qiov, pdata);
- }
-
- p_cmd->volume_id = p_vol->vol_id;
- p_cmd->offset_sectors = sector_num;
- p_cmd->size_sectors = nb_sectors;
- p_cmd->ret_status = ret_status;
-
- if (repagent_client_send((RepCmd *) p_cmd) != 0) {
- printf("Error sending command\n");
- }
-}
-
-static void repagent_report_volumes_to_hub(void)
-{
- /* Report IO to rephub */
- int i;
- RepCmdDataReportVmVolumes *p_cmd_data = NULL;
- RepCmdReportVmVolumes *p_cmd = (RepCmdReportVmVolumes *) repcmd_new(
- REPHUB_CMD_REPORT_VM_VOLUMES,
- g_rep_agent.num_volumes * sizeof(RepVmVolumeInfo),
- (uint8_t **) &p_cmd_data);
- p_cmd->num_volumes = g_rep_agent.num_volumes;
- printf("reporting %u volumes\n", g_rep_agent.num_volumes);
- for (i = 0; i < g_rep_agent.num_volumes ; i++) {
- assert(g_rep_agent.volumes[i] != NULL);
- printf("reporting volume %s size %u\n",
- g_rep_agent.volumes[i]->vol_path,
- (uint32_t) sizeof(p_cmd_data->volumes[i].name));
- strncpy((char *) p_cmd_data->volumes[i].name,
- g_rep_agent.volumes[i]->vol_path,
- sizeof(p_cmd_data->volumes[i].name));
- p_cmd_data->volumes[i].volume_id = g_rep_agent.volumes[i]->vol_id;
- }
- if (repagent_client_send((RepCmd *) p_cmd) != 0) {
- printf("Error sending command\n");
- }
-}
-
-int repaget_start_protect(RepCmdStartProtect *pcmd,
- RepCmdDataStartProtect *pcmd_data)
-{
- printf("Start protect vol %s, ID %llu\n", pcmd_data->volume_name,
- (unsigned long long) pcmd->volume_id);
- int vol_index = repagent_get_volume_by_name(pcmd_data->volume_name);
- if (g_rep_agent.num_volumes > 0
- && strcmp(pcmd_data->volume_name, "stam") == 0) {
- /* Choose the first one for rephub */
- vol_index = 0;
- }
- if (vol_index < 0) {
- printf("The volume doesn't exist\n");
- return TRUE;
- }
- /* orim todo protect */
- g_rep_agent.volumes[vol_index]->vol_id = pcmd->volume_id;
-
- return TRUE;
-}
-
-static int repagent_get_volume_by_name(const char *name)
-{
- int i = 0;
- for (i = 0; i < g_rep_agent.num_volumes ; i++) {
- if (g_rep_agent.volumes[i] != NULL
- && strcmp(name, g_rep_agent.volumes[i]->vol_path) == 0) {
- return i;
- }
- }
- return -1;
-}
-
-static int repagent_get_volume_by_id(uint64_t vol_id)
-{
- int i = 0;
- for (i = 0; i < g_rep_agent.num_volumes ; i++) {
- if (g_rep_agent.volumes[i] != NULL
- && g_rep_agent.volumes[i]->vol_id == vol_id) {
- return i;
- }
- }
- return -1;
-}
-
-int repaget_read_vol(RepCmdReadVolReq *pcmd, uint8_t *pdata)
-{
- int index = repagent_get_volume_by_id(pcmd->volume_id);
- int size_bytes = pcmd->size_sectors * 512;
- if (index < 0) {
- printf("Vol read - Could not find vol id %llx\n",
- (unsigned long long int) pcmd->volume_id);
- RepCmdReadVolRes *p_res_cmd = (RepCmdReadVolRes *) repcmd_new(
- REPHUB_CMD_READ_VOL_RES, 0, NULL);
- p_res_cmd->req_id = pcmd->req_id;
- p_res_cmd->volume_id = pcmd->volume_id;
- p_res_cmd->is_status_success = FALSE;
- repagent_client_send((RepCmd *) p_res_cmd);
- return TRUE;
- }
-
- printf("Vol read - driver %p, volId %llu, offset %llu, size %u\n",
- g_rep_agent.volumes[index]->driver_ptr,
- (unsigned long long int) pcmd->volume_id,
- (unsigned long long int) pcmd->offset_sectors,
pcmd->size_sectors);
-
- {
- RepagentReadVolIo *read_xact = calloc(1,
sizeof(RepagentReadVolIo));
-
-/* BlockDriverAIOCB *acb; */
-
- ZERO_MEM_OBJ(read_xact);
-
- qemu_iovec_init(&read_xact->qiov, 1);
-
- /*read_xact->buf =
- qemu_blockalign(g_rep_agent.volumes[index]->driver_ptr,
size_bytes); */
- read_xact->buf = (uint8_t *) g_malloc(size_bytes);
- read_xact->rep_cmd = *pcmd;
- qemu_iovec_add(&read_xact->qiov, read_xact->buf, size_bytes);
-
- gettimeofday(&read_xact->start_time, NULL);
- /* orim TODO - use the returned acb to cancel the request on
shutdown */
- /*acb = */bdrv_aio_readv(g_rep_agent.volumes[index]->driver_ptr,
- read_xact->rep_cmd.offset_sectors, &read_xact->qiov,
- read_xact->rep_cmd.size_sectors, repagent_vol_read_done,
- read_xact);
- }
-
- return TRUE;
-}
-
-static void repagent_vol_read_done(void *opaque, int ret)
-{
- struct timeval t2;
- RepagentReadVolIo *read_xact = (RepagentReadVolIo *) opaque;
- uint8_t *pdata = NULL;
- RepCmdReadVolRes *pcmd = (RepCmdReadVolRes *) repcmd_new(
- REPHUB_CMD_READ_VOL_RES, read_xact->rep_cmd.size_sectors * 512,
- &pdata);
- pcmd->req_id = read_xact->rep_cmd.req_id;
- pcmd->volume_id = read_xact->rep_cmd.volume_id;
- pcmd->is_status_success = FALSE;
-
- printf("Protected vol read - volId %llu, offset %llu, size %u\n",
- (unsigned long long int) read_xact->rep_cmd.volume_id,
- (unsigned long long int) read_xact->rep_cmd.offset_sectors,
- read_xact->rep_cmd.size_sectors);
- gettimeofday(&t2, NULL);
-
- if (ret >= 0) {
- /* Read response - send the data to the hub */
- t2 = tsub(t2, read_xact->start_time);
- printf("Read prot vol done. Took %u seconds, %u us.",
- (uint32_t) t2.tv_sec, (uint32_t) t2.tv_usec);
-
- pcmd->is_status_success = TRUE;
- /* orim todo optimize - don't copy, use the qiov buffer */
- qemu_iovec_to_buffer(&read_xact->qiov, pdata);
- } else {
- printf("readv failed: %s\n", strerror(-ret));
- }
-
- repagent_client_send((RepCmd *) pcmd);
-
- /*qemu_vfree(read_xact->buf); */
- g_free(read_xact->buf);
-
- g_free(read_xact);
-}
-
-static struct timeval tsub(struct timeval t1, struct timeval t2)
-{
- t1.tv_usec -= t2.tv_usec;
- if (t1.tv_usec < 0) {
- t1.tv_usec += 1000000;
- t1.tv_sec--;
- }
- t1.tv_sec -= t2.tv_sec;
- return t1;
-}
-
-void repagent_client_connected(void)
-{
- /* orim todo thread protection */
- repagent_report_volumes_to_hub();
-}
diff --git a/replication/repagent.h b/replication/repagent.h
deleted file mode 100644
index 98ccbf2..0000000
--- a/replication/repagent.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * QEMU System Emulator
- *
- * Copyright (c) 2003-2008 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
copy
- * of this software and associated documentation files (the "Software"),
to deal
- * in the Software without restriction, including without limitation the
rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN
- * THE SOFTWARE.
- */
-#ifndef REPAGENT_H
-#define REPAGENT_H
-#include <stdint.h>
-
-#include "qemu-common.h"
-
-typedef struct RepAgentState RepAgentState;
-typedef struct RepCmdStartProtect RepCmdStartProtect;
-typedef struct RepCmdDataStartProtect RepCmdDataStartProtect;
-struct RepCmdReadVolReq;
-
-void repagent_init(const char *hubname, int port);
-void repagent_handle_protected_write(BlockDriverState *bs,
- int64_t sector_num, int nb_sectors, QEMUIOVector *qiov, int
ret_status);
-void repagent_register_drive(const char *drive_path,
- BlockDriverState *driver_ptr);
-int repaget_start_protect(RepCmdStartProtect *pcmd,
- RepCmdDataStartProtect *pcmd_data);
-int repaget_read_vol(struct RepCmdReadVolReq *pcmd, uint8_t *pdata);
-void repagent_client_connected(void);
-
-
-#endif /* REPAGENT_H */
diff --git a/replication/repagent_client.c b/replication/repagent_client.c
deleted file mode 100644
index eaa0a28..0000000
--- a/replication/repagent_client.c
+++ /dev/null
@@ -1,160 +0,0 @@
-#include "repcmd.h"
-#include "rephub_cmds.h"
-#include "repcmd_listener.h"
-#include "repagent_client.h"
-#include "repagent.h"
-#include "main-loop.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <stdio.h>
-#include <resolv.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <unistd.h>
-
-#define ZERO_MEM_OBJ(pObj) memset(pObj, 0, sizeof(*pObj))
-
-static void repagent_process_cmd(RepCmd *pCmd, uint8_t *pData, void
*clientPtr);
-
-typedef struct repagent_client_state {
- int is_connected;
- int is_terminate_receive;
- int hsock;
-} repagent_client_state;
-
-static repagent_client_state g_client_state = { 0 };
-
-static void repagent_client_read(void *opaque)
-{
- printf("repagent_client_read\n");
- int bytes_read =
repcmd_listener_socket_read_next_buf(g_client_state.hsock);
- if (bytes_read <= 0) {
- g_client_state.is_connected = 0;
- }
-}
-
-void *repagent_listen(void *pParam)
-{
- rephub_params *pServerParams = (rephub_params *) pParam;
- int host_port = pServerParams->port;
- const char *host_name = pServerParams->name;
-
- printf("Creating repagent listener thread...\n");
- g_free(pServerParams);
-
- struct sockaddr_in my_addr;
-
- int err;
- int retries = 0;
-
- g_client_state.hsock = socket(AF_INET, SOCK_STREAM, 0);
- if (g_client_state.hsock == -1) {
- printf("Error initializing socket %d\n", errno);
- return (void *) -1;
- }
-
- int param = 1;
-
- if ((setsockopt(g_client_state.hsock, SOL_SOCKET, SO_REUSEADDR,
- (char *) ¶m, sizeof(int)) == -1)
- || (setsockopt(g_client_state.hsock, SOL_SOCKET, SO_KEEPALIVE,
- (char *) ¶m, sizeof(int)) == -1)) {
- printf("Error setting options %d\n", errno);
- return (void *) -1;
- }
-
- my_addr.sin_family = AF_INET;
- my_addr.sin_port = htons(host_port);
- memset(&(my_addr.sin_zero), 0, 8);
-
- my_addr.sin_addr.s_addr = inet_addr(host_name);
-
- /* Reconnect loop */
- while (!g_client_state.is_terminate_receive) {
-
- if (connect(g_client_state.hsock, (struct sockaddr *) &my_addr,
- sizeof(my_addr)) == -1) {
- err = errno;
- if (err != EINPROGRESS) {
- retries++;
- fprintf(
- stderr,
- "Error connecting socket %d. Host %s, port %u.
Retry count %d\n",
- errno, host_name, host_port, retries);
- usleep(5 * 1000 * 1000);
- continue;
- }
- }
- retries = 0;
-
-
- repagent_client_connected();
- repcmd_listener_init(repagent_process_cmd, NULL);
- g_client_state.is_connected = 1;
- static int c;
- /* repcmd_listener_socket_thread_listener(g_client_state.hsock); */
- qemu_set_fd_handler(g_client_state.hsock, repagent_client_read,
NULL,
- NULL);
- while (g_client_state.is_connected) {
- printf("Connected (%d)...\n", c++);
- usleep(1 * 1000 * 1000);
- }
- /* Unregister */
- qemu_set_fd_handler(g_client_state.hsock, NULL, NULL, NULL);
-
- printf("Disconnected\n");
- g_client_state.is_connected = 0;
- close(g_client_state.hsock);
-
- }
- return 0;
-}
-
-void repagent_process_cmd(RepCmd *pcmd, uint8_t *pdata, void *clientPtr)
-{
- int is_free_data = 1;
- printf("Repagent got cmd %d\n", pcmd->hdr.cmdid);
- switch (pcmd->hdr.cmdid) {
- case REPHUB_CMD_START_PROTECT: {
- is_free_data = repaget_start_protect((RepCmdStartProtect *) pcmd,
- (RepCmdDataStartProtect *) pdata);
- }
- break;
- case REPHUB_CMD_READ_VOL_REQ: {
- is_free_data = repaget_read_vol((RepCmdReadVolReq *) pcmd, pdata);
- }
- break;
- default:
- assert(0);
- break;
-
- }
-
- if (is_free_data) {
- g_free(pdata);
- }
-}
-
-int repagent_client_send(RepCmd *p_cmd)
-{
- int bytecount = 0;
- printf("Send cmd %u, data size %u\n", p_cmd->hdr.cmdid,
- p_cmd->hdr.data_size_bytes);
- if (!g_client_state.is_connected) {
- printf("Not connected to hub\n");
- return -1;
- }
-
- bytecount = send(g_client_state.hsock, p_cmd,
- sizeof(RepCmd) + p_cmd->hdr.data_size_bytes, 0);
- if (bytecount < sizeof(RepCmd) + p_cmd->hdr.data_size_bytes) {
- printf("Bad send %d, errno %d\n", bytecount, errno);
- return bytecount;
- }
-
- /* Success */
- return 0;
-}
diff --git a/replication/repagent_client.h b/replication/repagent_client.h
deleted file mode 100644
index 62a5377..0000000
--- a/replication/repagent_client.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * QEMU System Emulator
- *
- * Copyright (c) 2003-2008 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
copy
- * of this software and associated documentation files (the "Software"),
to deal
- * in the Software without restriction, including without limitation the
rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN
- * THE SOFTWARE.
- */
-#ifndef REPAGENT_CLIENT_H
-#define REPAGENT_CLIENT_H
-#include "repcmd.h"
-
-typedef struct rephub_params {
- char *name;
- int port;
-} rephub_params;
-
-void *repagent_listen(void *pParam);
-int repagent_client_send(RepCmd *p_cmd);
-
-#endif /* REPAGENT_CLIENT_H */
diff --git a/replication/repcmd.h b/replication/repcmd.h
deleted file mode 100644
index 8c6cf1b..0000000
--- a/replication/repcmd.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * QEMU System Emulator
- *
- * Copyright (c) 2003-2008 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
copy
- * of this software and associated documentation files (the "Software"),
to deal
- * in the Software without restriction, including without limitation the
rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN
- * THE SOFTWARE.
- */
-#ifndef REPCMD_H
-#define REPCMD_H
-
-#include <stdint.h>
-
-#define REPCMD_MAGIC1 (0x1122)
-#define REPCMD_MAGIC2 (0x3344)
-#define REPCMD_NUM_U32_PARAMS (11)
-
-enum RepCmds {
- REPCMD_FIRST_INVALID = 0,
- REPCMD_FIRST_HUBCMD = 1,
- REPHUB_CMD_PROTECTED_WRITE = 2,
- REPHUB_CMD_REPORT_VM_VOLUMES = 3,
- REPHUB_CMD_START_PROTECT = 4,
- REPHUB_CMD_READ_VOL_REQ = 5,
- REPHUB_CMD_READ_VOL_RES = 6,
- REPHUB_CMD_AGENT_SHUTDOWN = 7,
-};
-
-typedef struct RepCmdHdr {
- uint16_t magic1;
- uint16_t cmdid;
- uint32_t data_size_bytes;
-} RepCmdHdr;
-
-typedef struct RepCmd {
- RepCmdHdr hdr;
- unsigned int parameters[REPCMD_NUM_U32_PARAMS];
- unsigned int magic2;
- uint8_t data[0];
-} RepCmd;
-
-RepCmd *repcmd_new(int cmd_id, int data_size, uint8_t **p_out_pdata);
-
-#endif /* REPCMD_H */
diff --git a/replication/repcmd_listener.c b/replication/repcmd_listener.c
deleted file mode 100644
index c1ce97f..0000000
--- a/replication/repcmd_listener.c
+++ /dev/null
@@ -1,173 +0,0 @@
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <stdio.h>
-#include <netinet/in.h>
-#include <resolv.h>
-#include <sys/socket.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#include <pthread.h>
-#include <assert.h>
-
-/* Use the CONFIG_REPLICATION flag to determine whether
- * we're under qemu build or a hub When under
- * qemu use g_malloc */
-#ifdef CONFIG_REPLICATION
-#include <glib.h>
-#define REPCMD_MALLOC g_malloc
-#else
-#define REPCMD_MALLOC malloc
-#endif
-
-#include "repcmd.h"
-#include "repcmd_listener.h"
-
-#define ZERO_MEM_OBJ(pObj) memset((void *)pObj, 0, sizeof(*pObj))
-
-
-typedef struct RepCmdRxCmdState {
- RepCmd curCmd;
- uint8_t *pReadBuf;
- int bytesToGet;
- int bytesGotten;
- int isGotHeader;
- uint8_t *pdata;
-} RepCmdRxCmdState;
-
-typedef struct RepCmdListenerState {
- int is_terminate_receive;
- pfn_received_cmd_cb receive_cb;
- void *opaque;
- int hsock;
- RepCmdRxCmdState cur_cmd;
-} RepCmdListenerState;
-
-static RepCmdListenerState g_listenerState = { 0 };
-
-static int repcmd_listener_process_rx(int bytecount);
-
-void repcmd_listener_init(pfn_received_cmd_cb callback, void *opaque)
-{
- ZERO_MEM_OBJ(&g_listenerState);
- g_listenerState.receive_cb = callback;
- g_listenerState.opaque = opaque;
-
- g_listenerState.cur_cmd.bytesToGet = sizeof(RepCmd);
- g_listenerState.cur_cmd.pReadBuf =
- (uint8_t *) &g_listenerState.cur_cmd.curCmd;
-}
-
-int repcmd_listener_socket_read_next_buf(int hsock)
-{
- RepCmdRxCmdState *cmd_state = &g_listenerState.cur_cmd;
- int bytecount = recv(hsock, cmd_state->pReadBuf +
cmd_state->bytesGotten,
- cmd_state->bytesToGet - cmd_state->bytesGotten, 0);
- return repcmd_listener_process_rx(bytecount);
-}
-
-/* Returns 0 for initiated termination or socket error value on error */
-int repcmd_listener_socket_thread_listener(int hsock)
-{
- int ret = 0;
- /* receive loop */
- while (!g_listenerState.is_terminate_receive) {
- ret = repcmd_listener_socket_read_next_buf(hsock);
- if (ret <= 0) {
- return ret;
- }
- }
- return 0;
-}
-
-static int repcmd_listener_process_rx(int bytecount)
-{
- RepCmdRxCmdState *cmd_state = &g_listenerState.cur_cmd;
- if (bytecount == -1) {
- fprintf(stderr, "Error receiving data %d\n", errno);
- return errno;
- }
-
- if (bytecount == 0) {
- printf("Disconnected\n");
- return 0;
- }
- cmd_state->bytesGotten += bytecount;
-/* printf("Recieved bytes %d, got %d/%d\n",
- bytecount, cmd_state->bytesGotten, cmd_state->bytesToGet); */
- /* print content */
- if (0) {
- int i;
- for (i = 0; i < bytecount ; i += 4) {
- /*printf("%d/%d", i, bytecount/4); */
- printf(
- "%#x ",
- *(int *) (&cmd_state->pReadBuf[cmd_state->bytesGotten
- - bytecount + i]));
-
- }
- printf("\n");
- }
- assert(cmd_state->bytesGotten <= cmd_state->bytesToGet);
- if (cmd_state->bytesGotten == cmd_state->bytesToGet) {
- int isGotData = 0;
- cmd_state->bytesGotten = 0;
- if (!cmd_state->isGotHeader) {
- /* We just got the header */
- cmd_state->isGotHeader = 1;
-
- assert(cmd_state->curCmd.hdr.magic1 == REPCMD_MAGIC1);
- assert(cmd_state->curCmd.magic2 == REPCMD_MAGIC2);
- if (cmd_state->curCmd.hdr.data_size_bytes > 0) {
- cmd_state->pdata = (uint8_t *)REPCMD_MALLOC(
- cmd_state->curCmd.hdr.data_size_bytes);
-/* printf("malloc %p\n", cmd_state->pdata); */
- cmd_state->pReadBuf = cmd_state->pdata;
- } else {
- /* no data */
- isGotData = 1;
- cmd_state->pdata = NULL;
- }
- cmd_state->bytesToGet = cmd_state->curCmd.hdr.data_size_bytes;
- } else {
- isGotData = 1;
- }
-
- if (isGotData) {
- /* Got command and data */
- (*g_listenerState.receive_cb)(&cmd_state->curCmd,
cmd_state->pdata,
- g_listenerState.opaque);
-
- /* It's the callee responsibility to free cmd_state->pdata */
- cmd_state->pdata = NULL;
- ZERO_MEM_OBJ(&cmd_state->curCmd);
- cmd_state->pReadBuf = (uint8_t *) &cmd_state->curCmd;
- cmd_state->bytesGotten = 0;
- cmd_state->bytesToGet = sizeof(RepCmd);
- cmd_state->isGotHeader = 0;
- }
- }
- return bytecount;
-}
-
-RepCmd *repcmd_new(int cmd_id, int data_size, uint8_t **p_out_pdata)
-{
- RepCmd *p_cmd = (RepCmd *)REPCMD_MALLOC(sizeof(RepCmd) + data_size);
- assert(p_cmd != NULL);
-
- /* Zero the CMD (not the data) */
- ZERO_MEM_OBJ(p_cmd);
-
- p_cmd->hdr.cmdid = cmd_id;
- p_cmd->hdr.magic1 = REPCMD_MAGIC1;
- p_cmd->magic2 = REPCMD_MAGIC2;
- p_cmd->hdr.data_size_bytes = data_size;
-
- if (p_out_pdata != NULL) {
- *p_out_pdata = p_cmd->data;
- }
-
- return p_cmd;
-}
-
diff --git a/replication/repcmd_listener.h b/replication/repcmd_listener.h
deleted file mode 100644
index 19b9ea9..0000000
--- a/replication/repcmd_listener.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * QEMU System Emulator
- *
- * Copyright (c) 2003-2008 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
copy
- * of this software and associated documentation files (the "Software"),
to deal
- * in the Software without restriction, including without limitation the
rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN
- * THE SOFTWARE.
- */
-#ifndef REPCMD_LISTENER_H
-#define REPCMD_LISTENER_H
-#include <stdint.h>
-typedef void (*pfn_received_cmd_cb)(RepCmd *pcmd,
- uint8_t *pdata, void *opaque);
-
-void repcmd_listener_init(pfn_received_cmd_cb callback, void *opaque);
-int repcmd_listener_socket_read_next_buf(int hsock);
-int repcmd_listener_socket_thread_listener(int hsock);
-
-#endif /* REPCMD_LISTENER_H */
diff --git a/replication/rephub_cmds.h b/replication/rephub_cmds.h
deleted file mode 100644
index 3bd4eb4..0000000
--- a/replication/rephub_cmds.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * QEMU System Emulator
- *
- * Copyright (c) 2003-2008 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
copy
- * of this software and associated documentation files (the "Software"),
to deal
- * in the Software without restriction, including without limitation the
rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN
- * THE SOFTWARE.
- */
-#ifndef REPHUB_CMDS_H
-#define REPHUB_CMDS_H
-
-#include <stdint.h>
-#include "repcmd.h"
-#include "rephub_defs.h"
-
-/*********************************************************
- * RepCmd Report a protected IO
- *
- * REPHUB_CMD_PROTECTED_WRITE
- * Direction: agent->hub
- *
- * Any write of a protected volume is send with this
- * message to the hub, with its status.
- * When case the status is bad no data is sent
- *********************************************************/
-typedef struct RepCmdProtectedWrite {
- RepCmdHdr hdr;
- uint64_t volume_id;
- uint64_t offset_sectors;
- /* The size field duplicates the RepCmd size,
- * but it is needed for reporting failed IOs' sizes */
- uint32_t size_sectors;
- int ret_status;
-} RepCmdProtectedWrite;
-
-/*********************************************************
- * RepCmd Report VM volumes
- *
- * REPHUB_CMD_REPORT_VM_VOLUMES
- * Direction: agent->hub
- *
- * The agent reports all the volumes of the VM
- * to the hub.
- *********************************************************/
-typedef struct RepVmVolumeInfo {
- char name[REPHUB_MAX_VOL_NAME_LEN];
- uint64_t volume_id;
- uint32_t size_mb;
- uint32_t padding;
-} RepVmVolumeInfo;
-
-typedef struct RepCmdReportVmVolumes {
- RepCmdHdr hdr;
- int num_volumes;
-} RepCmdReportVmVolumes;
-
-typedef struct RepCmdDataReportVmVolumes {
- RepVmVolumeInfo volumes[0];
-} RepCmdDataReportVmVolumes;
-
-
-/*********************************************************
- * RepCmd Start protect
- *
- * REPHUB_CMD_START_PROTECT
- * Direction: hub->agent
- *
- * The hub instructs the agent to start protecting
- * a volume. When a volume is protected all its writes
- * are sent to to the hub.
- * With this command the hub also assigns a volume ID to
- * the given volume name.
- *********************************************************/
-typedef struct RepCmdStartProtect {
- RepCmdHdr hdr;
- uint64_t volume_id;
-} RepCmdStartProtect;
-
-typedef struct RepCmdDataStartProtect {
- char volume_name[REPHUB_MAX_VOL_NAME_LEN];
-} RepCmdDataStartProtect;
-
-
-/*********************************************************
- * RepCmd Read Volume Request
- *
- * REPHUB_CMD_READ_VOL_REQ
- * Direction: hub->agent
- *
- * The hub issues a read IO to a protected volume.
- * This command is used during sync - when the hub needs
- * to read unsyncronized sections of a protected volume.
- * This command is a request, the read data is returned
- * by the response command REPHUB_CMD_READ_VOL_RES
- *********************************************************/
-typedef struct RepCmdReadVolReq {
- RepCmdHdr hdr;
- int req_id;
- int size_sectors;
- uint64_t volume_id;
- uint64_t offset_sectors;
-} RepCmdReadVolReq;
-
-/*********************************************************
- * RepCmd Read Volume Response
- *
- * REPHUB_CMD_READ_VOL_RES
- * Direction: agent->hub
- *
- * A response to REPHUB_CMD_READ_VOL_REQ.
- * Sends the data read from a protected volume
- *********************************************************/
-typedef struct RepCmdReadVolRes {
- RepCmdHdr hdr;
- int req_id;
- int is_status_success;
- uint64_t volume_id;
-} RepCmdReadVolRes;
-
-/*********************************************************
- * RepCmd Agent shutdown
- *
- * REPHUB_CMD_AGENT_SHUTDOWN
- * Direction: agent->hub
- *
- * Notifies the hub that the agent is about to shutdown.
- * This allows a graceful shutdown. Any disconnection
- * of an agent without sending this command will result
- * in a full sync of the VM volumes.
- *********************************************************/
-typedef struct RepCmdAgentShutdown {
- RepCmdHdr hdr;
-} RepCmdAgentShutdown;
-
-
-#endif /* REPHUB_CMDS_H */
diff --git a/replication/rephub_defs.h b/replication/rephub_defs.h
deleted file mode 100644
index e34e0ce..0000000
--- a/replication/rephub_defs.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * QEMU System Emulator
- *
- * Copyright (c) 2003-2008 Fabrice Bellard
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
copy
- * of this software and associated documentation files (the "Software"),
to deal
- * in the Software without restriction, including without limitation the
rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or
sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN
- * THE SOFTWARE.
- */
-#ifndef REP_HUB_DEFS_H
-#define REP_HUB_DEFS_H
-
-#include <stdint.h>
-
-#define REPHUB_MAX_VOL_NAME_LEN (1024)
-#define REPHUB_MAX_NUM_VOLUMES (512)
-
-#ifndef TRUE
- #define TRUE (1)
-#endif
-
-#ifndef FALSE
- #define FALSE (0)
-#endif
-
-#endif /* REP_HUB_DEFS_H */
diff --git a/vl.c b/vl.c
index 7f8f14c..17cf6ce 100644
--- a/vl.c
+++ b/vl.c
@@ -167,7 +167,7 @@ int main(int argc, char **argv)
#include "ui/qemu-spice.h"
-#include "replication/repagent.h"
+#include "block/repagent/repagent.h"
//#define DEBUG_NET
//#define DEBUG_SLIRP
@@ -2413,10 +2413,10 @@ int main(int argc, char **argv, char **envp)
HD_OPTS);
break;
case QEMU_OPTION_repagent:
-#ifdef CONFIG_REPLICATION
+#ifdef CONFIG_REPAGENT
repagent_init(optarg, 0);
#else
- fprintf(stderr, "Replication support is disabled. "
+ fprintf(stderr, "Repagent support is disabled. "
"Don't use -repagent option.\n");
exit(1);
#endif
--
1.7.6.5
[-- Attachment #2: Type: text/html, Size: 165498 bytes --]
reply other threads:[~2012-04-05 12:24 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=9a75ff0ba418292c14268031ae7c000f@mail.gmail.com \
--to=omamluk@zerto.com \
--cc=anthony@codemonkey.ws \
--cc=dlaor@redhat.com \
--cc=kwolf@redhat.com \
--cc=oded@zerto.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=rluxenbe@redhat.com \
--cc=stefanha@gmail.com \
--cc=yairk@zerto.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).