}
custom_param("extra_guest_irqs", parse_extra_guest_irqs);
+/*
+ * 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.
+ */
+static void _domain_destroy(struct domain *d)
+{
+ BUG_ON(!d->is_dying);
+ BUG_ON(atomic_read(&d->refcnt) != DOMAIN_DESTROYED);
+
+ xfree(d->pbuf);
+
+ free_cpumask_var(d->dirty_cpumask);
+
+ free_domain_struct(d);
+}
+
struct domain *domain_create(domid_t domid,
struct xen_domctl_createdomain *config,
bool is_priv)
if ( hardware_domain == d )
hardware_domain = old_hwdom;
atomic_set(&d->refcnt, DOMAIN_DESTROYED);
- xfree(d->pbuf);
sched_destroy_domain(d);
watchdog_domain_destroy(d);
if ( init_status & INIT_xsm )
xsm_free_security_domain(d);
- free_cpumask_var(d->dirty_cpumask);
- free_domain_struct(d);
+
+ _domain_destroy(d);
+
return ERR_PTR(err);
}
xfree(d->vm_event_share);
#endif
- xfree(d->pbuf);
-
for ( i = d->max_vcpus - 1; i >= 0; i-- )
if ( (v = d->vcpu[i]) != NULL )
{
radix_tree_destroy(&d->pirq_tree, free_pirq_struct);
xsm_free_security_domain(d);
- free_cpumask_var(d->dirty_cpumask);
xfree(d->vcpu);
- free_domain_struct(d);
+
+ _domain_destroy(d);
send_global_virq(VIRQ_DOM_EXC);
}