[Spice-devel] [spice-server PATCH 1/2] display seamless migration: don't process both cmd ring and dispatcher queue till migration data is received

Yonit Halperin yhalperi at redhat.com
Wed Nov 7 08:14:50 PST 2012


Hi,

On 11/07/2012 10:25 AM, Uri Lublin wrote:
> On 11/05/2012 11:33 PM, Yonit Halperin wrote:
>> fix: rhbz#866929
>>
>> At migration destination side, we need to restore the client's surfaces
>> state, before sending surfaces related messages.
>> Before this patch, we stopped the processing of only the cmd ring,
>> till migration data
>> arrived.
>> However, some QXL_IOs require reading and rendering the cmd ring (e.g.,
>> update_area). Moreover, when the device is reset, after destroying all
>> surfaces, we assert (in qemu) if the cmd ring is not empty (see
>> rhbz#866929).
>> This fix makes the red_worker thread wait till the migration data arrives
>> (or till a timeout), and not process any input from the device after the
>> vm is started.
>
> Hi Yonit,
>
> This patch makes sense to me.
>
> While red_worker is waiting, potentially, the qxl device (qemu-kvm)
> continues to add
> requests to the worker queue. Hopefully it will not fill it.
>
> See 2 minor comments/questions below.
>
>> ---
>>   server/red_worker.c |   45
>> +++++++++++++++++++++++++++++++++++++--------
>>   1 files changed, 37 insertions(+), 8 deletions(-)
>>
>> diff --git a/server/red_worker.c b/server/red_worker.c
>> index 9edd5d4..dd27872 100644
>> --- a/server/red_worker.c
>> +++ b/server/red_worker.c
>> @@ -102,6 +102,7 @@
>>   #define CHANNEL_PUSH_SLEEP_DURATION 10000 //micro
>>
>>   #define DISPLAY_CLIENT_TIMEOUT 15000000000ULL //nano
>> +#define DISPLAY_CLIENT_MIGRATE_DATA_TIMEOUT 10000000000ULL //nano
> Nitpick, maybe, to make it clear, add after // nano --  10 seconds
ok

>
>>   #define DISPLAY_CLIENT_RETRY_INTERVAL 10000 //micro
>>
>>   #define DISPLAY_FREE_LIST_DEFAULT_SIZE 128
>> @@ -4892,13 +4893,7 @@ static int red_process_commands(RedWorker
>> *worker, uint32_t max_pipe_size, int *
>>       int n = 0;
>>       uint64_t start = red_now();
>>
>> -    /* we don't process the command ring if we are at the migration
>> target and we
>> -     * are expecting migration data. The migration data includes the
>> list
>> -     * of surfaces that are held by the client. We need to have it
>> before
>> -     * processing commands in order not to render and send surfaces
>> unnecessarily
>> -     */
>> -    if (!worker->running || (worker->display_channel&&
>> -
>> red_channel_waits_for_migrate_data(&worker->display_channel->common.base)))
>> {
>> +    if (!worker->running) {
>>           *ring_is_empty = TRUE;
>>           return n;
>>       }
>> @@ -11162,18 +11157,52 @@ void handle_dev_stop(void *opaque, void
>> *payload)
>>       red_wait_outgoing_items(&worker->cursor_channel->common.base);
>>   }
>>
>> +static int display_channel_wait_for_migrate_data(DisplayChannel
>> *display)
>> +{
>> +    uint64_t end_time = red_now() + DISPLAY_CLIENT_MIGRATE_DATA_TIMEOUT;
>> +    RedChannel *channel =&display->common.base;
>> +    RedChannelClient *rcc;
>> +
>> +    spice_debug(NULL);
>> +    spice_assert(channel->clients_num == 1);
>> +
>> +    rcc = SPICE_CONTAINEROF(ring_get_head(&channel->clients),
>> RedChannelClient, channel_link);
>> +    spice_assert(red_channel_client_waits_for_migrate_data(rcc));
>> +
>> +    for (;;) {
>> +        red_channel_client_receive(rcc);
>> +        if (!red_channel_client_is_connected(rcc)) {
>> +            break;
>> +        }
>> +
>> +        if (!red_channel_client_waits_for_migrate_data(rcc)) {
>> +            return TRUE;
>> +        }
>> +        if (red_now()>  end_time) {
>> +            spice_warning("timeout");
>> +            red_channel_client_disconnect(rcc);
>> +            break;
>> +        }
>> +        usleep(DISPLAY_CLIENT_RETRY_INTERVAL);
>> +    }
>> +    return FALSE;
>> +}
>> +
>>   void handle_dev_start(void *opaque, void *payload)
>>   {
>>       RedWorker *worker = opaque;
>>
>>       spice_assert(!worker->running);
>> +    worker->running = TRUE;
>
> Why does worker->running have to be set before the waiting ?
You are right, it is not necessary.

Thanks,
Yonit.
>
>>       if (worker->cursor_channel) {
>>           worker->cursor_channel->common.during_target_migrate = FALSE;
>>       }
>>       if (worker->display_channel) {
>>           worker->display_channel->common.during_target_migrate = FALSE;
>> +        if
>> (red_channel_waits_for_migrate_data(&worker->display_channel->common.base))
>> {
>> +
>> display_channel_wait_for_migrate_data(worker->display_channel);
>> +        }
>>       }
>> -    worker->running = TRUE;
>>       guest_set_client_capabilities(worker);
>>   }
>>
>



More information about the Spice-devel mailing list