debuggers.hg
changeset 22702:93236edbc269
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@gmail.com>
Signed-off-by: Han-Lin Li <Han-Lin.Li@itri.org.tw>
Acked-by: Tim Deegan <Tim.Deegan@citrix.com>
(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@gmail.com>
Signed-off-by: Han-Lin Li <Han-Lin.Li@itri.org.tw>
Acked-by: Tim Deegan <Tim.Deegan@citrix.com>
author | Tim Deegan <Tim.Deegan@citrix.com> |
---|---|
date | Thu Jan 06 16:58:48 2011 +0000 (2011-01-06) |
parents | 6874a9d26fd9 |
children | 4c2efce5a808 |
files | xen/arch/x86/mm/mem_sharing.c |
line diff
1.1 --- a/xen/arch/x86/mm/mem_sharing.c Thu Jan 06 14:27:33 2011 +0000 1.2 +++ b/xen/arch/x86/mm/mem_sharing.c Thu Jan 06 16:58:48 2011 +0000 1.3 @@ -502,6 +502,7 @@ int mem_sharing_nominate_page(struct p2m 1.4 1.5 *phandle = 0UL; 1.6 1.7 + shr_lock(); 1.8 mfn = gfn_to_mfn(p2m, gfn, &p2mt); 1.9 1.10 /* Check if mfn is valid */ 1.11 @@ -509,29 +510,33 @@ int mem_sharing_nominate_page(struct p2m 1.12 if (!mfn_valid(mfn)) 1.13 goto out; 1.14 1.15 + /* Return the handle if the page is already shared */ 1.16 + page = mfn_to_page(mfn); 1.17 + if (p2m_is_shared(p2mt)) { 1.18 + *phandle = page->shr_handle; 1.19 + ret = 0; 1.20 + goto out; 1.21 + } 1.22 + 1.23 /* Check p2m type */ 1.24 if (!p2m_is_sharable(p2mt)) 1.25 goto out; 1.26 1.27 /* Try to convert the mfn to the sharable type */ 1.28 - page = mfn_to_page(mfn); 1.29 ret = page_make_sharable(d, page, expected_refcnt); 1.30 if(ret) 1.31 goto out; 1.32 1.33 /* Create the handle */ 1.34 ret = -ENOMEM; 1.35 - shr_lock(); 1.36 handle = next_handle++; 1.37 if((hash_entry = mem_sharing_hash_insert(handle, mfn)) == NULL) 1.38 { 1.39 - shr_unlock(); 1.40 goto out; 1.41 } 1.42 if((gfn_info = mem_sharing_gfn_alloc()) == NULL) 1.43 { 1.44 mem_sharing_hash_destroy(hash_entry); 1.45 - shr_unlock(); 1.46 goto out; 1.47 } 1.48 1.49 @@ -545,7 +550,6 @@ int mem_sharing_nominate_page(struct p2m 1.50 BUG_ON(page_make_private(d, page) != 0); 1.51 mem_sharing_hash_destroy(hash_entry); 1.52 mem_sharing_gfn_destroy(gfn_info, 0); 1.53 - shr_unlock(); 1.54 goto out; 1.55 } 1.56 1.57 @@ -559,11 +563,11 @@ int mem_sharing_nominate_page(struct p2m 1.58 gfn_info->domain = d->domain_id; 1.59 page->shr_handle = handle; 1.60 *phandle = handle; 1.61 - shr_unlock(); 1.62 1.63 ret = 0; 1.64 1.65 out: 1.66 + shr_unlock(); 1.67 return ret; 1.68 } 1.69 1.70 @@ -633,14 +637,21 @@ int mem_sharing_unshare_page(struct p2m_ 1.71 struct list_head *le; 1.72 struct domain *d = p2m->domain; 1.73 1.74 + mem_sharing_audit(); 1.75 + /* Remove the gfn_info from the list */ 1.76 + shr_lock(); 1.77 + 1.78 mfn = gfn_to_mfn(p2m, gfn, &p2mt); 1.79 + 1.80 + /* Has someone already unshared it? */ 1.81 + if (!p2m_is_shared(p2mt)) { 1.82 + shr_unlock(); 1.83 + return 0; 1.84 + } 1.85 1.86 page = mfn_to_page(mfn); 1.87 handle = page->shr_handle; 1.88 1.89 - mem_sharing_audit(); 1.90 - /* Remove the gfn_info from the list */ 1.91 - shr_lock(); 1.92 hash_entry = mem_sharing_hash_lookup(handle); 1.93 list_for_each(le, &hash_entry->gfns) 1.94 { 1.95 @@ -707,7 +718,6 @@ private_page_found: 1.96 mem_sharing_hash_delete(handle); 1.97 else 1.98 atomic_dec(&nr_saved_mfns); 1.99 - shr_unlock(); 1.100 1.101 if(p2m_change_type(p2m, gfn, p2m_ram_shared, p2m_ram_rw) != 1.102 p2m_ram_shared) 1.103 @@ -718,6 +728,7 @@ private_page_found: 1.104 /* Update m2p entry */ 1.105 set_gpfn_from_mfn(mfn_x(page_to_mfn(page)), gfn); 1.106 1.107 + shr_unlock(); 1.108 return 0; 1.109 } 1.110