mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2026-01-09 05:51:00 +00:00
char device migration: don't read or write from/to the device while waiting for migraion data
This commit is contained in:
parent
b0264a5e37
commit
cb767a83fd
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user