summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorYonit Halperin <yhalperi@redhat.com>2012-08-02 22:55:53 +0300
committerYonit Halperin <yhalperi@redhat.com>2012-08-27 09:13:02 +0300
commitcb767a83fda2b93b47de284719353b3d073120be (patch)
tree9c65e48564607ac96ba0253f718f613156f67f27 /server
parentb0264a5e37b308c8a5b268974aa9936014a9389f (diff)
char device migration: don't read or write from/to the device while waiting for migraion data
Diffstat (limited to 'server')
-rw-r--r--server/char_device.c24
-rw-r--r--server/char_device.h3
-rw-r--r--server/reds.c13
-rw-r--r--server/smartcard.c3
-rw-r--r--server/spicevmc.c3
5 files changed, 32 insertions, 14 deletions
diff --git a/server/char_device.c b/server/char_device.c
index 84121e6d..d97c6dda 100644
--- a/server/char_device.c
+++ b/server/char_device.c
@@ -45,6 +45,8 @@ struct SpiceCharDeviceClientState {
struct SpiceCharDeviceState {
int running;
+ int active; /* has read/write been performed since the device was started */
+ int wait_for_migrate_data;
uint32_t refs;
Ring write_queue;
@@ -268,7 +270,7 @@ static int spice_char_device_read_from_device(SpiceCharDeviceState *dev)
uint64_t max_send_tokens;
int did_read = FALSE;
- if (!dev->running) {
+ if (!dev->running || dev->wait_for_migrate_data) {
return FALSE;
}
@@ -307,6 +309,7 @@ static int spice_char_device_read_from_device(SpiceCharDeviceState *dev)
}
dev->during_read_from_device = 0;
spice_char_device_state_unref(dev);
+ dev->active = dev->active || did_read;
return did_read;
}
@@ -415,7 +418,7 @@ static int spice_char_device_write_to_device(SpiceCharDeviceState *dev)
int total = 0;
int n;
- if (!dev->running) {
+ if (!dev->running || dev->wait_for_migrate_data) {
return 0;
}
@@ -462,6 +465,7 @@ static int spice_char_device_write_to_device(SpiceCharDeviceState *dev)
spice_assert(ring_is_empty(&dev->write_queue));
}
spice_char_device_state_unref(dev);
+ dev->active = dev->active || total;
return total;
}
@@ -682,13 +686,17 @@ void spice_char_device_client_add(SpiceCharDeviceState *dev,
int do_flow_control,
uint32_t max_send_queue_size,
uint32_t num_client_tokens,
- uint32_t num_send_tokens)
+ uint32_t num_send_tokens,
+ int wait_for_migrate_data)
{
SpiceCharDeviceClientState *dev_client;
spice_assert(dev);
spice_assert(client);
+ spice_assert(!wait_for_migrate_data || (dev->num_clients == 0 && !dev->active));
+ dev->wait_for_migrate_data = wait_for_migrate_data;
+
spice_debug("dev_state %p client %p", dev, client);
dev_client = spice_new0(SpiceCharDeviceClientState, 1);
dev_client->dev = dev;
@@ -727,8 +735,12 @@ void spice_char_device_client_remove(SpiceCharDeviceState *dev,
spice_error("client wasn't found");
return;
}
-
spice_char_device_client_free(dev, dev_client);
+ if (dev->wait_for_migrate_data) {
+ spice_assert(dev->num_clients == 0);
+ dev->wait_for_migrate_data = FALSE;
+ spice_char_device_read_from_device(dev);
+ }
}
int spice_char_device_client_exists(SpiceCharDeviceState *dev,
@@ -751,14 +763,16 @@ void spice_char_device_stop(SpiceCharDeviceState *dev)
{
spice_debug("dev_state %p", dev);
dev->running = FALSE;
+ dev->active = FALSE;
core->timer_cancel(dev->write_to_dev_timer);
}
void spice_char_device_reset(SpiceCharDeviceState *dev)
{
RingItem *client_item;
- spice_char_device_stop(dev);
+ spice_char_device_stop(dev);
+ dev->wait_for_migrate_data = FALSE;
spice_debug("dev_state %p", dev);
while (!ring_is_empty(&dev->write_queue)) {
RingItem *item = ring_get_tail(&dev->write_queue);
diff --git a/server/char_device.h b/server/char_device.h
index 186b1f1e..f3278e3d 100644
--- a/server/char_device.h
+++ b/server/char_device.h
@@ -150,7 +150,8 @@ void spice_char_device_client_add(SpiceCharDeviceState *dev,
int do_flow_control,
uint32_t max_send_queue_size,
uint32_t num_client_tokens,
- uint32_t num_send_tokens);
+ uint32_t num_send_tokens,
+ int wait_for_migrate_data);
void spice_char_device_client_remove(SpiceCharDeviceState *dev,
RedClient *client);
diff --git a/server/reds.c b/server/reds.c
index dc44de5f..a5a5a75a 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -1090,13 +1090,13 @@ void reds_fill_channels(SpiceMsgChannels *channels_info)
void reds_on_main_agent_start(MainChannelClient *mcc, uint32_t num_tokens)
{
SpiceCharDeviceState *dev_state = reds->agent_state.base;
- RedClient *client;
+ RedChannelClient *rcc;
if (!vdagent) {
return;
}
spice_assert(vdagent->st && vdagent->st == dev_state);
- client = main_channel_client_get_base(mcc)->client;
+ rcc = main_channel_client_get_base(mcc);
/*
* Note that in older releases, send_tokens were set to ~0 on both client
* and server. The server ignored the client given tokens.
@@ -1104,16 +1104,17 @@ void reds_on_main_agent_start(MainChannelClient *mcc, uint32_t num_tokens)
* and vice versa, the sending from the server to the client won't have
* flow control, but will have no other problem.
*/
- if (!spice_char_device_client_exists(dev_state, client)) {
+ if (!spice_char_device_client_exists(dev_state, rcc->client)) {
spice_char_device_client_add(dev_state,
- client,
+ rcc->client,
TRUE, /* flow control */
REDS_VDI_PORT_NUM_RECEIVE_BUFFS,
REDS_AGENT_WINDOW_SIZE,
- num_tokens);
+ num_tokens,
+ red_channel_client_waits_for_migrate_data(rcc));
} else {
spice_char_device_send_to_client_tokens_set(dev_state,
- client,
+ rcc->client,
num_tokens);
}
reds->agent_state.write_filter.discard_all = FALSE;
diff --git a/server/smartcard.c b/server/smartcard.c
index 2ed0bde8..de86185d 100644
--- a/server/smartcard.c
+++ b/server/smartcard.c
@@ -326,7 +326,8 @@ static void smartcard_char_device_attach(SpiceCharDeviceInstance *char_device,
FALSE, /* no flow control yet */
0, /* send queue size */
~0,
- ~0);
+ ~0,
+ red_channel_client_waits_for_migrate_data(&scc->base));
scc->smartcard_state = st;
write_buf = spice_char_device_write_buffer_get(st->chardev_st, NULL, sizeof(vheader));
if (!write_buf) {
diff --git a/server/spicevmc.c b/server/spicevmc.c
index 36d901f5..8bc23fda 100644
--- a/server/spicevmc.c
+++ b/server/spicevmc.c
@@ -309,7 +309,8 @@ static void spicevmc_connect(RedChannel *channel, RedClient *client,
state->rcc = rcc;
red_channel_client_ack_zero_messages_window(rcc);
- spice_char_device_client_add(state->chardev_st, client, FALSE, 0, ~0, ~0);
+ spice_char_device_client_add(state->chardev_st, client, FALSE, 0, ~0, ~0,
+ red_channel_client_waits_for_migrate_data(rcc));
if (sif->state) {
sif->state(sin, 1);