[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v2 5/7] vmport_rpc: Add migration
From: |
Don Slutz |
Subject: |
[Qemu-devel] [PATCH v2 5/7] vmport_rpc: Add migration |
Date: |
Mon, 27 Apr 2015 18:46:02 -0400 |
Signed-off-by: Don Slutz <address@hidden>
---
hw/misc/vmport_rpc.c | 250 +++++++++++++++++++++++++++++++++++++++++++++++++++
trace-events | 8 +-
2 files changed, 255 insertions(+), 3 deletions(-)
diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
index 0ba3319..a147561 100644
--- a/hw/misc/vmport_rpc.c
+++ b/hw/misc/vmport_rpc.c
@@ -171,6 +171,14 @@ typedef struct VMPortRpcState {
uint32_t open_cookie;
channel_t chans[GUESTMSG_MAX_CHANNEL];
GHashTable *guestinfo;
+ /* Temporary cache for migration purposes */
+ int32_t mig_chan_num;
+ int32_t mig_bucket_num;
+ uint32_t mig_guestinfo_size;
+ uint32_t mig_guestinfo_off;
+ uint8_t *mig_guestinfo_buf;
+ channel_control_t *mig_chans;
+ bucket_control_t *mig_buckets;
#ifdef VMPORT_RPC_DEBUG
unsigned int end;
unsigned int last;
@@ -1168,6 +1176,247 @@ static Property vmport_rpc_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
+static const VMStateDescription vmstate_vmport_rpc_chan = {
+ .name = "vmport_rpc/chan",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField [])
+ {
+ VMSTATE_UINT64(active_time, channel_control_t),
+ VMSTATE_UINT32(chan_id, channel_control_t),
+ VMSTATE_UINT32(cookie, channel_control_t),
+ VMSTATE_UINT32(proto_num, channel_control_t),
+ VMSTATE_UINT16(send_len, channel_control_t),
+ VMSTATE_UINT16(send_idx, channel_control_t),
+ VMSTATE_UINT16(send_buf_max, channel_control_t),
+ VMSTATE_UINT8(recv_read, channel_control_t),
+ VMSTATE_UINT8(recv_write, channel_control_t),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static const VMStateDescription vmstate_vmport_rpc_bucket = {
+ .name = "vmport_rpc/bucket",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField [])
+ {
+ VMSTATE_UINT16(recv_len, bucket_control_t),
+ VMSTATE_UINT16(recv_idx, bucket_control_t),
+ VMSTATE_UINT16(recv_buf_max, bucket_control_t),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
+static void vmport_rpc_size_mig_guestinfo(gpointer key, gpointer value,
+ gpointer opaque)
+{
+ VMPortRpcState *s = opaque;
+ unsigned int key_len = strlen(key) + 1;
+ guestinfo_t *gi = value;
+
+ s->mig_guestinfo_size += 1 + key_len + 4 + gi->val_max;
+}
+
+static void vmport_rpc_fill_mig_guestinfo(gpointer key, gpointer value,
+ gpointer opaque)
+{
+ VMPortRpcState *s = opaque;
+ unsigned int key_len = strlen(key) + 1;
+ guestinfo_t *gi = value;
+
+ assert(gi->val_len <= gi->val_max);
+ trace_vmport_rpc_fill_mig_guestinfo(key_len, key_len, key, gi->val_len,
+ gi->val_len, gi->val_data);
+ s->mig_guestinfo_buf[s->mig_guestinfo_off++] = key_len;
+ memcpy(s->mig_guestinfo_buf + s->mig_guestinfo_off, key, key_len);
+ s->mig_guestinfo_off += key_len;
+ s->mig_guestinfo_buf[s->mig_guestinfo_off++] = gi->val_len >> 8;
+ s->mig_guestinfo_buf[s->mig_guestinfo_off++] = gi->val_len;
+ s->mig_guestinfo_buf[s->mig_guestinfo_off++] = gi->val_max >> 8;
+ s->mig_guestinfo_buf[s->mig_guestinfo_off++] = gi->val_max;
+ memcpy(s->mig_guestinfo_buf + s->mig_guestinfo_off, gi->val_data,
+ gi->val_max);
+ s->mig_guestinfo_off += gi->val_max;
+}
+
+static int vmport_rpc_pre_load(void *opaque)
+{
+ VMPortRpcState *s = opaque;
+
+ g_free(s->mig_guestinfo_buf);
+ s->mig_guestinfo_buf = NULL;
+ s->mig_guestinfo_size = 0;
+ s->mig_guestinfo_off = 0;
+ g_free(s->mig_chans);
+ s->mig_chans = NULL;
+ s->mig_chan_num = 0;
+ g_free(s->mig_buckets);
+ s->mig_buckets = NULL;
+ s->mig_bucket_num = 0;
+
+ return 0;
+}
+
+static void vmport_rpc_pre_save(void *opaque)
+{
+ VMPortRpcState *s = opaque;
+ unsigned int i;
+ unsigned int mig_chan_idx = 0;
+ unsigned int mig_bucket_idx = 0;
+
+ (void)vmport_rpc_pre_load(opaque);
+ for (i = 0; i < GUESTMSG_MAX_CHANNEL; ++i) {
+ channel_t *c = &s->chans[i];
+
+ if (c->ctl.proto_num) {
+ unsigned int j;
+
+ s->mig_chan_num++;
+ for (j = 0; j < MAX_BKTS; ++j) {
+ bucket_t *b = &c->recv_bkt[j];
+
+ s->mig_bucket_num++;
+ s->mig_guestinfo_size +=
+ (b->ctl.recv_buf_max + 1) * CHAR_PER_CALL;
+ }
+ s->mig_guestinfo_size += (c->ctl.send_buf_max + 1) * CHAR_PER_CALL;
+ }
+ }
+ g_hash_table_foreach(s->guestinfo, vmport_rpc_size_mig_guestinfo, s);
+ s->mig_guestinfo_size++;
+ s->mig_guestinfo_buf = g_malloc(s->mig_guestinfo_size);
+ s->mig_chans = g_malloc(s->mig_chan_num * sizeof(channel_control_t));
+ s->mig_buckets = g_malloc(s->mig_bucket_num * sizeof(bucket_control_t));
+
+ for (i = 0; i < GUESTMSG_MAX_CHANNEL; ++i) {
+ channel_t *c = &s->chans[i];
+
+ if (c->ctl.proto_num) {
+ unsigned int j;
+ channel_control_t *cm = s->mig_chans + mig_chan_idx++;
+ unsigned int send_chars = (c->ctl.send_buf_max + 1) *
CHAR_PER_CALL;
+
+ *cm = c->ctl;
+ for (j = 0; j < MAX_BKTS; ++j) {
+ bucket_t *b = &c->recv_bkt[j];
+ bucket_control_t *bm = s->mig_buckets + mig_bucket_idx++;
+ unsigned int recv_chars =
+ (b->ctl.recv_buf_max + 1) * CHAR_PER_CALL;
+
+ *bm = b->ctl;
+ memcpy(s->mig_guestinfo_buf + s->mig_guestinfo_off,
+ b->recv.words, recv_chars);
+ s->mig_guestinfo_off += recv_chars;
+ }
+ memcpy(s->mig_guestinfo_buf + s->mig_guestinfo_off,
+ c->send.words, send_chars);
+ s->mig_guestinfo_off += send_chars;
+ }
+ }
+ g_hash_table_foreach(s->guestinfo, vmport_rpc_fill_mig_guestinfo, s);
+ s->mig_guestinfo_buf[s->mig_guestinfo_off++] = 0;
+ assert(s->mig_guestinfo_size == s->mig_guestinfo_off);
+ assert(s->mig_chan_num == mig_chan_idx);
+ assert(s->mig_bucket_num == mig_bucket_idx);
+}
+
+static int vmport_rpc_post_load(void *opaque, int version_id)
+{
+ VMPortRpcState *s = opaque;
+ unsigned int i;
+ unsigned int key_len;
+ unsigned int mig_bucket_idx = 0;
+
+ s->mig_guestinfo_off = 0;
+ for (i = 0; i < s->mig_chan_num; ++i) {
+ channel_control_t *cm = s->mig_chans + i;
+ channel_t *c = &s->chans[cm->chan_id];
+ unsigned int j;
+ unsigned int send_chars;
+
+ c->ctl = *cm;
+ for (j = 0; j < MAX_BKTS; ++j) {
+ bucket_t *b = &c->recv_bkt[j];
+ bucket_control_t *bm = s->mig_buckets + mig_bucket_idx++;
+ unsigned int recv_chars;
+
+ b->ctl = *bm;
+ recv_chars = (b->ctl.recv_buf_max + 1) * CHAR_PER_CALL;
+ b->recv.words =
+ g_memdup(s->mig_guestinfo_buf + s->mig_guestinfo_off,
+ recv_chars);
+ s->mig_guestinfo_off += recv_chars;
+ }
+ send_chars = (c->ctl.send_buf_max + 1) * CHAR_PER_CALL;
+ c->send.words = g_memdup(s->mig_guestinfo_buf + s->mig_guestinfo_off,
+ send_chars);
+ s->mig_guestinfo_off += send_chars;
+ }
+ assert(s->mig_bucket_num == mig_bucket_idx);
+
+ do {
+ key_len = s->mig_guestinfo_buf[s->mig_guestinfo_off++];
+ if (key_len) {
+ gpointer key = g_memdup(s->mig_guestinfo_buf +
s->mig_guestinfo_off,
+ key_len);
+ guestinfo_t *gi = g_malloc(sizeof(guestinfo_t));
+ unsigned int bhi, blow;
+
+ s->mig_guestinfo_off += key_len;
+ bhi = s->mig_guestinfo_buf[s->mig_guestinfo_off++];
+ blow = s->mig_guestinfo_buf[s->mig_guestinfo_off++];
+ gi->val_len = (bhi << 8) + blow;
+ bhi = s->mig_guestinfo_buf[s->mig_guestinfo_off++];
+ blow = s->mig_guestinfo_buf[s->mig_guestinfo_off++];
+ gi->val_max = (bhi << 8) + blow;
+ assert(gi->val_len <= gi->val_max);
+ gi->val_data = g_memdup(s->mig_guestinfo_buf +
+ s->mig_guestinfo_off,
+ gi->val_max);
+ s->mig_guestinfo_off += gi->val_max;
+ trace_vmport_rpc_post_load(key_len, key_len, key, gi->val_len,
+ gi->val_len, gi->val_data);
+ assert(!g_hash_table_lookup(s->guestinfo, key));
+ g_hash_table_insert(s->guestinfo, key, gi);
+ }
+ } while (key_len);
+ assert(s->mig_guestinfo_size == s->mig_guestinfo_off);
+
+ (void)vmport_rpc_pre_load(opaque);
+ return 0;
+}
+
+static const VMStateDescription vmstate_vmport_rpc = {
+ .name = "vmport_rpc",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .pre_save = vmport_rpc_pre_save,
+ .pre_load = vmport_rpc_pre_load,
+ .post_load = vmport_rpc_post_load,
+ .fields = (VMStateField[])
+ {
+ VMSTATE_UINT64(reset_time, VMPortRpcState),
+ VMSTATE_UINT64(build_number_value, VMPortRpcState),
+ VMSTATE_UINT64(build_number_time, VMPortRpcState),
+ VMSTATE_UINT64(ping_time, VMPortRpcState),
+ VMSTATE_UINT32(open_cookie, VMPortRpcState),
+ VMSTATE_INT32(mig_chan_num, VMPortRpcState),
+ VMSTATE_STRUCT_VARRAY_ALLOC(mig_chans, VMPortRpcState, mig_chan_num,
+ 0, vmstate_vmport_rpc_chan,
+ channel_control_t),
+ VMSTATE_INT32(mig_bucket_num, VMPortRpcState),
+ VMSTATE_STRUCT_VARRAY_ALLOC(mig_buckets, VMPortRpcState,
+ mig_bucket_num, 0,
+ vmstate_vmport_rpc_bucket,
+ bucket_control_t),
+ VMSTATE_UINT32(mig_guestinfo_size, VMPortRpcState),
+ VMSTATE_VBUFFER_ALLOC_UINT32(mig_guestinfo_buf, VMPortRpcState, 1,
+ NULL, 0, mig_guestinfo_size),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
static void vmport_rpc_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -1175,6 +1424,7 @@ static void vmport_rpc_class_init(ObjectClass *klass,
void *data)
dc->realize = vmport_rpc_realize;
dc->reset = vmport_rpc_reset;
dc->props = vmport_rpc_properties;
+ dc->vmsd = &vmstate_vmport_rpc;
}
static const TypeInfo vmport_rpc_info = {
diff --git a/trace-events b/trace-events
index 784397d..1324b9f 100644
--- a/trace-events
+++ b/trace-events
@@ -891,9 +891,9 @@ vmport_detail_rpc_end(int sub_cmd, unsigned int ax,
unsigned int bx, unsigned in
vmport_rpc_send_skip(char *prefix, unsigned int end, unsigned int len,
unsigned int k, size_t out_size, char *out) "%s%d[%d,%d,%zu]%s"
vmport_rpc_send_normal(char *prefix, unsigned int end, unsigned int len,
unsigned int k, size_t out_size, char *out) "%s%d[%d,%d,%zu]%s"
vmport_rpc_recv_normal(char *prefix, unsigned int end, unsigned int len,
unsigned int k, size_t out_size, char *out) "%s%d[%d,%d,%zu]%s"
-vmport_rpc_get_guestinfo(int klen, int kmaxlen, char *key) "klen=%d key=%.*s"
-vmport_rpc_get_guestinfo_found(int vlen, int vmaxlen, char *val) "vlen=%d
val=%.*s"
-vmport_rpc_set_guestinfo(int klen, int kmaxlen, char *key, int vlen, int
vmaxlen, char *val) "klen=%d key=%.*s vlen=%d val=%.*s"
+vmport_rpc_get_guestinfo(short klen, int kmaxlen, char *key) "klen=%d key=%.*s"
+vmport_rpc_get_guestinfo_found(short vlen, int vmaxlen, char *val) "vlen=%d
val=%.*s"
+vmport_rpc_set_guestinfo(short klen, int kmaxlen, char *key, short vlen, int
vmaxlen, char *val) "klen=%d key=%.*s vlen=%d val=%.*s"
vmport_rpc_set_guestinfo_bad(int i, int used_guestinfo) "i=%d not allocated,
but used_guestinfo=%d"
vmport_rpc_send_big(int len, size_t maxlen) "recv_len=%d >= %zd"
vmport_rpc_sweep(int chan_id, long delta) "flush %d. delta=%ld"
@@ -906,6 +906,8 @@ vmport_detail_rpc_process_send_size(int chan_id, int
send_len) "chan %d is %d"
vmport_detail_rpc_process_recv_size(int chan_id, int send_len) "chan %d is %d"
vmport_rpc_process_close(int chan_id) "chan %d"
vmport_rpc_process_open(int chan_id, int proto_num) "chan %d proto 0x%x"
+vmport_rpc_fill_mig_guestinfo(short klen, int kmaxlen, char *key, short vlen,
int vmaxlen, char *val) "klen=%d key=%.*s vlen=%d val=%.*s"
+vmport_rpc_post_load(short klen, int kmaxlen, char *key, short vlen, int
vmaxlen, char *val) "klen=%d key=%.*s vlen=%d val=%.*s"
# hw/scsi/vmw_pvscsi.c
pvscsi_ring_init_data(uint32_t txr_len_log2, uint32_t rxr_len_log2) "TX/RX
rings logarithms set to %d/%d"
--
1.8.4
- [Qemu-devel] [PATCH v2 0/7] Add limited support of VMware's hyper-call rpc, Don Slutz, 2015/04/27
- [Qemu-devel] [PATCH v2 1/7] vmport.c: Fix vmport_cmd_ram_size, Don Slutz, 2015/04/27
- [Qemu-devel] [PATCH v2 5/7] vmport_rpc: Add migration,
Don Slutz <=
- [Qemu-devel] [PATCH v2 7/7] MAINTAINERS: add VMware port, Don Slutz, 2015/04/27
- [Qemu-devel] [PATCH v2 3/7] vmport_rpc: Add limited support of VMware's hyper-call rpc, Don Slutz, 2015/04/27
- [Qemu-devel] [PATCH v2 4/7] vmport_rpc: Add QMP access to vmport_rpc object., Don Slutz, 2015/04/27
- [Qemu-devel] [PATCH v2 2/7] vmport_rpc: Add the object vmport_rpc, Don Slutz, 2015/04/27
- [Qemu-devel] [PATCH v2 6/7] vmport: Add VMware all ring hack, Don Slutz, 2015/04/27
- Re: [Qemu-devel] [PATCH v2 0/7] Add limited support of VMware's hyper-call rpc, Don Slutz, 2015/04/27