x86/mm: Make {hap, shadow}_teardown() preemptible

A domain with sufficient shadow allocation can cause a watchdog timeout
during domain destruction.  Expand the existing -EAGAIN logic in
paging_teardown() to allow {hap/sh}_set_allocation() to become
restartable during the DOMCTL_destroydomain hypercall.

Signed-off-by: Anshul Makkar <anshul.makkar@citrix.com>
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Tim Deegan <tim@xen.org>
Reviewed-by: George Dunlap <george.dunlap@eu.citrix.com>
master commit: 0174da5b79
master date: 2015-08-06 10:04:43 +0100
This commit is contained in:
Anshul Makkar authored and Jan Beulich committed 2015-09-10 15:55:23 +02:00
1 parent cfb5d20017
commit e19042ffbd
5 files changed
+25 -34

No files matched your search

+8 -14
View File
@@ -498,7 +498,7 @@ void hap_final_teardown(struct domain *d)
}
if ( d->arch.paging.hap.total_pages != 0 )
hap_teardown(d);
hap_teardown(d, NULL);
p2m_teardown(p2m_get_hostp2m(d));
/* Free any memory that the p2m teardown released */
@@ -508,7 +508,7 @@ void hap_final_teardown(struct domain *d)
paging_unlock(d);
}
void hap_teardown(struct domain *d)
void hap_teardown(struct domain *d, int *preempted)
{
struct vcpu *v;
mfn_t mfn;
@@ -536,18 +536,11 @@ void hap_teardown(struct domain *d)
if ( d->arch.paging.hap.total_pages != 0 )
{
HAP_PRINTK("teardown of domain %u starts."
" pages total = %u, free = %u, p2m=%u\n",
d->domain_id,
d->arch.paging.hap.total_pages,
d->arch.paging.hap.free_pages,
d->arch.paging.hap.p2m_pages);
hap_set_allocation(d, 0, NULL);
HAP_PRINTK("teardown done."
" pages total = %u, free = %u, p2m=%u\n",
d->arch.paging.hap.total_pages,
d->arch.paging.hap.free_pages,
d->arch.paging.hap.p2m_pages);
hap_set_allocation(d, 0, preempted);
if ( preempted && *preempted )
goto out;
ASSERT(d->arch.paging.hap.total_pages == 0);
}
@@ -556,6 +549,7 @@ void hap_teardown(struct domain *d)
xfree(d->arch.hvm_domain.dirty_vram);
d->arch.hvm_domain.dirty_vram = NULL;
out:
paging_unlock(d);
}
+6 -3
View File
@@ -777,12 +777,15 @@ long paging_domctl_continuation(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl)
/* Call when destroying a domain */
int paging_teardown(struct domain *d)
{
int rc;
int rc, preempted = 0;
if ( hap_enabled(d) )
hap_teardown(d);
hap_teardown(d, &preempted);
else
shadow_teardown(d);
shadow_teardown(d, &preempted);
if ( preempted )
return -EAGAIN;
/* clean up log dirty resources. */
rc = paging_free_log_dirty_bitmap(d, 0);
+9 -15
View File
@@ -3031,7 +3031,7 @@ int shadow_enable(struct domain *d, u32 mode)
return rv;
}
void shadow_teardown(struct domain *d)
void shadow_teardown(struct domain *d, int *preempted)
/* Destroy the shadow pagetables of this domain and free its shadow memory.
* Should only be called for dying domains. */
{
@@ -3092,23 +3092,16 @@ void shadow_teardown(struct domain *d)
if ( d->arch.paging.shadow.total_pages != 0 )
{
SHADOW_PRINTK("teardown of domain %u starts."
" Shadow pages total = %u, free = %u, p2m=%u\n",
d->domain_id,
d->arch.paging.shadow.total_pages,
d->arch.paging.shadow.free_pages,
d->arch.paging.shadow.p2m_pages);
/* Destroy all the shadows and release memory to domheap */
sh_set_allocation(d, 0, NULL);
sh_set_allocation(d, 0, preempted);
if ( preempted && *preempted )
goto out;
/* Release the hash table back to xenheap */
if (d->arch.paging.shadow.hash_table)
shadow_hash_teardown(d);
/* Should not have any more memory held */
SHADOW_PRINTK("teardown done."
" Shadow pages total = %u, free = %u, p2m=%u\n",
d->arch.paging.shadow.total_pages,
d->arch.paging.shadow.free_pages,
d->arch.paging.shadow.p2m_pages);
ASSERT(d->arch.paging.shadow.total_pages == 0);
}
@@ -3139,6 +3132,7 @@ void shadow_teardown(struct domain *d)
d->arch.hvm_domain.dirty_vram = NULL;
}
out:
paging_unlock(d);
/* Must be called outside the lock */
@@ -3160,7 +3154,7 @@ void shadow_final_teardown(struct domain *d)
* It is possible for a domain that never got domain_kill()ed
* to get here with its shadow allocation intact. */
if ( d->arch.paging.shadow.total_pages != 0 )
shadow_teardown(d);
shadow_teardown(d, NULL);
/* It is now safe to pull down the p2m map. */
p2m_teardown(p2m_get_hostp2m(d));
+1 -1
View File
@@ -54,7 +54,7 @@ int hap_domctl(struct domain *d, xen_domctl_shadow_op_t *sc,
XEN_GUEST_HANDLE_PARAM(void) u_domctl);
int hap_enable(struct domain *d, u32 mode);
void hap_final_teardown(struct domain *d);
void hap_teardown(struct domain *d);
void hap_teardown(struct domain *d, int *preempted);
void hap_vcpu_init(struct vcpu *v);
void hap_logdirty_init(struct domain *d);
int hap_track_dirty_vram(struct domain *d,
+1 -1
View File
@@ -76,7 +76,7 @@ int shadow_domctl(struct domain *d,
XEN_GUEST_HANDLE_PARAM(void) u_domctl);
/* Call when destroying a domain */
void shadow_teardown(struct domain *d);
void shadow_teardown(struct domain *d, int *preempted);
/* Call once all of the references to the domain have gone away */
void shadow_final_teardown(struct domain *d);
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.