[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] mem_sharing: fix race condition of nominate and unshare
# HG changeset patch # User Tim Deegan <Tim.Deegan@xxxxxxxxxx> # Date 1294333128 0 # Node ID 93236edbc2696ee1d6f467061617a310df7e53f2 # Parent 6874a9d26fd98661a0806d5de8333b30199d6d5e mem_sharing: fix race condition of nominate and unshare (1) When updating/checking p2m type for mem_sharing, we must hold shr_lock (2) For nominate operation, if the page is already nominated, return the handle from page_info->shr_handle (3) For unshare operation, it is possible that multiple users unshare a page via hvm_hap_nested_page_fault() at the same time. If the page is already un-shared by someone else, simply return success. Signed-off-by: Jui-Hao Chiang <juihaochiang@xxxxxxxxx> Signed-off-by: Han-Lin Li <Han-Lin.Li@xxxxxxxxxxx> Acked-by: Tim Deegan <Tim.Deegan@xxxxxxxxxx> --- xen/arch/x86/mm/mem_sharing.c | 37 ++++++++++++++++++++++++------------- 1 files changed, 24 insertions(+), 13 deletions(-) diff -r 6874a9d26fd9 -r 93236edbc269 xen/arch/x86/mm/mem_sharing.c --- a/xen/arch/x86/mm/mem_sharing.c Thu Jan 06 14:27:33 2011 +0000 +++ b/xen/arch/x86/mm/mem_sharing.c Thu Jan 06 16:58:48 2011 +0000 @@ -502,6 +502,7 @@ int mem_sharing_nominate_page(struct p2m *phandle = 0UL; + shr_lock(); mfn = gfn_to_mfn(p2m, gfn, &p2mt); /* Check if mfn is valid */ @@ -509,29 +510,33 @@ int mem_sharing_nominate_page(struct p2m if (!mfn_valid(mfn)) goto out; + /* Return the handle if the page is already shared */ + page = mfn_to_page(mfn); + if (p2m_is_shared(p2mt)) { + *phandle = page->shr_handle; + ret = 0; + goto out; + } + /* Check p2m type */ if (!p2m_is_sharable(p2mt)) goto out; /* Try to convert the mfn to the sharable type */ - page = mfn_to_page(mfn); ret = page_make_sharable(d, page, expected_refcnt); if(ret) goto out; /* Create the handle */ ret = -ENOMEM; - shr_lock(); handle = next_handle++; if((hash_entry = mem_sharing_hash_insert(handle, mfn)) == NULL) { - shr_unlock(); goto out; } if((gfn_info = mem_sharing_gfn_alloc()) == NULL) { mem_sharing_hash_destroy(hash_entry); - shr_unlock(); goto out; } @@ -545,7 +550,6 @@ int mem_sharing_nominate_page(struct p2m BUG_ON(page_make_private(d, page) != 0); mem_sharing_hash_destroy(hash_entry); mem_sharing_gfn_destroy(gfn_info, 0); - shr_unlock(); goto out; } @@ -559,11 +563,11 @@ int mem_sharing_nominate_page(struct p2m gfn_info->domain = d->domain_id; page->shr_handle = handle; *phandle = handle; + + ret = 0; + +out: shr_unlock(); - - ret = 0; - -out: return ret; } @@ -633,14 +637,21 @@ int mem_sharing_unshare_page(struct p2m_ struct list_head *le; struct domain *d = p2m->domain; + mem_sharing_audit(); + /* Remove the gfn_info from the list */ + shr_lock(); + mfn = gfn_to_mfn(p2m, gfn, &p2mt); + + /* Has someone already unshared it? */ + if (!p2m_is_shared(p2mt)) { + shr_unlock(); + return 0; + } page = mfn_to_page(mfn); handle = page->shr_handle; - mem_sharing_audit(); - /* Remove the gfn_info from the list */ - shr_lock(); hash_entry = mem_sharing_hash_lookup(handle); list_for_each(le, &hash_entry->gfns) { @@ -707,7 +718,6 @@ private_page_found: mem_sharing_hash_delete(handle); else atomic_dec(&nr_saved_mfns); - shr_unlock(); if(p2m_change_type(p2m, gfn, p2m_ram_shared, p2m_ram_rw) != p2m_ram_shared) @@ -718,6 +728,7 @@ private_page_found: /* Update m2p entry */ set_gpfn_from_mfn(mfn_x(page_to_mfn(page)), gfn); + shr_unlock(); return 0; } _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |