# HG changeset patch
# User Tim Deegan <Tim.Deegan@xxxxxxxxxx>
# Date 1305302439 -3600
# Node ID 93e48d4ea41425022c1c82ce7a6de298cd355ab0
# Parent 72da3d3b68d68c9b5e834e9b707abf2e2c61bdc4
x86/mm/p2m: Fix locking discipline around log-dirty teardown.
It's not safe to call paging_free_log_dirty_page with the
log-dirty lock held.
Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxx>
diff -r 72da3d3b68d6 -r 93e48d4ea414 xen/arch/x86/mm/paging.c
--- a/xen/arch/x86/mm/paging.c Fri May 13 17:00:39 2011 +0100
+++ b/xen/arch/x86/mm/paging.c Fri May 13 17:00:39 2011 +0100
@@ -156,10 +156,16 @@ void paging_free_log_dirty_bitmap(struct
{
mfn_t *l4, *l3, *l2;
int i4, i3, i2;
+ struct page_list_head to_free;
+ struct page_info *pg, *tmp;
if ( !mfn_valid(d->arch.paging.log_dirty.top) )
return;
+ INIT_PAGE_LIST_HEAD(&to_free);
+
+ log_dirty_lock(d);
+
l4 = map_domain_page(mfn_x(d->arch.paging.log_dirty.top));
for ( i4 = 0; i4 < LOGDIRTY_NODE_ENTRIES; i4++ )
@@ -178,22 +184,28 @@ void paging_free_log_dirty_bitmap(struct
for ( i2 = 0; i2 < LOGDIRTY_NODE_ENTRIES; i2++ )
if ( mfn_valid(l2[i2]) )
- paging_free_log_dirty_page(d, l2[i2]);
+ page_list_add_tail(mfn_to_page(l2[i2]), &to_free);
unmap_domain_page(l2);
- paging_free_log_dirty_page(d, l3[i3]);
+ page_list_add_tail(mfn_to_page(l3[i3]), &to_free);
}
unmap_domain_page(l3);
- paging_free_log_dirty_page(d, l4[i4]);
+ page_list_add_tail(mfn_to_page(l4[i4]), &to_free);
}
unmap_domain_page(l4);
- paging_free_log_dirty_page(d, d->arch.paging.log_dirty.top);
+ page_list_add_tail(mfn_to_page(d->arch.paging.log_dirty.top), &to_free);
d->arch.paging.log_dirty.top = _mfn(INVALID_MFN);
ASSERT(d->arch.paging.log_dirty.allocs == 0);
d->arch.paging.log_dirty.failed_allocs = 0;
+
+ log_dirty_unlock(d);
+
+ /* Return the memory now that we're not holding the log-dirty lock */
+ page_list_for_each_safe(pg, tmp, &to_free)
+ paging_free_log_dirty_page(d, page_to_mfn(pg));
}
int paging_log_dirty_enable(struct domain *d)
@@ -217,10 +229,8 @@ int paging_log_dirty_disable(struct doma
domain_pause(d);
/* Safe because the domain is paused. */
ret = d->arch.paging.log_dirty.disable_log_dirty(d);
- log_dirty_lock(d);
if ( !paging_mode_log_dirty(d) )
paging_free_log_dirty_bitmap(d);
- log_dirty_unlock(d);
domain_unpause(d);
return ret;
@@ -672,10 +682,9 @@ void paging_log_dirty_init(struct domain
/* This function fress log dirty bitmap resources. */
static void paging_log_dirty_teardown(struct domain*d)
{
- log_dirty_lock(d);
paging_free_log_dirty_bitmap(d);
- log_dirty_unlock(d);
}
+
/************************************************/
/* CODE FOR PAGING SUPPORT */
/************************************************/
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|