summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYonit Halperin <yhalperi@redhat.com>2012-08-05 10:45:02 +0300
committerYonit Halperin <yhalperi@redhat.com>2012-08-27 09:13:03 +0300
commitef44c5eff9b25b990434db91a055ca9229f80593 (patch)
tree41fb2cb6a46e9e57b4cd6cb80879e4c711a127c5
parent15fe69e06b6840fe7416ae8c8a4afc81fea62c21 (diff)
downloadspice-ef44c5eff9b25b990434db91a055ca9229f80593.tar.gz
spice-ef44c5eff9b25b990434db91a055ca9229f80593.tar.xz
spice-ef44c5eff9b25b990434db91a055ca9229f80593.zip
spicevmc migration: send migration data
-rw-r--r--server/spicevmc.c60
1 files changed, 55 insertions, 5 deletions
diff --git a/server/spicevmc.c b/server/spicevmc.c
index a1092d26..b14ba639 100644
--- a/server/spicevmc.c
+++ b/server/spicevmc.c
@@ -31,6 +31,7 @@
#include "char_device.h"
#include "red_channel.h"
#include "reds.h"
+#include "migration_protocol.h"
/* todo: add flow control. i.e.,
* (a) limit the tokens available for the client
@@ -57,6 +58,11 @@ typedef struct SpiceVmcState {
SpiceCharDeviceWriteBuffer *recv_from_client_buf;
} SpiceVmcState;
+enum {
+ PIPE_ITEM_TYPE_SPICEVMC_DATA = PIPE_ITEM_TYPE_CHANNEL_BASE,
+ PIPE_ITEM_TYPE_SPICEVMC_MIGRATE_DATA,
+};
+
static SpiceVmcPipeItem *spicevmc_pipe_item_ref(SpiceVmcPipeItem *item)
{
item->refs++;
@@ -100,7 +106,7 @@ static SpiceCharDeviceMsgToClient *spicevmc_chardev_read_msg_from_dev(SpiceCharD
msg_item = spice_new0(SpiceVmcPipeItem, 1);
msg_item->refs = 1;
red_channel_pipe_item_init(&state->channel,
- &msg_item->base, 0);
+ &msg_item->base, PIPE_ITEM_TYPE_SPICEVMC_DATA);
} else {
spice_assert(state->pipe_item->buf_used == 0);
msg_item = state->pipe_item;
@@ -200,6 +206,12 @@ static void spicevmc_red_channel_client_on_disconnect(RedChannelClient *rcc)
}
}
+static int spicevmc_channel_client_handle_migrate_flush_mark(RedChannelClient *rcc)
+{
+ red_channel_client_pipe_add_type(rcc, PIPE_ITEM_TYPE_SPICEVMC_MIGRATE_DATA);
+ return TRUE;
+}
+
static int spicevmc_red_channel_client_handle_message(RedChannelClient *rcc,
uint16_t type,
uint32_t size,
@@ -261,21 +273,58 @@ static void spicevmc_red_channel_hold_pipe_item(RedChannelClient *rcc,
/* NOOP */
}
-static void spicevmc_red_channel_send_item(RedChannelClient *rcc,
- PipeItem *item)
+static void spicevmc_red_channel_send_data(RedChannelClient *rcc,
+ SpiceMarshaller *m,
+ PipeItem *item)
{
SpiceVmcPipeItem *i = SPICE_CONTAINEROF(item, SpiceVmcPipeItem, base);
- SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
red_channel_client_init_send_data(rcc, SPICE_MSG_SPICEVMC_DATA, item);
spice_marshaller_add_ref(m, i->buf, i->buf_used);
+}
+
+static void spicevmc_red_channel_send_migrate_data(RedChannelClient *rcc,
+ SpiceMarshaller *m,
+ PipeItem *item)
+{
+ SpiceVmcState *state;
+
+ state = SPICE_CONTAINEROF(rcc->channel, SpiceVmcState, channel);
+ red_channel_client_init_send_data(rcc, SPICE_MSG_MIGRATE_DATA, item);
+ spice_marshaller_add_uint32(m, SPICE_MIGRATE_DATA_SPICEVMC_MAGIC);
+ spice_marshaller_add_uint32(m, SPICE_MIGRATE_DATA_SPICEVMC_VERSION);
+
+ spice_char_device_state_migrate_data_marshall(state->chardev_st, m);
+}
+
+static void spicevmc_red_channel_send_item(RedChannelClient *rcc,
+ PipeItem *item)
+{
+ SpiceMarshaller *m = red_channel_client_get_marshaller(rcc);
+
+ switch (item->type) {
+ case PIPE_ITEM_TYPE_SPICEVMC_DATA:
+ spicevmc_red_channel_send_data(rcc, m, item);
+ break;
+ case PIPE_ITEM_TYPE_SPICEVMC_MIGRATE_DATA:
+ spicevmc_red_channel_send_migrate_data(rcc, m, item);
+ break;
+ default:
+ spice_error("bad pipe item %d", item->type);
+ free(item);
+ return;
+ }
red_channel_client_begin_send_message(rcc);
}
static void spicevmc_red_channel_release_pipe_item(RedChannelClient *rcc,
PipeItem *item, int item_pushed)
{
- spicevmc_pipe_item_unref((SpiceVmcPipeItem *)item);
+ if (item->type == PIPE_ITEM_TYPE_SPICEVMC_DATA) {
+ spicevmc_pipe_item_unref((SpiceVmcPipeItem *)item);
+ } else {
+ free(item);
+ }
}
static void spicevmc_connect(RedChannel *channel, RedClient *client,
@@ -333,6 +382,7 @@ SpiceCharDeviceState *spicevmc_device_connect(SpiceCharDeviceInstance *sin,
channel_cbs.release_item = spicevmc_red_channel_release_pipe_item;
channel_cbs.alloc_recv_buf = spicevmc_red_channel_alloc_msg_rcv_buf;
channel_cbs.release_recv_buf = spicevmc_red_channel_release_msg_rcv_buf;
+ channel_cbs.handle_migrate_flush_mark = spicevmc_channel_client_handle_migrate_flush_mark;
state = (SpiceVmcState*)red_channel_create(sizeof(SpiceVmcState),
core, channel_type, id[channel_type]++,