ia64/xen-unstable

changeset 15825:bd59dd48e208

Make XEN_DOMCTL_destroydomain hypercall preemptible, in a way that is
visible to the caller (via -EAGAIN return code).

This prevents softlockup in dom0 kernel, due to the hypercall taking
too long to execute on very large (multi-multi-gigabyte) domains.

Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Fri Aug 31 15:44:38 2007 +0100 (2007-08-31)
parents ca0938180509
children 7e79e7f01f3d
files xen/arch/ia64/xen/domain.c xen/arch/powerpc/domain.c xen/arch/x86/domain.c xen/common/domain.c xen/common/domctl.c xen/include/asm-ia64/domain.h xen/include/xen/domain.h xen/include/xen/sched.h
line diff
     1.1 --- a/xen/arch/ia64/xen/domain.c	Fri Aug 31 15:43:28 2007 +0100
     1.2 +++ b/xen/arch/ia64/xen/domain.c	Fri Aug 31 15:44:38 2007 +0100
     1.3 @@ -936,7 +936,7 @@ static void relinquish_memory(struct dom
     1.4      spin_unlock_recursive(&d->page_alloc_lock);
     1.5  }
     1.6  
     1.7 -void domain_relinquish_resources(struct domain *d)
     1.8 +int domain_relinquish_resources(struct domain *d)
     1.9  {
    1.10      /* Relinquish guest resources for VT-i domain. */
    1.11      if (d->vcpu[0] && VMX_DOMAIN(d->vcpu[0]))
    1.12 @@ -954,6 +954,8 @@ void domain_relinquish_resources(struct 
    1.13  
    1.14      /* Free page used by xen oprofile buffer */
    1.15      free_xenoprof_pages(d);
    1.16 +
    1.17 +    return 0;
    1.18  }
    1.19  
    1.20  unsigned long
     2.1 --- a/xen/arch/powerpc/domain.c	Fri Aug 31 15:43:28 2007 +0100
     2.2 +++ b/xen/arch/powerpc/domain.c	Fri Aug 31 15:44:38 2007 +0100
     2.3 @@ -313,13 +313,13 @@ static void relinquish_memory(struct dom
     2.4      spin_unlock_recursive(&d->page_alloc_lock);
     2.5  }
     2.6  
     2.7 -void domain_relinquish_resources(struct domain *d)
     2.8 +int domain_relinquish_resources(struct domain *d)
     2.9  {
    2.10      relinquish_memory(d, &d->xenpage_list);
    2.11      relinquish_memory(d, &d->page_list);
    2.12      xfree(d->arch.foreign_mfns);
    2.13      xfree(d->arch.p2m);
    2.14 -    return;
    2.15 +    return 0;
    2.16  }
    2.17  
    2.18  void arch_dump_domain_info(struct domain *d)
     3.1 --- a/xen/arch/x86/domain.c	Fri Aug 31 15:43:28 2007 +0100
     3.2 +++ b/xen/arch/x86/domain.c	Fri Aug 31 15:44:38 2007 +0100
     3.3 @@ -1717,7 +1717,7 @@ static void vcpu_destroy_pagetables(stru
     3.4      v->arch.cr3 = 0;
     3.5  }
     3.6  
     3.7 -void domain_relinquish_resources(struct domain *d)
     3.8 +int domain_relinquish_resources(struct domain *d)
     3.9  {
    3.10      struct vcpu *v;
    3.11  
    3.12 @@ -1754,6 +1754,8 @@ void domain_relinquish_resources(struct 
    3.13  
    3.14      if ( is_hvm_domain(d) )
    3.15          hvm_domain_relinquish_resources(d);
    3.16 +
    3.17 +    return 0;
    3.18  }
    3.19  
    3.20  void arch_dump_domain_info(struct domain *d)
     4.1 --- a/xen/common/domain.c	Fri Aug 31 15:43:28 2007 +0100
     4.2 +++ b/xen/common/domain.c	Fri Aug 31 15:44:38 2007 +0100
     4.3 @@ -245,7 +245,7 @@ struct domain *domain_create(
     4.4      return d;
     4.5  
     4.6   fail:
     4.7 -    d->is_dying = 1;
     4.8 +    d->is_dying = DOMDYING_dead;
     4.9      atomic_set(&d->refcnt, DOMAIN_DESTROYED);
    4.10      if ( init_status & INIT_arch )
    4.11          arch_domain_destroy(d);
    4.12 @@ -303,26 +303,37 @@ struct domain *rcu_lock_domain_by_id(dom
    4.13  }
    4.14  
    4.15  
    4.16 -void domain_kill(struct domain *d)
    4.17 +int domain_kill(struct domain *d)
    4.18  {
    4.19 -    domain_pause(d);
    4.20 +    int rc = 0;
    4.21  
    4.22 -    /* Already dying? Then bail. */
    4.23 -    if ( test_and_set_bool(d->is_dying) )
    4.24 +    if ( d == current->domain )
    4.25 +        return -EINVAL;
    4.26 +
    4.27 +    /* Protected by domctl_lock. */
    4.28 +    switch ( d->is_dying )
    4.29      {
    4.30 -        domain_unpause(d);
    4.31 -        return;
    4.32 +    case DOMDYING_alive:
    4.33 +        domain_pause(d);
    4.34 +        d->is_dying = DOMDYING_dying;
    4.35 +        evtchn_destroy(d);
    4.36 +        gnttab_release_mappings(d);
    4.37 +    case DOMDYING_dying:
    4.38 +        rc = domain_relinquish_resources(d);
    4.39 +        page_scrub_kick();
    4.40 +        if ( rc != 0 )
    4.41 +        {
    4.42 +            BUG_ON(rc != -EAGAIN);
    4.43 +            break;
    4.44 +        }
    4.45 +        d->is_dying = DOMDYING_dead;
    4.46 +        put_domain(d);
    4.47 +        send_guest_global_virq(dom0, VIRQ_DOM_EXC);
    4.48 +    case DOMDYING_dead:
    4.49 +        break;
    4.50      }
    4.51  
    4.52 -    evtchn_destroy(d);
    4.53 -    gnttab_release_mappings(d);
    4.54 -    domain_relinquish_resources(d);
    4.55 -    put_domain(d);
    4.56 -
    4.57 -    /* Kick page scrubbing after domain_relinquish_resources(). */
    4.58 -    page_scrub_kick();
    4.59 -
    4.60 -    send_guest_global_virq(dom0, VIRQ_DOM_EXC);
    4.61 +    return rc;
    4.62  }
    4.63  
    4.64  
     5.1 --- a/xen/common/domctl.c	Fri Aug 31 15:43:28 2007 +0100
     5.2 +++ b/xen/common/domctl.c	Fri Aug 31 15:44:38 2007 +0100
     5.3 @@ -114,10 +114,10 @@ void getdomaininfo(struct domain *d, str
     5.4      info->cpu_time = cpu_time;
     5.5  
     5.6      info->flags = flags |
     5.7 -        (d->is_dying                ? XEN_DOMINF_dying    : 0) |
     5.8 -        (d->is_shut_down            ? XEN_DOMINF_shutdown : 0) |
     5.9 -        (d->is_paused_by_controller ? XEN_DOMINF_paused   : 0) |
    5.10 -        (d->debugger_attached       ? XEN_DOMINF_debugged : 0) |
    5.11 +        ((d->is_dying == DOMDYING_dead) ? XEN_DOMINF_dying    : 0) |
    5.12 +        (d->is_shut_down                ? XEN_DOMINF_shutdown : 0) |
    5.13 +        (d->is_paused_by_controller     ? XEN_DOMINF_paused   : 0) |
    5.14 +        (d->debugger_attached           ? XEN_DOMINF_debugged : 0) |
    5.15          d->shutdown_code << XEN_DOMINF_shutdownshift;
    5.16  
    5.17      if ( is_hvm_domain(d) )
    5.18 @@ -422,18 +422,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
    5.19          ret = -ESRCH;
    5.20          if ( d != NULL )
    5.21          {
    5.22 -            ret = xsm_destroydomain(d);
    5.23 -            if ( ret )
    5.24 -                goto destroydomain_out;
    5.25 -
    5.26 -            ret = -EINVAL;
    5.27 -            if ( d != current->domain )
    5.28 -            {
    5.29 -                domain_kill(d);
    5.30 -                ret = 0;
    5.31 -            }
    5.32 -
    5.33 -        destroydomain_out:
    5.34 +            ret = xsm_destroydomain(d) ? : domain_kill(d);
    5.35              rcu_unlock_domain(d);
    5.36          }
    5.37      }
     6.1 --- a/xen/include/asm-ia64/domain.h	Fri Aug 31 15:43:28 2007 +0100
     6.2 +++ b/xen/include/asm-ia64/domain.h	Fri Aug 31 15:44:38 2007 +0100
     6.3 @@ -18,7 +18,6 @@ struct p2m_entry;
     6.4  struct tlb_track;
     6.5  #endif
     6.6  
     6.7 -extern void domain_relinquish_resources(struct domain *);
     6.8  struct vcpu;
     6.9  extern void relinquish_vcpu_resources(struct vcpu *v);
    6.10  extern void vcpu_share_privregs_with_guest(struct vcpu *v);
     7.1 --- a/xen/include/xen/domain.h	Fri Aug 31 15:43:28 2007 +0100
     7.2 +++ b/xen/include/xen/domain.h	Fri Aug 31 15:44:38 2007 +0100
     7.3 @@ -45,7 +45,7 @@ void arch_domain_destroy(struct domain *
     7.4  int arch_set_info_guest(struct vcpu *, vcpu_guest_context_u);
     7.5  void arch_get_info_guest(struct vcpu *, vcpu_guest_context_u);
     7.6  
     7.7 -void domain_relinquish_resources(struct domain *d);
     7.8 +int domain_relinquish_resources(struct domain *d);
     7.9  
    7.10  void dump_pageframe_info(struct domain *d);
    7.11  
     8.1 --- a/xen/include/xen/sched.h	Fri Aug 31 15:43:28 2007 +0100
     8.2 +++ b/xen/include/xen/sched.h	Fri Aug 31 15:44:38 2007 +0100
     8.3 @@ -194,7 +194,7 @@ struct domain
     8.4      /* Are any VCPUs polling event channels (SCHEDOP_poll)? */
     8.5      bool_t           is_polling;
     8.6      /* Is this guest dying (i.e., a zombie)? */
     8.7 -    bool_t           is_dying;
     8.8 +    enum { DOMDYING_alive, DOMDYING_dying, DOMDYING_dead } is_dying;
     8.9      /* Domain is paused by controller software? */
    8.10      bool_t           is_paused_by_controller;
    8.11  
    8.12 @@ -338,7 +338,7 @@ static inline struct domain *rcu_lock_cu
    8.13  
    8.14  struct domain *get_domain_by_id(domid_t dom);
    8.15  void domain_destroy(struct domain *d);
    8.16 -void domain_kill(struct domain *d);
    8.17 +int domain_kill(struct domain *d);
    8.18  void domain_shutdown(struct domain *d, u8 reason);
    8.19  void domain_resume(struct domain *d);
    8.20  void domain_pause_for_debugger(void);