[Spice-devel] [PATCH spice] server: do not fail to read all agent data when called recursively

Alon Levy alevy at redhat.com
Thu Oct 14 04:47:33 PDT 2010


ACK.

----- "Hans de Goede" <hdegoede at redhat.com> wrote:

> We can loose (not handle) a virtio port write from the guest:
> 
> - server/reds.c: vdagent_char_device_wakeup get called
>   by hw/spice-vmc.c because data has arrived from the guest,
> - hw/spice-vmc.c: vmc_read get calls
> - If the vmc_read call depletes the current buffer it calls
>   virtio_serial_throttle_port(&svc->port, false)
> - This causes vmc_have_data to get called, which if in the
>   mean time another buffer has arrived causes
>   vdagent_char_device_wakeup to gets called again
>   (so recursively)
> - vdagent_char_device_wakeup is protected against recursive
>   calling and ignores the second call (a nasty hack)
> - if no other data arrives, the arrived data will not get read
> 
> Together with another nasty hack in the linux guest virtio_console
> driver, where it waits for a write to be acked by the host before
> continuing with the next one, this can lead to the guest
> getting stuck / hang (until the write is read by the spice-server
> which never happens becaus of the above issues).
> ---
>  server/reds.c |   23 ++++++++++++++---------
>  1 files changed, 14 insertions(+), 9 deletions(-)
> 
> diff --git a/server/reds.c b/server/reds.c
> index a88ca95..f4dfa46 100644
> --- a/server/reds.c
> +++ b/server/reds.c
> @@ -1231,21 +1231,14 @@ static void dispatch_vdi_port_data(int port,
> VDIReadBuf *buf)
>  
>  static int read_from_vdi_port(void)
>  {
> -    // FIXME: UGLY HACK. Result of spice-vmc vmc_read triggering
> flush of throttled data, and recalling this.
> -    static int inside_call = 0;
>      int quit_loop = 0;
>      VDIPortState *state = &reds->agent_state;
>      SpiceCharDeviceInterface *sif;
>      VDIReadBuf *dispatch_buf;
>      int total = 0;
>      int n;
> -    if (inside_call) {
> -        return 0;
> -    }
> -    inside_call = 1;
>  
>      if (!reds->agent_state.connected || reds->mig_target) {
> -        inside_call = 0;
>          return 0;
>      }
>  
> @@ -1314,13 +1307,25 @@ static int read_from_vdi_port(void)
>              dispatch_vdi_port_data(state->vdi_chunk_header.port,
> dispatch_buf);
>          }
>      }
> -    inside_call = 0;
>      return total;
>  }
>  
>  void vdagent_char_device_wakeup(SpiceCharDeviceInstance *sin)
>  {
> -    while (read_from_vdi_port());
> +    static int vdagent_char_device_wakeups = 0;
> +
> +    vdagent_char_device_wakeups++;
> +
> +    if (vdagent_char_device_wakeups != 1) {
> +        /* When spice-vmc vmc_read triggers flush of throttled data,
> we may get
> +           recalled and we may not call read_from_vdi_port()
> recursively */
> +        return;
> +    }
> +
> +    while (vdagent_char_device_wakeups) {
> +        while (read_from_vdi_port()) {}
> +        vdagent_char_device_wakeups--;
> +    }
>  }
>  
>  static void reds_handle_agent_mouse_event()
> -- 
> 1.7.3.1
> 
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel


More information about the Spice-devel mailing list