From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([208.118.235.92]:39048) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SFlg1-0006Hr-TQ for qemu-devel@nongnu.org; Thu, 05 Apr 2012 08:20:43 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SFlfs-0003MM-JR for qemu-devel@nongnu.org; Thu, 05 Apr 2012 08:20:33 -0400 Received: from mail-qa0-f46.google.com ([209.85.216.46]:52839) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SFlfs-0003M0-58 for qemu-devel@nongnu.org; Thu, 05 Apr 2012 08:20:24 -0400 Received: by qatm19 with SMTP id m19so1282064qat.12 for ; Thu, 05 Apr 2012 05:20:17 -0700 (PDT) From: Ori Mamluk References: d552e5d05d1da56d906e8ab1c5863ea6@mail.gmail.com In-Reply-To: d552e5d05d1da56d906e8ab1c5863ea6@mail.gmail.com MIME-Version: 1.0 Date: Thu, 5 Apr 2012 15:20:15 +0300 Message-ID: <4f768955970e56d54b304c6d8384108c@mail.gmail.com> Content-Type: multipart/alternative; boundary=00248c768f9e18b84b04bced9092 Subject: [Qemu-devel] [RFC PATCH v3 8/9] repagent: Work on review of patch V2 - moved to QTAILQ instead of array, replaced pthreads with qemu-thread List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Kevin Wolf , Roni Luxenberg , Stefan Hajnoczi , dlaor@redhat.com, Anthony Liguori , Oded Kedem , Yair Kuszpet , Paolo Bonzini --00248c768f9e18b84b04bced9092 Content-Type: text/plain; charset=ISO-8859-1 Changed volumes list to QTAILQ instead of an array. Replaced pthreads with qemu-thread Fixed license text --- block.c | 9 --- block/repagent/qemu-repagent.txt | 2 + block/repagent/repagent.c | 142 ++++++++++++++++++-------------------- block/repagent/repagent.h | 5 +- block/repagent/repagent_client.c | 2 +- block/repagent/repagent_client.h | 4 +- block/repagent/repagent_drv.c | 6 +- block/repagent/repcmd_listener.c | 2 +- block/repagent/repcmd_listener.h | 2 +- block/repagent/rephub_cmds.h | 2 +- block/repagent/rephub_defs.h | 2 +- 11 files changed, 82 insertions(+), 96 deletions(-) diff --git a/block.c b/block.c index 8e11c03..b77ca0f 100644 --- a/block.c +++ b/block.c @@ -1486,13 +1486,6 @@ static int bdrv_rw_co(BlockDriverState *bs, int64_t sector_num, uint8_t *buf, qemu_aio_wait(); } } - /* orim todo remove */ - printf("IO done. is_write %d sec %lld size %d ", is_write, - (long long int) sector_num, nb_sectors); - if (bs->drv != NULL) { - printf("Drv %s, ", bs->drv->format_name); - } - printf("file %s, ret %d\n", bs->filename, rwco.ret); return rwco.ret; } @@ -1966,8 +1959,6 @@ int64_t bdrv_getlength(BlockDriverState *bs) ret = drv->bdrv_getlength(bs); } } - /* orim todo remove */ - printf("bdrv_getlength returned %d", (int)ret); return ret; } diff --git a/block/repagent/qemu-repagent.txt b/block/repagent/qemu-repagent.txt index 0f9dc03..af1245c 100644 --- a/block/repagent/qemu-repagent.txt +++ b/block/repagent/qemu-repagent.txt @@ -1,5 +1,7 @@ repagent - replication agent - a Qemu module for enabling continuous async replication of VM volumes +Ori Mamluk, 2012 + Introduction This document describes a feature in Qemu - a replication agent (named Repagent). The Repagent is a new module that exposes an API to an external replication system (AKA Rephub). diff --git a/block/repagent/repagent.c b/block/repagent/repagent.c index 2e70853..a5c0636 100644 --- a/block/repagent/repagent.c +++ b/block/repagent/repagent.c @@ -1,7 +1,7 @@ /* * QEMU System Emulator replication agent * - * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2012 Ori Mamluk * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -24,7 +24,6 @@ #include #include #include -#include #include #include "block.h" @@ -33,21 +32,24 @@ #include "repagent_client.h" #include "repagent.h" #include "rephub_cmds.h" +#include "qemu-queue.h" +#include "qemu-thread.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; + char *vol_path; BlockDriverState *driver_ptr; + QTAILQ_ENTRY(RepagentVolume) list; } RepagentVolume; struct RepAgentState { bool is_init; int num_volumes; - RepagentVolume *volumes[REPAGENT_MAX_NUM_VOLUMES]; + QTAILQ_HEAD(RepagentVolumesList, RepagentVolume) volumes; + QemuThread disconnectThread; }; typedef struct RepagentReadVolIo { @@ -57,9 +59,9 @@ typedef struct RepagentReadVolIo { struct timeval start_time; } RepagentReadVolIo; -static int repagent_get_volume_by_driver( +static RepagentVolume *repagent_get_volume_by_driver( BlockDriverState *bs); -static int repagent_get_volume_by_name(const char *name); +static RepagentVolume *repagent_get_volume_by_name(const char *name); static void repagent_report_volumes_to_hub(void); static void repagent_remote_io_done(void *opaque, int ret); static struct timeval tsub(struct timeval t1, struct timeval t2); @@ -68,6 +70,10 @@ RepAgentState g_rep_agent = { 0 }; void repagent_init(const char *hubname, int port) { + QTAILQ_HEAD(RepagentVolumesList, RepagentVolume) tmpHead = + QTAILQ_HEAD_INITIALIZER(tmpHead); + memcpy(&g_rep_agent.volumes, &tmpHead, sizeof(g_rep_agent.volumes)); + /* It is the responsibility of the thread to free this struct */ rephub_params *pParams = g_malloc(sizeof(rephub_params)); if (hubname == NULL) { @@ -82,70 +88,57 @@ void repagent_init(const char *hubname, int port) 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); + qemu_thread_create(&g_rep_agent.disconnectThread, repagent_listen, + (void *) pParams, QEMU_THREAD_DETACHED); } void repagent_register_drive(const char *drive_path, BlockDriverState *driver_ptr) { /* Assert that the volume is not registered yet */ - int i = repagent_get_volume_by_name(drive_path); - assert(i == -1); - - /*Add the volume at the last place*/ - assert(g_rep_agent.num_volumes < REPAGENT_MAX_NUM_VOLUMES); - - i = g_rep_agent.num_volumes; - g_rep_agent.num_volumes++; + RepagentVolume *vol = repagent_get_volume_by_name(drive_path); + assert(vol == NULL); 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; + RepagentVolume *new_vol = g_malloc(sizeof(RepagentVolume)); + new_vol->driver_ptr = driver_ptr; /* orim todo strcpy? */ - g_rep_agent.volumes[i]->vol_path = drive_path; + new_vol->vol_path = g_strdup(drive_path); + + QTAILQ_INSERT_HEAD(&g_rep_agent.volumes, new_vol, list); /* Orim todo thread-safety? */ g_rep_agent.num_volumes++; repagent_report_volumes_to_hub(); } -void repagent_deregister_drive(const char *drive_path, - BlockDriverState *driver_ptr) +void repagent_deregister_drive(BlockDriverState *driver_ptr) { /* Orim todo thread-safety? */ - int i = repagent_get_volume_by_driver(driver_ptr); - assert(i != -1); - - RepagentVolume *vol = g_rep_agent.volumes[i]; - /* Put the last volume in the cell of the removed volume to maintain a - * contiguous array */ - g_rep_agent.volumes[i] = g_rep_agent.volumes[g_rep_agent.num_volumes - 1]; - g_rep_agent.volumes[g_rep_agent.num_volumes - 1] = NULL; + RepagentVolume *vol = repagent_get_volume_by_driver(driver_ptr); + assert(vol != NULL); + + QTAILQ_REMOVE(&g_rep_agent.volumes, vol, list); + g_free(vol->vol_path); g_rep_agent.num_volumes--; g_free(vol); - } /* orim todo destruction? */ -static int repagent_get_volume_by_driver( +static RepagentVolume *repagent_get_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 i; + RepagentVolume *vol = NULL; + QTAILQ_FOREACH(vol, &g_rep_agent.volumes, list) { + if (vol != NULL && vol->driver_ptr == (void *)bs) { + return vol; } } - return -1; + return NULL; } void repagent_handle_protected_write(BlockDriverState *bs, int64_t sector_num, @@ -160,15 +153,13 @@ void repagent_handle_protected_write(BlockDriverState *bs, int64_t sector_num, printf("\n"); /* orim todo thread safety? */ - int i = repagent_get_volume_by_driver(bs); - if (i == -1 || g_rep_agent.volumes[i]->vol_id == REPAGENT_VOLUME_ID_NONE) { + RepagentVolume *vol = repagent_get_volume_by_driver(bs); + if (vol == NULL || vol->vol_id == REPAGENT_VOLUME_ID_NONE) { /* Unprotected */ printf("Got a write to an unprotected volume.\n"); return; } - RepagentVolume *p_vol = g_rep_agent.volumes[i]; - /* Report IO to rephub */ int data_size = qiov->size; @@ -184,7 +175,7 @@ void repagent_handle_protected_write(BlockDriverState *bs, int64_t sector_num, qemu_iovec_to_buffer(qiov, pdata); } - p_cmd->volume_id = p_vol->vol_id; + p_cmd->volume_id = vol->vol_id; p_cmd->offset_sectors = sector_num; p_cmd->size_sectors = nb_sectors; p_cmd->ret_status = ret_status; @@ -197,23 +188,26 @@ void repagent_handle_protected_write(BlockDriverState *bs, int64_t sector_num, 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); + RepagentVolume *vol = QTAILQ_FIRST(&g_rep_agent.volumes); p_cmd->num_volumes = g_rep_agent.num_volumes; printf("reporting %u volumes\n", g_rep_agent.num_volumes); + + int i; for (i = 0; i < g_rep_agent.num_volumes ; i++) { - assert(g_rep_agent.volumes[i] != NULL); + assert(vol != NULL); printf("reporting volume %s size %u\n", - g_rep_agent.volumes[i]->vol_path, + vol->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, + vol->vol_path, sizeof(p_cmd_data->volumes[i].name)); - p_cmd_data->volumes[i].volume_id = g_rep_agent.volumes[i]->vol_id; + p_cmd_data->volumes[i].volume_id = vol->vol_id; + vol = QTAILQ_NEXT(vol, list); } if (repagent_client_send((RepCmd *) p_cmd) != 0) { printf("Error sending command\n"); @@ -225,51 +219,49 @@ bool repaget_start_protect(RepCmdStartProtect *pcmd, { 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); + RepagentVolume *vol = 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; + vol = QTAILQ_LAST(&g_rep_agent.volumes, RepagentVolumesList); } - if (vol_index < 0) { + if (vol == NULL) { printf("The volume doesn't exist\n"); return true; } /* orim todo protect */ - g_rep_agent.volumes[vol_index]->vol_id = pcmd->volume_id; + vol->vol_id = pcmd->volume_id; return true; } -static int repagent_get_volume_by_name(const char *name) +static RepagentVolume *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; + RepagentVolume *vol = NULL; + QTAILQ_FOREACH(vol, &g_rep_agent.volumes, list) { + if (vol != NULL && strcmp(name, vol->vol_path) == 0) { + return vol; } } - return -1; + return NULL; } -static int repagent_get_volume_by_id(uint64_t vol_id) +static RepagentVolume *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; + RepagentVolume *vol = NULL; + QTAILQ_FOREACH(vol, &g_rep_agent.volumes, list) { + if (vol != NULL && vol->vol_id == vol_id) { + return vol; } } - return -1; + return NULL; } bool repagent_remote_io(RepCmdRemoteIoReq *pcmd, uint8_t *pdata) { - int index = repagent_get_volume_by_id(pcmd->volume_id); + RepagentVolume *vol = repagent_get_volume_by_id(pcmd->volume_id); int size_bytes = pcmd->size_sectors * 512; - if (index < 0) { + if (vol == NULL) { printf("Vol read - Could not find vol id %llx\n", (unsigned long long int) pcmd->volume_id); RepCmdRemoteIoRes *p_res_cmd = (RepCmdRemoteIoRes *) repcmd_new( @@ -282,7 +274,7 @@ bool repagent_remote_io(RepCmdRemoteIoReq *pcmd, uint8_t *pdata) } printf("Vol read - driver %p, volId %llu, offset %llu, size %u\n", - g_rep_agent.volumes[index]->driver_ptr, + vol->driver_ptr, (unsigned long long int) pcmd->volume_id, (unsigned long long int) pcmd->offset_sectors, pcmd->size_sectors); @@ -296,7 +288,7 @@ bool repagent_remote_io(RepCmdRemoteIoReq *pcmd, uint8_t *pdata) qemu_iovec_init(&io_xaction->qiov, 1); /*read_xact->buf = - qemu_blockalign(g_rep_agent.volumes[index]->driver_ptr, size_bytes); */ + qemu_blockalign(vol->driver_ptr, size_bytes); */ io_xaction->buf = (uint8_t *) g_malloc(size_bytes); io_xaction->rep_cmd = *pcmd; qemu_iovec_add(&io_xaction->qiov, io_xaction->buf, size_bytes); @@ -305,12 +297,12 @@ bool repagent_remote_io(RepCmdRemoteIoReq *pcmd, uint8_t *pdata) /* orim TODO - use the returned acb to cancel the request on shutdown */ /*acb = */ if (pcmd->is_read) { - bdrv_aio_readv(g_rep_agent.volumes[index]->driver_ptr, + bdrv_aio_readv(vol->driver_ptr, io_xaction->rep_cmd.offset_sectors, &io_xaction->qiov, io_xaction->rep_cmd.size_sectors, repagent_remote_io_done, io_xaction); } else { - bdrv_aio_writev(g_rep_agent.volumes[index]->driver_ptr, + bdrv_aio_writev(vol->driver_ptr, io_xaction->rep_cmd.offset_sectors, &io_xaction->qiov, io_xaction->rep_cmd.size_sectors, repagent_remote_io_done, io_xaction); diff --git a/block/repagent/repagent.h b/block/repagent/repagent.h index 2863ffc..157a9b6 100644 --- a/block/repagent/repagent.h +++ b/block/repagent/repagent.h @@ -1,7 +1,7 @@ /* * QEMU System Emulator * - * Copyright (c) 2003-2008 Fabrice Bellard + * Copyright (c) 2012 Ori Mamluk * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -42,8 +42,7 @@ void repagent_handle_protected_write(BlockDriverState *bs, int nb_sectors, QEMUIOVector *qiov, int ret_status); void repagent_register_drive(const char *drive_path, BlockDriverState *driver_ptr); -void repagent_deregister_drive(const char *drive_path, - BlockDriverState *driver_ptr); +void repagent_deregister_drive(BlockDriverState *driver_ptr); bool repaget_start_protect(RepCmdStartProtect *pcmd, RepCmdDataStartProtect *pcmd_data); bool repagent_remote_io(struct RepCmdRemoteIoReq *pcmd, uint8_t *pdata); diff --git a/block/repagent/repagent_client.c b/block/repagent/repagent_client.c index 9d826c4..2e57ed0 100644 --- a/block/repagent/repagent_client.c +++ b/block/repagent/repagent_client.c @@ -1,7 +1,7 @@ /* * QEMU System Emulator replication agent - socket client * - * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2012 Ori Mamluk * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/block/repagent/repagent_client.h b/block/repagent/repagent_client.h index 62a5377..6eaafed 100644 --- a/block/repagent/repagent_client.h +++ b/block/repagent/repagent_client.h @@ -1,7 +1,7 @@ /* - * QEMU System Emulator + * QEMU System Emulator - replication agent client * - * Copyright (c) 2003-2008 Fabrice Bellard + * Copyright (c) 2012 Ori Mamluk * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/block/repagent/repagent_drv.c b/block/repagent/repagent_drv.c index 4775166..1795de1 100644 --- a/block/repagent/repagent_drv.c +++ b/block/repagent/repagent_drv.c @@ -1,7 +1,7 @@ /* * QEMU System Emulator replication agent - repagent block driver * - * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2012 Ori Mamluk * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -68,6 +68,7 @@ static int coroutine_fn repagent_co_writev(BlockDriverState *bs, static void repagent_close(BlockDriverState *bs) { printf("%s\n", __func__); + repagent_deregister_drive(bs); } static int coroutine_fn repagent_co_flush(BlockDriverState *bs) @@ -88,11 +89,12 @@ static int repagent_truncate(BlockDriverState *bs, int64_t offset) return bdrv_truncate(bs->file, offset); } +/* orim todo maybe use probe for planting repagent in every driver */ static int repagent_probe(const uint8_t *buf, int buf_size, const char *filename) { printf("%s\n", __func__); - return 1; /* everything can be opened as raw image */ + return 0; /* everything can be opened as raw image */ } static int coroutine_fn repagent_co_discard(BlockDriverState *bs, diff --git a/block/repagent/repcmd_listener.c b/block/repagent/repcmd_listener.c index e6b4d74..0998f44 100644 --- a/block/repagent/repcmd_listener.c +++ b/block/repagent/repcmd_listener.c @@ -1,7 +1,7 @@ /* * QEMU System Emulator replication agent - socket commands layer * - * Copyright (c) 2003 Fabrice Bellard + * Copyright (c) 2012 Ori Mamluk * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/block/repagent/repcmd_listener.h b/block/repagent/repcmd_listener.h index 19b9ea9..629cdb5 100644 --- a/block/repagent/repcmd_listener.h +++ b/block/repagent/repcmd_listener.h @@ -1,7 +1,7 @@ /* * QEMU System Emulator * - * Copyright (c) 2003-2008 Fabrice Bellard + * Copyright (c) 2012 Ori Mamluk * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/block/repagent/rephub_cmds.h b/block/repagent/rephub_cmds.h index cb737e6..5075f33 100644 --- a/block/repagent/rephub_cmds.h +++ b/block/repagent/rephub_cmds.h @@ -1,7 +1,7 @@ /* * QEMU System Emulator * - * Copyright (c) 2003-2008 Fabrice Bellard + * Copyright (c) 2012 Ori Mamluk * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal diff --git a/block/repagent/rephub_defs.h b/block/repagent/rephub_defs.h index f036f58..575e9f8 100644 --- a/block/repagent/rephub_defs.h +++ b/block/repagent/rephub_defs.h @@ -1,7 +1,7 @@ /* * QEMU System Emulator * - * Copyright (c) 2003-2008 Fabrice Bellard + * Copyright (c) 2012 Ori Mamluk * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal -- 1.7.6.5 --00248c768f9e18b84b04bced9092 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable

Changed volumes list to QTAIL= Q instead of an array.

Replaced pthreads with qem= u-thread

Fixed license text

---

=

block.c=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 |=A0=A0=A0 9 ---

b= lock/repagent/qemu-repagent.txt |=A0=A0=A0 2 +

block/repagent/repagent.c=A0=A0=A0=A0=A0=A0=A0 |=A0 142 ++++++++++++++++++-= -------------------

block/repagent/repagent.h=A0= =A0=A0=A0=A0=A0=A0 |=A0=A0=A0 5 +-

block/repagent= /repagent_client.c |=A0=A0=A0 2 +-

block/repagent/repagent_client.h |=A0=A0=A0 4 +-

= block/repagent/repagent_drv.c=A0=A0=A0 |=A0=A0=A0 6 +-

block/repagent/repcmd_listener.c |=A0=A0=A0 2 +-

block/repagent/repcmd_listener.h |=A0=A0=A0 2 +-

block/repagent/rephub_cmds.h=A0=A0=A0=A0 |=A0=A0=A0 = 2 +-

block/repagent/rephub_defs.h=A0=A0=A0=A0 | = =A0=A0=A02 +-

11 files changed, 82 insertions(+),= 96 deletions(-)

=A0

diff --git a/block.c b/block.c

index 8e11c03..b77ca0f 100644

--- a/b= lock.c

+++ b/block.c

@@= -1486,13 +1486,6 @@ static int bdrv_rw_co(BlockDriverState *bs, int64_t se= ctor_num, uint8_t *buf,

=A0=A0=A0 =A0=A0=A0=A0=A0=A0=A0=A0=A0qemu_aio_wait()= ;

=A0=A0=A0=A0=A0=A0=A0=A0 }

=A0=A0=A0=A0 }

-=A0=A0=A0 /* orim todo remo= ve */

-=A0=A0=A0 printf("IO done. is_write %= d sec %lld size %d ", is_write,

-=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (long long int) s= ector_num, nb_sectors);

-=A0=A0=A0 if (bs->drv= !=3D NULL) {

-=A0=A0=A0=A0=A0=A0=A0 printf("= ;Drv %s, ", bs->drv->format_name);

-=A0=A0=A0 }

-=A0=A0=A0 pr= intf("file %s, ret %d\n", bs->filename, rwco.ret);

=A0=A0=A0=A0 return rwco.ret;

}

=A0

@@ -1966,8 +1959,6 @@ int64_t bdrv_getlength(BlockDr= iverState *bs)

=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0 ret =3D drv->bdrv_getlength(bs);

=A0 =A0= =A0=A0=A0=A0=A0=A0}

=A0=A0=A0=A0 }

-=A0=A0=A0 /* orim todo remove */

-=A0=A0=A0 printf("bdrv_getlength returned %d", (int)ret)= ;

=A0=A0=A0=A0 return ret;

}

=A0

diff --git a/block/repagent/qemu-repagent.txt= b/block/repagent/qemu-repagent.txt

index 0f9dc03= ..af1245c 100644

--- a/block/repagent/qemu-repage= nt.txt

+++ b/block/repagent/qemu-repagent.txt

@@ -1,5 +1,7 @@

=A0=A0=A0=A0 repag= ent - replication agent - a Qemu module for enabling continuous async repli= cation of VM volumes

=A0

+Ori Mamluk, 2012

<= p class=3D"MsoNormal">+

Introduction

=A0=A0=A0=A0 This document describes a feature in Qemu - a r= eplication agent (named Repagent).

=A0=A0=A0=A0 The Repagent is a new module that expos= es an API to an external replication system (AKA Rephub).

diff --git a/block/repagent/repagent.c b/block/repagent/repagent.c=

index 2e70853..a5c0636 100644

--- a/block/repagen= t/repagent.c

+++ b/block/repagent/repagent.c

<= p class=3D"MsoNormal">@@ -1,7 +1,7 @@

/*

=A0 * QEMU System Emulator replication agent

=A0 = *

- * Copyright (c) 2003 Fabrice Bellard

+ * Copyright (c) 2012 Ori Mamluk

=A0 *

=A0 * Permission is hereby granted, free of charge, = to any person obtaining a copy

=A0 * of this soft= ware and associated documentation files (the "Software"), to deal=

@@ -24,7 +24,6 @@

#include= <string.h>

#include <stdlib.h>

#include <stdio.h>

-#i= nclude <pthread.h>

#include <stdint.h>

= =A0

=A0#include "block.h"

@@ -33,21 +32,24 @@

#include "= ;repagent_client.h"

#include "repagent.h"

#include "rephub_cmds.h"

+#includ= e "qemu-queue.h"

+#include "qemu-t= hread.h"

=A0

=A0#define ZERO_MEM_OB= J(pObj) memset(pObj, 0, sizeof(*pObj))

-#define R= EPAGENT_MAX_NUM_VOLUMES (64)

#define REPAGENT_VOL= UME_ID_NONE (0)

=A0

=A0typedef struct Repa= gentVolume {

=A0=A0=A0=A0 uint64_t vol_id;

-=A0=A0=A0 const char *vol_path;

+=A0=A0=A0 char *vol_path;

=A0=A0=A0=A0 BlockDriverState *driver_ptr;

+=A0=A0=A0 QTAILQ_ENTRY(RepagentVolume) list;

} RepagentVolume;

=A0

=A0struct RepAgentState {

=A0=A0=A0=A0 bool is_init;

=A0=A0=A0=A0 int num_volumes;

-=A0=A0=A0 Repagen= tVolume *volumes[REPAGENT_MAX_NUM_VOLUMES];

+=A0= =A0=A0 QTAILQ_HEAD(RepagentVolumesList, RepagentVolume) volumes;

+=A0=A0=A0 QemuThread disconnectThread;

};

=A0

= =A0typedef struct RepagentReadVolIo {

@@ -57,9 +5= 9,9 @@ typedef struct RepagentReadVolIo {

=A0=A0=A0=A0 struct timeval start_time;

} RepagentReadVolIo;

=A0

-static int repagent_get_volume_by_driver(

+static RepagentVolume *repagent_get_volume_by_driver(

=A0=A0=A0=A0=A0=A0=A0=A0 BlockDriverState *bs);

<= p class=3D"MsoNormal">-static int repagent_get_volume_by_name(const char *n= ame);

+static RepagentVolume *repagent_get_volume= _by_name(const char *name);

static void repagent_report_volumes_to_hub(void);

static void repagent_remote_io_done(void *opaque, i= nt ret);

static struct timeval tsub(struct timeva= l t1, struct timeval t2);

@@ -68,6 +70,10 @@ RepAgentState g_rep_agent =3D { 0= };

=A0

=A0void repagen= t_init(const char *hubname, int port)

{

+=A0=A0=A0 QTAILQ_HEAD(RepagentVolumesList, RepagentVolume) tmpHead=A0 =3D<= /p>

+=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 QTAILQ_HEAD_IN= ITIALIZER(tmpHead);

+=A0=A0=A0 memcpy(&g_rep_= agent.volumes, &tmpHead, sizeof(g_rep_agent.volumes));

+

=A0=A0=A0=A0 /* It is th= e responsibility of the thread to free this struct */

=A0=A0=A0=A0 rephub_params *pParams =3D g_malloc(sizeof(rephub_params)= );

=A0=A0=A0=A0 if (hubname =3D=3D NULL) {

@@ -82,70= +88,57 @@ void repagent_init(const char *hubname, int port)

=A0=A0=A0=A0 pParams->port =3D port;

=A0=A0=A0=A0 pParams->name =3D g_strdup(hubname);

=A0

-=A0=A0=A0 pthread_t t= hread_id =3D 0;

=A0

=A0= =A0=A0=A0=A0/* Create the repagent client listener thread */

-=A0=A0=A0 pthread_create(&thread_id, 0, repagent_listen, (= void *) pParams);

-=A0=A0=A0 pthread_detach(thread_id);

+=A0=A0=A0 qemu_thread_create(&g_rep_agent.disconnectThread= , repagent_listen,

+=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0 (void *) pParams, QEMU_THREAD_DETACHED);

}

=A0

=A0void repagent_register_drive(const char *drive_path,

=A0=A0=A0=A0=A0=A0=A0=A0 BlockDriverState *driver_ptr)

{

=A0=A0=A0=A0 /* Assert that the volume is not registered yet */

-=A0=A0=A0 int i =3D repagent_get_volume_by_name(drive_path)= ;

-=A0=A0=A0 assert(i =3D=3D -1);

-

-=A0=A0=A0 /*Add the volume at the last place*/

-= =A0=A0=A0 assert(g_rep_agent.num_volumes < REPAGENT_MAX_NUM_VOLUMES);

-

-=A0=A0=A0 i =3D g_rep_= agent.num_volumes;

-=A0=A0=A0 g_rep_agent.num_volumes++;

+=A0=A0=A0 RepagentVolume *vol =3D repagent_get_volume_by_name(= drive_path);

+=A0=A0=A0 assert(vol =3D=3D NULL);<= /p>

=A0

=A0=A0=A0=A0=A0printf("zerto repagent: Register= ing drive. Num drives %d, path %s\n",

=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 g_rep_agent.num_volumes, drive_path);

-=A0=A0=A0 g_rep_agent.volumes[i] =3D

-=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (RepagentVolume *= )g_malloc(sizeof(RepagentVolume));

-=A0=A0=A0 g_r= ep_agent.volumes[i]->driver_ptr =3D driver_ptr;

+=A0=A0=A0 RepagentVolume *new_vol =3D g_malloc(sizeof(RepagentVolume));<= /p>

+=A0=A0=A0 new_vol->driver_ptr =3D driver_ptr;

=A0=A0=A0=A0 /* orim todo strcpy? */

-=A0=A0=A0 g_rep_agent.volumes[i]->vol_path =3D drive_path;<= /p>

+=A0=A0=A0 new_vol->vol_path =3D g_strdup(driv= e_path);

=A0

+

+=A0=A0=A0 QTAILQ_INSERT_HEAD(&g_rep_agent.volumes, new_vol, list= );

=A0=A0=A0=A0 /* Orim todo thread-safety? */

=A0=A0=A0=A0 g_rep_agent.num_volumes++;

=A0

=A0=A0=A0=A0=A0repagent_report_volumes_to_hub();

}

=A0

-void repagent_deregister_drive(const char *drive_path,

-=A0=A0=A0=A0=A0=A0=A0 BlockDriverState *driver_ptr)=

+void repagent_deregister_drive(BlockDriverState= *driver_ptr)

{

=A0=A0= =A0=A0 /* Orim todo thread-safety? */

-=A0=A0=A0 int i =3D repagent_get_volume_by_driver(d= river_ptr);

-=A0=A0=A0 assert(i !=3D -1);

-

-=A0=A0=A0 RepagentVolume *v= ol =3D g_rep_agent.volumes[i];

-=A0=A0=A0 /* Put the last volume in the cell of the= removed volume to maintain a

-=A0=A0=A0=A0 * con= tiguous array */

-=A0=A0=A0 g_rep_agent.volumes[i= ] =3D g_rep_agent.volumes[g_rep_agent.num_volumes - 1];

-=A0=A0=A0 g_rep_agent.volumes[g_rep_agent.num_volum= es - 1] =3D NULL;

+=A0=A0=A0 RepagentVolume *vol = =3D repagent_get_volume_by_driver(driver_ptr);

+= =A0=A0=A0 assert(vol !=3D NULL);

+

+=A0=A0=A0 QTAILQ_REMOVE= (&g_rep_agent.volumes, vol, list);

+=A0=A0=A0= g_free(vol->vol_path);

=A0=A0=A0=A0 g_rep_age= nt.num_volumes--;

=A0=A0=A0=A0 g_free(vol);

-

}

/* orim todo destruction? */

=A0

-static int repagent_get_volum= e_by_driver(

+static RepagentVolume *repagent_get_volume_by_driver(

=A0=A0=A0=A0=A0=A0=A0=A0 BlockDriverState *bs)

{

-=A0=A0=A0 /* orim todo optimize search */<= /p>

-=A0=A0=A0 int i =3D 0;

-=A0=A0=A0 for (i =3D 0; = i < g_rep_agent.num_volumes ; i++) {

-=A0=A0= =A0=A0=A0=A0=A0 RepagentVolume *p_vol =3D g_rep_agent.volumes[i];

-=A0=A0=A0=A0=A0=A0=A0 if (p_vol !=3D NULL && p_vo= l->driver_ptr =3D=3D (void *) bs) {

-=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 return i;

+=A0=A0=A0 RepagentVolume *vol =3D NULL;

+=A0=A0=A0 QTAILQ_FOREACH(vol, &g_rep_agent.volumes, list) {=

+=A0=A0=A0=A0=A0=A0=A0 if (vol !=3D NULL &&a= mp; vol->driver_ptr =3D=3D (void *)bs) {

+=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 return vol;

=A0=A0=A0=A0=A0=A0=A0=A0 }

= =A0=A0=A0=A0 }

-=A0=A0=A0 return -1;

+=A0=A0=A0 return NULL;

}

=A0

=A0void repagent_handl= e_protected_write(BlockDriverState *bs, int64_t sector_num,

@@ -160,15 +153,13 @@ void repagent_handle_protected_write(Block= DriverState *bs, int64_t sector_num,

=A0=A0=A0=A0 printf("\n");

=A0

=A0=A0=A0=A0=A0/* orim todo thread= safety? */

-=A0=A0=A0 int i =3D repagent_get_vol= ume_by_driver(bs);

-=A0=A0=A0 if (i =3D=3D -1 || g_rep_agent.volumes[i]->vol_id =3D=3D REPA= GENT_VOLUME_ID_NONE) {

+=A0=A0=A0 RepagentVolume = *vol =3D repagent_get_volume_by_driver(bs);

+=A0= =A0=A0 if (vol =3D=3D NULL || vol->vol_id =3D=3D REPAGENT_VOLUME_ID_NONE= ) {

=A0=A0=A0=A0=A0=A0=A0=A0 /* Unprotected */

=A0=A0=A0=A0=A0=A0=A0=A0 printf("Got a write to an un= protected volume.\n");

=A0=A0=A0=A0=A0=A0=A0= =A0 return;

=A0=A0=A0=A0 }

=A0

-=A0=A0=A0 RepagentVolume *p_vol =3D g_rep_ag= ent.volumes[i];

-

=A0= =A0=A0=A0 /* Report IO to rephub */

=A0

=A0=A0=A0=A0=A0int data_size =3D qiov->size;

@@ -184,7 +175,7 @@ void repagent_handle_protected_w= rite(BlockDriverState *bs, int64_t sector_num,

= =A0=A0=A0=A0=A0=A0=A0=A0 qemu_iovec_to_buffer(qiov, pdata);

=A0=A0=A0=A0 }

=A0

-=A0=A0=A0 p_cmd->v= olume_id =3D p_vol->vol_id;

+=A0=A0=A0 p_cmd-&= gt;volume_id =3D vol->vol_id;

=A0=A0=A0=A0 p_c= md->offset_sectors =3D sector_num;

=A0=A0=A0=A0 p_cmd->size_sectors =3D nb_sectors;<= /p>

=A0=A0=A0=A0 p_cmd->ret_status =3D ret_status;=

@@ -197,23 +188,26 @@ void repagent_handle_prote= cted_write(BlockDriverState *bs, int64_t sector_num,

static void repagent_report_volumes_to_hub(void)

=

{

=A0=A0=A0=A0 /* Report I= O to rephub */

-=A0=A0=A0 int i;

=A0=A0=A0=A0 RepCmdDataReportVmVolumes *p_cmd_data =3D NULL;

=A0=A0=A0=A0 RepCmdReportVmVolumes *p_cmd =3D (RepCm= dReportVmVolumes *) repcmd_new(

=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0 REPHUB_CMD_REPORT_VM_VOLUMES,

=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 g_rep_agent.num_volumes * sizeof(Re= pVmVolumeInfo),

=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (uint8_t **) &a= mp;p_cmd_data);

+=A0=A0=A0 RepagentVolume *vol = =3D QTAILQ_FIRST(&g_rep_agent.volumes);

=A0= =A0=A0=A0 p_cmd->num_volumes =3D g_rep_agent.num_volumes;

=A0=A0=A0=A0 printf("reporting %u volumes\n&quo= t;, g_rep_agent.num_volumes);

+

+=A0=A0=A0 int i;

=A0=A0=A0=A0 for (i = =3D 0; i < g_rep_agent.num_volumes ; i++) {

-=A0=A0=A0=A0=A0=A0=A0 assert(g_rep_agent.volumes[i]= !=3D NULL);

+=A0=A0=A0=A0=A0=A0=A0 assert(vol != =3D NULL);

=A0=A0=A0=A0=A0=A0=A0=A0 printf("= reporting volume %s size %u\n",

-=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 g_rep_agent.volumes[i]->v= ol_path,

+=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0 vol->vol_path,

=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0 (uint32_t) sizeof(p_cmd_data->volumes[i].name))= ;

=A0=A0=A0=A0=A0=A0=A0=A0 strncpy((char *) p_cmd_data->volumes[i].name,

-=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 g_r= ep_agent.volumes[i]->vol_path,

+=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 vol->vol_path,

=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 sizeof(p_cmd_data->v= olumes[i].name));

-=A0=A0=A0=A0=A0=A0=A0 p_cmd_data->volumes[i].vol= ume_id =3D g_rep_agent.volumes[i]->vol_id;

+= =A0=A0=A0=A0=A0=A0=A0 p_cmd_data->volumes[i].volume_id =3D vol->vol_i= d;

+=A0=A0=A0=A0=A0=A0=A0 vol =3D QTAILQ_NEXT(vol= , list);

=A0=A0=A0=A0 }

=A0=A0=A0= =A0 if (repagent_client_send((RepCmd *) p_cmd) !=3D 0) {

=A0=A0=A0=A0=A0=A0=A0=A0 printf("Error sending command\n"= );

@@ -225,51 +219,49 @@ bool repaget_start_prote= ct(RepCmdStartProtect *pcmd,

{

=A0=A0=A0=A0 printf(&quo= t;Start protect vol %s, ID %llu\n", pcmd_data->volume_name,

=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (unsigned long long= ) pcmd->volume_id);

-=A0=A0=A0 int vol_index =3D repagent_get_volume_by_name(pcmd_data->volu= me_name);

+=A0=A0=A0 RepagentVolume *vol =3D repa= gent_get_volume_by_name(pcmd_data->volume_name);

=A0=A0=A0=A0 if (g_rep_agent.num_volumes > 0

=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 && strc= mp(pcmd_data->volume_name, "stam") =3D=3D 0) {

=A0=A0=A0=A0=A0=A0=A0=A0 /* Choose the first one for rephub */

-=A0=A0=A0=A0=A0=A0=A0 vol_index =3D 0;

+=A0=A0=A0=A0=A0=A0=A0 vol =3D QTAILQ_LAST(&g_re= p_agent.volumes, RepagentVolumesList);

=A0=A0=A0= =A0 }

-=A0=A0=A0 if (vol_index < 0) {

+=A0=A0=A0 if (vol =3D=3D NULL) {

=A0=A0=A0=A0=A0=A0=A0=A0 printf("The volume doe= sn't exist\n");

=A0=A0=A0=A0=A0=A0=A0=A0= return true;

=A0=A0=A0=A0 }

=A0=A0=A0=A0 /* orim todo protect */

-=A0=A0=A0 g_rep_agent.volumes[vol_index]->vol_id =3D pcmd->volume_id= ;

+=A0=A0=A0 vol->vol_id =3D pcmd->volume_i= d;

=A0

=A0=A0=A0=A0=A0r= eturn true;

}

=A0

-static int repag= ent_get_volume_by_name(const char *name)

+static = RepagentVolume *repagent_get_volume_by_name(const char *name)

{

-=A0=A0=A0 int i =3D 0;

-=A0=A0=A0 for (i =3D 0; i < g_rep_agent.num_volumes ; i++) {

-=A0=A0=A0=A0=A0=A0=A0 if (g_rep_agent.volumes[i] !=3D N= ULL

-=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0 && strcmp(name, g_rep_agent.volumes[i]->vol_path) =3D=3D 0) = {

-=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 return i;

+=A0=A0=A0 RepagentVolume *vol =3D NULL;

+=A0=A0=A0 QTAILQ_FOREACH(vol, &g_rep_agent.volumes, list) {=

+=A0=A0=A0=A0=A0=A0=A0 if (vol !=3D NULL &&a= mp; strcmp(name, vol->vol_path) =3D=3D 0) {

+=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 return vol;

=A0=A0=A0=A0=A0=A0=A0=A0 }

= =A0=A0=A0=A0 }

-=A0=A0=A0 return -1;

+=A0=A0=A0 return NULL;

}

=A0

-static int repagent_g= et_volume_by_id(uint64_t vol_id)

+static Repagent= Volume *repagent_get_volume_by_id(uint64_t vol_id)

{

-=A0=A0=A0 int i =3D 0;

-= =A0=A0=A0 for (i =3D 0; i < g_rep_agent.num_volumes ; i++) {

-=A0=A0=A0=A0=A0=A0=A0 if (g_rep_agent.volumes[i] !=3D NULL<= /p>

-=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 &a= mp;& g_rep_agent.volumes[i]->vol_id =3D=3D vol_id) {

-=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 return i;

+=A0=A0=A0 RepagentVolume *vol =3D NULL;

+=A0=A0=A0 QTAILQ_FOREACH(vol, &g_rep_agent.volumes, list) {=

+=A0=A0=A0=A0=A0=A0=A0 if (vol !=3D NULL &&a= mp; vol->vol_id =3D=3D vol_id) {

+=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 return vol;

=A0=A0=A0=A0=A0=A0=A0=A0 }

= =A0=A0=A0=A0 }

-=A0=A0=A0 return -1;

+=A0=A0=A0 return NULL;

}

=A0

=A0bool repagent_remot= e_io(RepCmdRemoteIoReq *pcmd, uint8_t *pdata)

{

-=A0=A0=A0 int index =3D repagent_get_volume_by_id= (pcmd->volume_id);

+=A0=A0=A0 RepagentVolume *vol =3D repagent_get_volu= me_by_id(pcmd->volume_id);

=A0=A0=A0=A0 int si= ze_bytes =3D pcmd->size_sectors * 512;

-=A0=A0= =A0 if (index < 0) {

+=A0=A0=A0 if (vol =3D=3D NULL) {

=A0=A0=A0=A0=A0=A0=A0=A0 printf("Vol read - Could not find vol= id %llx\n",

=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0 (unsigned long long int) pcmd->volume_id);

=A0=A0=A0=A0=A0=A0=A0=A0 RepCmdRemoteIoRes *p_res_cm= d =3D (RepCmdRemoteIoRes *) repcmd_new(

@@ -282,7= +274,7 @@ bool repagent_remote_io(RepCmdRemoteIoReq *pcmd, uint8_t *pdata)=

=A0=A0=A0=A0 }

=A0

=A0= =A0=A0=A0=A0printf("Vol read - driver %p, volId %llu, offset %llu, siz= e %u\n",

-=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 = g_rep_agent.volumes[index]->driver_ptr,

+=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 vol->driver_pt= r,

=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 (unsigned= long long int) pcmd->volume_id,

=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0 (unsigned long long int) pcmd->offset_sectors, = pcmd->size_sectors);

=A0

@@ -296,7 +288,7 @@ bo= ol repagent_remote_io(RepCmdRemoteIoReq *pcmd, uint8_t *pdata)

=A0=A0=A0=A0=A0=A0=A0=A0 qemu_iovec_init(&io_xaction->= ;qiov, 1);

=A0

=A0=A0=A0=A0=A0=A0=A0=A0=A0/*read_xact->bu= f =3D

-=A0=A0=A0=A0=A0=A0=A0 qemu_blockalign(g_re= p_agent.volumes[index]->driver_ptr, size_bytes); */

+=A0 =A0=A0=A0=A0=A0=A0qemu_blockalign(vol->driver_ptr, size_bytes= ); */

=A0=A0=A0=A0=A0=A0=A0=A0 io_xaction->buf =3D (uin= t8_t *) g_malloc(size_bytes);

=A0=A0=A0=A0=A0=A0= =A0=A0 io_xaction->rep_cmd =3D *pcmd;

=A0=A0= =A0=A0=A0=A0=A0=A0 qemu_iovec_add(&io_xaction->qiov, io_xaction->= buf, size_bytes);

@@ -305,12 +297,12 @@ bool repagent_remote_io(RepCmd= RemoteIoReq *pcmd, uint8_t *pdata)

=A0=A0=A0=A0= =A0=A0=A0=A0 /* orim TODO - use the returned acb to cancel the request on s= hutdown */

=A0=A0=A0=A0=A0=A0=A0=A0 /*acb =3D */

=A0=A0=A0= =A0=A0=A0=A0=A0 if (pcmd->is_read) {

-=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0 bdrv_aio_readv(g_rep_agent.volumes[index]->d= river_ptr,

+=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 bdr= v_aio_readv(vol->driver_ptr,

=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0 io_xaction->rep_cmd.offset_sectors, &io_xaction->qiov,<= /p>

=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0 io_xaction->rep_cmd.size_sectors, repagent_remote_io_done,<= /p>

=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 io_xaction);

=A0=A0=A0=A0=A0=A0=A0=A0 } else {

-=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 bdrv_aio_writev(g_rep_agent.vo= lumes[index]->driver_ptr,

+=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0 bdrv_aio_writev(vol->driver_ptr,

=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0 io_xaction->rep_cmd.offset_sectors, &io_xaction->qiov,<= /p>

=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0 io_xaction->rep_cmd.size_sectors, repagent_remote_io_done,<= /p>

=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 io_xaction);

diff --git a/block/repagent/repagent.h b/block/rep= agent/repagent.h

index 2863ffc..157a9b6 100644

--- a/block/repagent/repagent.h

+++ b/block/repagent/repagent.h

@@ -1,7 +1,7 @@

/*

=A0 * QEMU System Emulator

=A0*

- * Copyright (c) 2003-2008 Fabrice Bellard

+ * Copyright (c) 2012 Ori Mamluk

=A0 *

=A0 * Permission is hereby granted,= free of charge, to any person obtaining a copy

= =A0 * of this software and associated documentation files (the "Softwa= re"), to deal

@@ -42,8 +42,7 @@ void repagent_handle_protected_wri= te(BlockDriverState *bs,

=A0=A0=A0=A0=A0=A0=A0=A0= int nb_sectors, QEMUIOVector *qiov, int ret_status);

void repagent_register_drive(const char *drive_path,

=A0=A0=A0=A0=A0=A0=A0=A0 BlockDriverState *driver_pt= r);

-void repagent_deregister_drive(const char *d= rive_path,

-=A0=A0=A0=A0=A0=A0=A0 BlockDriverStat= e *driver_ptr);

+void repagent_deregister_drive(BlockDriverState *driver_ptr);

bool repaget_start_protect(RepCmdStartProtect *pcmd,

=A0=A0=A0=A0=A0=A0=A0=A0 RepCmdDataStartProtect *pcmd_da= ta);

bool repagent_remote_io(struct RepCmdRemoteIoReq *pcmd, uint8_t *pdata);

diff --git a/block/repagent/repagent_client.c b/blo= ck/repagent/repagent_client.c

index 9d826c4..2e57= ed0 100644

--- a/block/repagent/repagent_client.c

+++ b/block/repagent/repagent_client.c

@@ -1,7 +1,7 @@

/*

=A0 * QEMU System Emulator replication agent - socket client

=A0 *

- * Copyright (c) 20= 03 Fabrice Bellard

+ * Copyright (c) 2012 Ori Mam= luk

=A0 *

=A0 * Permiss= ion is hereby granted, free of charge, to any person obtaining a copy

=A0 * of this software and associated documentation = files (the "Software"), to deal

diff --= git a/block/repagent/repagent_client.h b/block/repagent/repagent_client.h

index 62a5377..6eaafed 100644

--- a/block/repagent/repagent_client.h

+++ b/= block/repagent/repagent_client.h

@@ -1,7 +1,7 @@<= /p>

/*

- * QEMU System Emulator

+ * QEMU System Emulator - replication agent client

=A0 *

- * Copyright (c) 2003-2008 Fabrice= Bellard

+ * Copyright (c) 2012 Ori Mamluk

=A0 *

=A0 * Permission is hereby granted,= free of charge, to any person obtaining a copy

= =A0 * of this software and associated documentation files (the "Softwa= re"), to deal

diff --git a/block/repagent/repagent_drv.c b/block/r= epagent/repagent_drv.c

index 4775166..1795de1 100= 644

--- a/block/repagent/repagent_drv.c

+++ b/block/repagent/repagent_drv.c

@@ -1,7 +1,7 = @@

/*

=A0 * QEMU System= Emulator replication agent - repagent block driver

=A0 *

- * Copyright (c) 2003 Fabrice Bellard

+ * Copyright (c) 2012 Ori Mamluk

= =A0 *

=A0 * Permission is hereby granted, free of= charge, to any person obtaining a copy

=A0 * of this software and associated documentation = files (the "Software"), to deal

@@ -68,= 6 +68,7 @@ static int coroutine_fn repagent_co_writev(BlockDriverState *bs,=

static void repagent_close(BlockDriverState *bs)

=

{

=A0=A0=A0=A0 printf(&quo= t;%s\n", __func__);

+=A0=A0=A0 repagent_dere= gister_drive(bs);

}

=A0

=A0static int coroutine_fn repagent_co_flush(BlockDriverState *bs)

@@ -88,11 +89,12 @@ static int repagent_truncate(Bl= ockDriverState *bs, int64_t offset)

=A0=A0=A0=A0 return bdrv_truncate(bs->file, offse= t);

}

=A0

+/* orim todo maybe use probe for planting repagent in every= driver */

static int repagent_probe(const uint8_t *buf, int buf_size,

=A0=A0=A0=A0=A0=A0=A0=A0 const char *filename)

{

=A0=A0=A0=A0 printf("%s\n", = __func__);

-=A0=A0=A0 return 1; /* everything can be opened as raw image */

+=A0=A0=A0 return 0; /* everything can be opened as raw ima= ge */

}

=A0

=A0static int coroutine_fn repagent_co_discard(BlockDriverSt= ate *bs,

diff --git a/block/repagent/repcmd_listener.c b/bloc= k/repagent/repcmd_listener.c

index e6b4d74..0998f= 44 100644

--- a/block/repagent/repcmd_listener.c<= /p>

+++ b/block/repagent/repcmd_listener.c

@@ -1,7 +1,7 @@

/*

=A0 * QEMU System Emulator replication agent - socket commands l= ayer

=A0 *

- * Copyright (c) 20= 03 Fabrice Bellard

+ * Copyright (c) 2012 Ori Mam= luk

=A0 *

=A0 * Permiss= ion is hereby granted, free of charge, to any person obtaining a copy

=A0 * of this software and associated documentation = files (the "Software"), to deal

diff --= git a/block/repagent/repcmd_listener.h b/block/repagent/repcmd_listener.h

index 19b9ea9..629cdb5 100644

--- a/block/repagent/repcmd_listener.h

+++ b/= block/repagent/repcmd_listener.h

@@ -1,7 +1,7 @@<= /p>

/*

=A0 * QEMU System Emulator

=A0 *

- * Copyright (c) 2003-2008 Fabrice = Bellard

+ * Copyright (c) 2012 Ori Mamluk

=A0 *

=A0 * Permission is hereby granted, free of= charge, to any person obtaining a copy

=A0 * of = this software and associated documentation files (the "Software")= , to deal

diff --git a/block/repagent/rephub_cmds.h b/block/re= pagent/rephub_cmds.h

index cb737e6..5075f33 10064= 4

--- a/block/repagent/rephub_cmds.h

+++ b/block/repagent/rephub_cmds.h

@@ -1,7 +1,7 @= @

/*

=A0 * QEMU System = Emulator

=A0 *

- * Copy= right (c) 2003-2008 Fabrice Bellard

+ * Copyright (c) 2012 Ori Mamluk

=A0 *

=A0 * Permission is hereby granted,= free of charge, to any person obtaining a copy

= =A0 * of this software and associated documentation files (the "Softwa= re"), to deal

diff --git a/block/repagent/rephub_defs.h b/block/re= pagent/rephub_defs.h

index f036f58..575e9f8 10064= 4

--- a/block/repagent/rephub_defs.h

+++ b/block/repagent/rephub_defs.h

@@ -1,7 +1,7 @= @

/*

=A0 * QEMU System = Emulator

=A0 *

- * Copy= right (c) 2003-2008 Fabrice Bellard

+ * Copyright (c) 2012 Ori Mamluk

=A0 *

=A0 * Permission is hereby granted,= free of charge, to any person obtaining a copy

= =A0 * of this software and associated documentation files (the "Softwa= re"), to deal

--

1.7.6.5

--00248c768f9e18b84b04bced9092--