[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 2/3] xen/domain: Introduce domain_teardown()
There is no common equivelent of domain_reliquish_resources(), which has caused various pieces of common cleanup to live in inappropriate places. Perhaps most obviously, evtchn_destroy() is called for every continuation of domain_reliquish_resources(), which can easily be thousands of times. Create domain_teardown() to be a new top level facility, and call it from the appropriate positions in domain_kill() and domain_create()'s error path. No change in behaviour yet. Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> --- CC: Jan Beulich <JBeulich@xxxxxxxx> CC: Roger Pau Monné <roger.pau@xxxxxxxxxx> CC: Wei Liu <wl@xxxxxxx> CC: Stefano Stabellini <sstabellini@xxxxxxxxxx> CC: Julien Grall <julien@xxxxxxx> CC: Volodymyr Babchuk <Volodymyr_Babchuk@xxxxxxxx> --- xen/common/domain.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ xen/include/xen/sched.h | 8 +++++++ 2 files changed, 67 insertions(+) diff --git a/xen/common/domain.c b/xen/common/domain.c index ce3667f1b4..ef1987335b 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -273,6 +273,59 @@ static int __init parse_extra_guest_irqs(const char *s) custom_param("extra_guest_irqs", parse_extra_guest_irqs); /* + * Release resources held by a domain. There may or may not be live + * references to the domain, and it may or may not be fully constructed. + * + * d->is_dying differing between DOMDYING_dying and DOMDYING_dead can be used + * to determine if live references to the domain exist, and also whether + * continuations are permitted. + * + * If d->is_dying is DOMDYING_dead, this must not return non-zero. + */ +static int domain_teardown(struct domain *d) +{ + BUG_ON(!d->is_dying); + + /* + * This hypercall can take minutes of wallclock time to complete. This + * logic implements a co-routine, stashing state in struct domain across + * hypercall continuation boundaries. + */ + switch ( d->teardown.val ) + { + /* + * Record the current progress. Subsequent hypercall continuations + * will logically restart work from this point. + * + * PROGRESS() markers must not be in the middle of loops. The loop + * variable isn't preserved across a continuation. + * + * To avoid redundant work, there should be a marker before each + * function which may return -ERESTART. + */ +#define PROGRESS(x) \ + d->teardown.val = PROG_ ## x; \ + /* Fallthrough */ \ + case PROG_ ## x + + enum { + PROG_done = 1, + }; + + case 0: + PROGRESS(done): + break; + +#undef PROGRESS + + default: + BUG(); + } + + return 0; +} + +/* * Destroy a domain once all references to it have been dropped. Used either * from the RCU path, or from the domain_create() error path before the domain * is inserted into the domlist. @@ -553,6 +606,9 @@ struct domain *domain_create(domid_t domid, if ( init_status & INIT_watchdog ) watchdog_domain_destroy(d); + /* Must not hit a continuation in this context. */ + ASSERT(domain_teardown(d) == 0); + _domain_destroy(d); return ERR_PTR(err); @@ -733,6 +789,9 @@ int domain_kill(struct domain *d) domain_set_outstanding_pages(d, 0); /* fallthrough */ case DOMDYING_dying: + rc = domain_teardown(d); + if ( rc ) + break; rc = evtchn_destroy(d); if ( rc ) break; diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index faf5fda36f..3f35c537b8 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -525,6 +525,14 @@ struct domain /* Argo interdomain communication support */ struct argo_domain *argo; #endif + + /* + * Continuation information for domain_teardown(). All fields entirely + * private. + */ + struct { + unsigned int val; + } teardown; }; static inline struct page_list_head *page_to_list( -- 2.11.0
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |