Mailing List Archive

[xen-unstable] Make XEN_DOMCTL_destroydomain hypercall preemptible, in a way that is
# HG changeset patch
# User kfraser@localhost.localdomain
# Date 1188571478 -3600
# Node ID bd59dd48e2084c5b1ec9ae8c8dfde87690a5ef1b
# Parent ca093818050990ae9042272dc7ed5a3f205d2862
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>
---
xen/arch/ia64/xen/domain.c | 4 ++-
xen/arch/powerpc/domain.c | 4 +--
xen/arch/x86/domain.c | 4 ++-
xen/common/domain.c | 53 +++++++++++++++++++++++++-----------------
xen/common/domctl.c | 21 +++-------------
xen/include/asm-ia64/domain.h | 1
xen/include/xen/domain.h | 2 -
xen/include/xen/sched.h | 4 +--
8 files changed, 48 insertions(+), 45 deletions(-)

diff -r ca0938180509 -r bd59dd48e208 xen/arch/ia64/xen/domain.c
--- a/xen/arch/ia64/xen/domain.c Fri Aug 31 15:43:28 2007 +0100
+++ b/xen/arch/ia64/xen/domain.c Fri Aug 31 15:44:38 2007 +0100
@@ -936,7 +936,7 @@ static void relinquish_memory(struct dom
spin_unlock_recursive(&d->page_alloc_lock);
}

-void domain_relinquish_resources(struct domain *d)
+int domain_relinquish_resources(struct domain *d)
{
/* Relinquish guest resources for VT-i domain. */
if (d->vcpu[0] && VMX_DOMAIN(d->vcpu[0]))
@@ -954,6 +954,8 @@ void domain_relinquish_resources(struct

/* Free page used by xen oprofile buffer */
free_xenoprof_pages(d);
+
+ return 0;
}

unsigned long
diff -r ca0938180509 -r bd59dd48e208 xen/arch/powerpc/domain.c
--- a/xen/arch/powerpc/domain.c Fri Aug 31 15:43:28 2007 +0100
+++ b/xen/arch/powerpc/domain.c Fri Aug 31 15:44:38 2007 +0100
@@ -313,13 +313,13 @@ static void relinquish_memory(struct dom
spin_unlock_recursive(&d->page_alloc_lock);
}

-void domain_relinquish_resources(struct domain *d)
+int domain_relinquish_resources(struct domain *d)
{
relinquish_memory(d, &d->xenpage_list);
relinquish_memory(d, &d->page_list);
xfree(d->arch.foreign_mfns);
xfree(d->arch.p2m);
- return;
+ return 0;
}

void arch_dump_domain_info(struct domain *d)
diff -r ca0938180509 -r bd59dd48e208 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c Fri Aug 31 15:43:28 2007 +0100
+++ b/xen/arch/x86/domain.c Fri Aug 31 15:44:38 2007 +0100
@@ -1717,7 +1717,7 @@ static void vcpu_destroy_pagetables(stru
v->arch.cr3 = 0;
}

-void domain_relinquish_resources(struct domain *d)
+int domain_relinquish_resources(struct domain *d)
{
struct vcpu *v;

@@ -1754,6 +1754,8 @@ void domain_relinquish_resources(struct

if ( is_hvm_domain(d) )
hvm_domain_relinquish_resources(d);
+
+ return 0;
}

void arch_dump_domain_info(struct domain *d)
diff -r ca0938180509 -r bd59dd48e208 xen/common/domain.c
--- a/xen/common/domain.c Fri Aug 31 15:43:28 2007 +0100
+++ b/xen/common/domain.c Fri Aug 31 15:44:38 2007 +0100
@@ -245,7 +245,7 @@ struct domain *domain_create(
return d;

fail:
- d->is_dying = 1;
+ d->is_dying = DOMDYING_dead;
atomic_set(&d->refcnt, DOMAIN_DESTROYED);
if ( init_status & INIT_arch )
arch_domain_destroy(d);
@@ -303,26 +303,37 @@ struct domain *rcu_lock_domain_by_id(dom
}


-void domain_kill(struct domain *d)
-{
- domain_pause(d);
-
- /* Already dying? Then bail. */
- if ( test_and_set_bool(d->is_dying) )
- {
- domain_unpause(d);
- return;
- }
-
- evtchn_destroy(d);
- gnttab_release_mappings(d);
- domain_relinquish_resources(d);
- put_domain(d);
-
- /* Kick page scrubbing after domain_relinquish_resources(). */
- page_scrub_kick();
-
- send_guest_global_virq(dom0, VIRQ_DOM_EXC);
+int domain_kill(struct domain *d)
+{
+ int rc = 0;
+
+ if ( d == current->domain )
+ return -EINVAL;
+
+ /* Protected by domctl_lock. */
+ switch ( d->is_dying )
+ {
+ case DOMDYING_alive:
+ domain_pause(d);
+ d->is_dying = DOMDYING_dying;
+ evtchn_destroy(d);
+ gnttab_release_mappings(d);
+ case DOMDYING_dying:
+ rc = domain_relinquish_resources(d);
+ page_scrub_kick();
+ if ( rc != 0 )
+ {
+ BUG_ON(rc != -EAGAIN);
+ break;
+ }
+ d->is_dying = DOMDYING_dead;
+ put_domain(d);
+ send_guest_global_virq(dom0, VIRQ_DOM_EXC);
+ case DOMDYING_dead:
+ break;
+ }
+
+ return rc;
}


diff -r ca0938180509 -r bd59dd48e208 xen/common/domctl.c
--- a/xen/common/domctl.c Fri Aug 31 15:43:28 2007 +0100
+++ b/xen/common/domctl.c Fri Aug 31 15:44:38 2007 +0100
@@ -114,10 +114,10 @@ void getdomaininfo(struct domain *d, str
info->cpu_time = cpu_time;

info->flags = flags |
- (d->is_dying ? XEN_DOMINF_dying : 0) |
- (d->is_shut_down ? XEN_DOMINF_shutdown : 0) |
- (d->is_paused_by_controller ? XEN_DOMINF_paused : 0) |
- (d->debugger_attached ? XEN_DOMINF_debugged : 0) |
+ ((d->is_dying == DOMDYING_dead) ? XEN_DOMINF_dying : 0) |
+ (d->is_shut_down ? XEN_DOMINF_shutdown : 0) |
+ (d->is_paused_by_controller ? XEN_DOMINF_paused : 0) |
+ (d->debugger_attached ? XEN_DOMINF_debugged : 0) |
d->shutdown_code << XEN_DOMINF_shutdownshift;

if ( is_hvm_domain(d) )
@@ -422,18 +422,7 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc
ret = -ESRCH;
if ( d != NULL )
{
- ret = xsm_destroydomain(d);
- if ( ret )
- goto destroydomain_out;
-
- ret = -EINVAL;
- if ( d != current->domain )
- {
- domain_kill(d);
- ret = 0;
- }
-
- destroydomain_out:
+ ret = xsm_destroydomain(d) ? : domain_kill(d);
rcu_unlock_domain(d);
}
}
diff -r ca0938180509 -r bd59dd48e208 xen/include/asm-ia64/domain.h
--- a/xen/include/asm-ia64/domain.h Fri Aug 31 15:43:28 2007 +0100
+++ b/xen/include/asm-ia64/domain.h Fri Aug 31 15:44:38 2007 +0100
@@ -18,7 +18,6 @@ struct tlb_track;
struct tlb_track;
#endif

-extern void domain_relinquish_resources(struct domain *);
struct vcpu;
extern void relinquish_vcpu_resources(struct vcpu *v);
extern void vcpu_share_privregs_with_guest(struct vcpu *v);
diff -r ca0938180509 -r bd59dd48e208 xen/include/xen/domain.h
--- a/xen/include/xen/domain.h Fri Aug 31 15:43:28 2007 +0100
+++ b/xen/include/xen/domain.h Fri Aug 31 15:44:38 2007 +0100
@@ -45,7 +45,7 @@ int arch_set_info_guest(struct vcpu *, v
int arch_set_info_guest(struct vcpu *, vcpu_guest_context_u);
void arch_get_info_guest(struct vcpu *, vcpu_guest_context_u);

-void domain_relinquish_resources(struct domain *d);
+int domain_relinquish_resources(struct domain *d);

void dump_pageframe_info(struct domain *d);

diff -r ca0938180509 -r bd59dd48e208 xen/include/xen/sched.h
--- a/xen/include/xen/sched.h Fri Aug 31 15:43:28 2007 +0100
+++ b/xen/include/xen/sched.h Fri Aug 31 15:44:38 2007 +0100
@@ -194,7 +194,7 @@ struct domain
/* Are any VCPUs polling event channels (SCHEDOP_poll)? */
bool_t is_polling;
/* Is this guest dying (i.e., a zombie)? */
- bool_t is_dying;
+ enum { DOMDYING_alive, DOMDYING_dying, DOMDYING_dead } is_dying;
/* Domain is paused by controller software? */
bool_t is_paused_by_controller;

@@ -338,7 +338,7 @@ static inline struct domain *rcu_lock_cu

struct domain *get_domain_by_id(domid_t dom);
void domain_destroy(struct domain *d);
-void domain_kill(struct domain *d);
+int domain_kill(struct domain *d);
void domain_shutdown(struct domain *d, u8 reason);
void domain_resume(struct domain *d);
void domain_pause_for_debugger(void);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@lists.xensource.com
http://lists.xensource.com/xen-changelog