All the mail mirrored from lore.kernel.org
 help / color / mirror / Atom feed
From: Don Slutz <dslutz@verizon.com>
To: qemu-devel@nongnu.org
Cc: "Michael S. Tsirkin" <mst@redhat.com>,
	"Markus Armbruster" <armbru@redhat.com>,
	"Don Slutz" <dslutz@verizon.com>,
	"Luiz Capitulino" <lcapitulino@redhat.com>,
	"Don Slutz" <don.slutz@gmail.com>,
	"Anthony Liguori" <aliguori@amazon.com>,
	"Paolo Bonzini" <pbonzini@redhat.com>,
	"Andreas Färber" <afaerber@suse.de>,
	"Richard Henderson" <rth@twiddle.net>
Subject: [Qemu-devel] [PATCH v7 7/9] vmport_rpc: Add migration
Date: Fri, 12 Jun 2015 10:05:54 -0400	[thread overview]
Message-ID: <1434117956-4929-8-git-send-email-dslutz@verizon.com> (raw)
In-Reply-To: <1434117956-4929-1-git-send-email-dslutz@verizon.com>

Signed-off-by: Don Slutz <dslutz@verizon.com>
CC: Don Slutz <don.slutz@gmail.com>
---
 hw/misc/vmport_rpc.c | 250 +++++++++++++++++++++++++++++++++++++++++++++++++++
 trace-events         |   2 +
 2 files changed, 252 insertions(+)

diff --git a/hw/misc/vmport_rpc.c b/hw/misc/vmport_rpc.c
index e122bad..4984193 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;
@@ -1183,6 +1191,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);
@@ -1190,6 +1439,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 cfb3ffa..fbfcd86 100644
--- a/trace-events
+++ b/trace-events
@@ -908,6 +908,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

  parent reply	other threads:[~2015-06-12 14:06 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-06-12 14:05 [Qemu-devel] [PATCH v7 0/9] Add limited support of VMware's hyper-call rpc Don Slutz
2015-06-12 14:05 ` [Qemu-devel] [BUGFIX][PATCH v7 1/9] vmport: The io memory region needs to be at least a size of 4 Don Slutz
2015-06-12 22:38   ` Eric Blake
2015-06-15 13:53     ` Don Slutz
2015-06-15 15:09       ` Eric Blake
2015-06-15 16:15         ` Don Slutz
2015-06-12 14:05 ` [Qemu-devel] [PATCH v7 2/9] vmport: Switch to trace Don Slutz
2015-06-12 14:05 ` [Qemu-devel] [BUGFIX][PATCH v7 3/9] vmport: Fix vmport_cmd_ram_size Don Slutz
2015-06-12 14:05 ` [Qemu-devel] [PATCH v7 4/9] vmport_rpc: Add the object vmport_rpc Don Slutz
2015-06-12 14:05 ` [Qemu-devel] [PATCH v7 5/9] vmport_rpc: Add limited support of VMware's hyper-call rpc Don Slutz
2015-06-12 14:05 ` [Qemu-devel] [PATCH v7 6/9] vmport_rpc: Add QMP access to vmport_rpc object Don Slutz
2015-06-15 15:53   ` Eric Blake
2015-06-17 16:42     ` Don Slutz
2015-06-12 14:05 ` Don Slutz [this message]
2015-06-12 14:05 ` [Qemu-devel] [PATCH v7 8/9] vmport: Add VMware all ring hack Don Slutz
2015-06-12 14:05 ` [Qemu-devel] [PATCH v7 9/9] MAINTAINERS: add VMware port Don Slutz
2015-06-17 13:44 ` [Qemu-devel] [PATCH v7 0/9] Add limited support of VMware's hyper-call rpc Paolo Bonzini
2015-06-17 22:26   ` Don Slutz
2015-06-18  7:58     ` Michael S. Tsirkin
2015-06-18  8:33       ` Paolo Bonzini
2015-06-18  9:40         ` Michael S. Tsirkin
2015-06-18  8:33     ` Paolo Bonzini
2015-06-17 14:11 ` Michael S. Tsirkin
2015-06-17 14:13   ` Paolo Bonzini
2015-06-17 14:18     ` Michael S. Tsirkin
2015-06-17 14:27       ` Paolo Bonzini
2015-06-17 14:29         ` Michael S. Tsirkin
2015-06-17 16:17           ` Paolo Bonzini
2015-06-17 16:29             ` Michael S. Tsirkin
2015-06-17 16:48               ` Paolo Bonzini
2015-06-17 18:43                 ` Michael S. Tsirkin
2015-06-17 19:15                   ` Paolo Bonzini
2015-06-17 19:22                     ` Michael S. Tsirkin
2015-06-17 19:24                       ` Paolo Bonzini
2015-06-17 19:29                         ` Michael S. Tsirkin
2015-06-17 17:03               ` Don Slutz
2015-06-17 17:14                 ` Paolo Bonzini
2015-06-17 17:25                   ` Paolo Bonzini
2015-06-17 17:34                     ` Don Slutz
2015-06-17 18:58                       ` Michael S. Tsirkin
2015-06-18 18:40                         ` Don Slutz
2015-06-17 18:45                   ` Michael S. Tsirkin
2015-06-17 18:45                 ` Michael S. Tsirkin
2015-06-18  7:03             ` Gerd Hoffmann

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=1434117956-4929-8-git-send-email-dslutz@verizon.com \
    --to=dslutz@verizon.com \
    --cc=afaerber@suse.de \
    --cc=aliguori@amazon.com \
    --cc=armbru@redhat.com \
    --cc=don.slutz@gmail.com \
    --cc=lcapitulino@redhat.com \
    --cc=mst@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=rth@twiddle.net \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.