On Thu, Feb 9, 2017 at 10:11 AM, Razvan Cojocaru
<rcojoc...@bitdefender.com> wrote:
> It is currently possible for the guest to lock when subscribing
> to synchronous vm_events if max_vcpus is larger than the
> number of available ring buffer slots. This patch no longer
> blocks already paused VCPUs, fixing the issue for this use
> case, and wakes up as many blocked VCPUs as there are slots
> available in the ring buffer, eliminating the blockage for
> asynchronous events.
>
> Signed-off-by: Razvan Cojocaru <rcojoc...@bitdefender.com>

Acked-by: Tamas K Lengyel <ta...@tklengyel.com>

>
> ---
> Changes since V2:
>  - Fixed typo: re-enabled commented-out code (for testing).
> ---
>  xen/common/vm_event.c | 27 +++++++--------------------
>  1 file changed, 7 insertions(+), 20 deletions(-)
>
> diff --git a/xen/common/vm_event.c b/xen/common/vm_event.c
> index 82ce8f1..45046d1 100644
> --- a/xen/common/vm_event.c
> +++ b/xen/common/vm_event.c
> @@ -127,26 +127,11 @@ static unsigned int vm_event_ring_available(struct 
> vm_event_domain *ved)
>  static void vm_event_wake_blocked(struct domain *d, struct vm_event_domain 
> *ved)
>  {
>      struct vcpu *v;
> -    int online = d->max_vcpus;
>      unsigned int avail_req = vm_event_ring_available(ved);
>
>      if ( avail_req == 0 || ved->blocked == 0 )
>          return;
>
> -    /*
> -     * We ensure that we only have vCPUs online if there are enough free 
> slots
> -     * for their memory events to be processed.  This will ensure that no
> -     * memory events are lost (due to the fact that certain types of events
> -     * cannot be replayed, we need to ensure that there is space in the ring
> -     * for when they are hit).
> -     * See comment below in vm_event_put_request().
> -     */
> -    for_each_vcpu ( d, v )
> -        if ( test_bit(ved->pause_flag, &v->pause_flags) )
> -            online--;
> -
> -    ASSERT(online == (d->max_vcpus - ved->blocked));
> -
>      /* We remember which vcpu last woke up to avoid scanning always linearly
>       * from zero and starving higher-numbered vcpus under high load */
>      if ( d->vcpu )
> @@ -160,13 +145,13 @@ static void vm_event_wake_blocked(struct domain *d, 
> struct vm_event_domain *ved)
>              if ( !v )
>                  continue;
>
> -            if ( !(ved->blocked) || online >= avail_req )
> +            if ( !(ved->blocked) || avail_req == 0 )
>                 break;
>
>              if ( test_and_clear_bit(ved->pause_flag, &v->pause_flags) )
>              {
>                  vcpu_unpause(v);
> -                online++;
> +                avail_req--;
>                  ved->blocked--;
>                  ved->last_vcpu_wake_up = k;
>              }
> @@ -280,8 +265,9 @@ void vm_event_put_request(struct domain *d,
>      int free_req;
>      unsigned int avail_req;
>      RING_IDX req_prod;
> +    struct vcpu *curr = current;
>
> -    if ( current->domain != d )
> +    if ( curr->domain != d )
>      {
>          req->flags |= VM_EVENT_FLAG_FOREIGN;
>  #ifndef NDEBUG
> @@ -316,8 +302,9 @@ void vm_event_put_request(struct domain *d,
>       * See the comments above wake_blocked() for more information
>       * on how this mechanism works to avoid waiting. */
>      avail_req = vm_event_ring_available(ved);
> -    if( current->domain == d && avail_req < d->max_vcpus )
> -        vm_event_mark_and_pause(current, ved);
> +    if( curr->domain == d && avail_req < d->max_vcpus &&
> +        !atomic_read(&curr->vm_event_pause_count) )
> +        vm_event_mark_and_pause(curr, ved);
>
>      vm_event_ring_unlock(ved);
>
> --
> 1.9.1
>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> https://lists.xen.org/xen-devel

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

Reply via email to