If reading/writing from the device have occured before migration data has arrived, the migration data might no longer be relvant, and we disconnect the client. --- server/char_device.c | 22 ++++++++++++++-------- server/char_device.h | 14 +++++++------- server/reds.c | 44 ++++++++++++++++++++++++++++++-------------- server/smartcard.c | 22 +++++++++++++++------- server/spicevmc.c | 8 ++++++-- 5 files changed, 72 insertions(+), 38 deletions(-) diff --git a/server/char_device.c b/server/char_device.c index b85a24d..ac2632d 100644 --- a/server/char_device.c +++ b/server/char_device.c @@ -681,20 +681,25 @@ void spice_char_device_state_destroy(SpiceCharDeviceState *char_dev) spice_char_device_state_unref(char_dev); } -void spice_char_device_client_add(SpiceCharDeviceState *dev, - RedClient *client, - int do_flow_control, - uint32_t max_send_queue_size, - uint32_t num_client_tokens, - uint32_t num_send_tokens, - int wait_for_migrate_data) +int spice_char_device_client_add(SpiceCharDeviceState *dev, + RedClient *client, + int do_flow_control, + uint32_t max_send_queue_size, + uint32_t num_client_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)); + if (wait_for_migrate_data && (dev->num_clients > 0 || dev->active)) { + spice_warning("can't restore device %p from migration data. The device " + "has already been active", dev); + return FALSE; + } + dev->wait_for_migrate_data = wait_for_migrate_data; spice_debug("dev_state %p client %p", dev, client); @@ -721,6 +726,7 @@ void spice_char_device_client_add(SpiceCharDeviceState *dev, dev->num_clients++; /* Now that we have a client, forward any pending device data */ spice_char_device_wakeup(dev); + return TRUE; } void spice_char_device_client_remove(SpiceCharDeviceState *dev, diff --git a/server/char_device.h b/server/char_device.h index 6688e91..d6d75e3 100644 --- a/server/char_device.h +++ b/server/char_device.h @@ -148,13 +148,13 @@ void spice_char_device_reset(SpiceCharDeviceState *dev); /* max_send_queue_size = how many messages we can read from the device and enqueue for this client, * when we have tokens for other clients and no tokens for this one */ -void spice_char_device_client_add(SpiceCharDeviceState *dev, - RedClient *client, - int do_flow_control, - uint32_t max_send_queue_size, - uint32_t num_client_tokens, - uint32_t num_send_tokens, - int wait_for_migrate_data); +int spice_char_device_client_add(SpiceCharDeviceState *dev, + RedClient *client, + int do_flow_control, + uint32_t max_send_queue_size, + uint32_t num_client_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 38e9298..4b3b1ee 100644 --- a/server/reds.c +++ b/server/reds.c @@ -1111,13 +1111,21 @@ void reds_on_main_agent_start(MainChannelClient *mcc, uint32_t num_tokens) * flow control, but will have no other problem. */ if (!spice_char_device_client_exists(dev_state, rcc->client)) { - spice_char_device_client_add(dev_state, - rcc->client, - TRUE, /* flow control */ - REDS_VDI_PORT_NUM_RECEIVE_BUFFS, - REDS_AGENT_WINDOW_SIZE, - num_tokens, - red_channel_client_waits_for_migrate_data(rcc)); + int client_added; + + client_added = spice_char_device_client_add(dev_state, + rcc->client, + TRUE, /* flow control */ + REDS_VDI_PORT_NUM_RECEIVE_BUFFS, + REDS_AGENT_WINDOW_SIZE, + num_tokens, + red_channel_client_waits_for_migrate_data(rcc)); + + if (!client_added) { + spice_warning("failed to add client to agent"); + reds_client_disconnect(rcc->client); + return; + } } else { spice_char_device_send_to_client_tokens_set(dev_state, rcc->client, @@ -3580,13 +3588,21 @@ static SpiceCharDeviceState *attach_to_red_agent(SpiceCharDeviceInstance *sin) } else { spice_debug("waiting for migration data"); if (!spice_char_device_client_exists(reds->agent_state.base, reds_get_client())) { - spice_char_device_client_add(reds->agent_state.base, - reds_get_client(), - TRUE, /* flow control */ - REDS_VDI_PORT_NUM_RECEIVE_BUFFS, - REDS_AGENT_WINDOW_SIZE, - ~0, - TRUE); + int client_added; + + client_added = spice_char_device_client_add(reds->agent_state.base, + reds_get_client(), + TRUE, /* flow control */ + REDS_VDI_PORT_NUM_RECEIVE_BUFFS, + REDS_AGENT_WINDOW_SIZE, + ~0, + TRUE); + + if (!client_added) { + spice_warning("failed to add client to agent"); + reds_disconnect(); + } + } } return state->base; diff --git a/server/smartcard.c b/server/smartcard.c index 0ec8a13..7c3a070 100644 --- a/server/smartcard.c +++ b/server/smartcard.c @@ -339,17 +339,25 @@ static void smartcard_char_device_attach_client(SpiceCharDeviceInstance *char_de SmartCardChannelClient *scc) { SmartCardDeviceState *st = spice_char_device_state_opaque_get(char_device->st); + int client_added; spice_assert(!scc->smartcard_state && !st->scc); st->scc = scc; - spice_char_device_client_add(st->chardev_st, - scc->base.client, - FALSE, /* no flow control yet */ - 0, /* send queue size */ - ~0, - ~0, - red_channel_client_waits_for_migrate_data(&scc->base)); scc->smartcard_state = st; + client_added = spice_char_device_client_add(st->chardev_st, + scc->base.client, + FALSE, /* no flow control yet */ + 0, /* send queue size */ + ~0, + ~0, + red_channel_client_waits_for_migrate_data( + &scc->base)); + if (!client_added) { + spice_warning("failed"); + st->scc = NULL; + scc->smartcard_state = NULL; + red_channel_client_disconnect(&scc->base); + } } static void smartcard_char_device_notify_reader_remove(SmartCardDeviceState *st) diff --git a/server/spicevmc.c b/server/spicevmc.c index 1ce3169..b6eaa08 100644 --- a/server/spicevmc.c +++ b/server/spicevmc.c @@ -384,8 +384,12 @@ 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, - red_channel_client_waits_for_migrate_data(rcc)); + if (!spice_char_device_client_add(state->chardev_st, client, FALSE, 0, ~0, ~0, + red_channel_client_waits_for_migrate_data(rcc))) { + spice_warning("failed to add client to spicevmc"); + red_channel_client_disconnect(rcc); + return; + } if (sif->state) { sif->state(sin, 1); -- 1.7.7.6 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel