aboutsummaryrefslogtreecommitdiffstats
path: root/xen/common/memory.c
diff options
context:
space:
mode:
authorTim Deegan <tim@xen.org>2012-03-15 11:12:44 +0000
committerTim Deegan <tim@xen.org>2012-03-15 11:12:44 +0000
commit0806e3965914990286b62c120e95f09e4962152c (patch)
tree2c7da2078ca2aec05371fffde8c56d11ddbefdb6 /xen/common/memory.c
parent9ccfacd4706c785434848b9b31701945eceefe0f (diff)
downloadxen-0806e3965914990286b62c120e95f09e4962152c.tar.gz
xen-0806e3965914990286b62c120e95f09e4962152c.tar.bz2
xen-0806e3965914990286b62c120e95f09e4962152c.zip
Memory sharing: better handling of ENOMEM while unsharing
If unsharing fails with ENOMEM, we were: - leaving the list of gfns backed by the shared page in an inconsistent state - cycling forever on the hap page fault handler. - Attempting to produce a mem event (which could sleep on a wait queue) while holding locks. - Not checking, for all callers, that unshare could have indeed failed. Fix bugs above, and sanitize callers to place a ring event in an unlocked context, or without requiring to go to sleep on a wait queue. A note on the rationale for unshare error handling: 1. Unshare can only fail with ENOMEM. Any other error conditions BUG_ON() 2. We notify a potential dom0 helper through a mem_event ring. But we allow the notification to not go to sleep. If the event ring is full of ENOMEM warnings, then the helper will already have been kicked enough. 3. We cannot "just" go to sleep until the unshare is resolved, because we might be buried deep into locks (e.g. something -> copy_to_user -> __hvm_copy) 4. So, we make sure we: 4.1. return an error 4.2. do not corrupt memory shared with other guests 4.3. do not corrupt memory private to the current guest 4.4. do not corrupt the hypervisor memory sharing meta data 4.5. let the guest deal with the error, if propagation will reach that far Signed-off-by: Andres Lagar-Cavilla <andres@lagarcavilla.org> Acked-by: Tim Deegan <tim@xen.org> Committed-by: Tim Deegan <tim@xen.org>
Diffstat (limited to 'xen/common/memory.c')
-rw-r--r--xen/common/memory.c1
1 files changed, 1 insertions, 0 deletions
diff --git a/xen/common/memory.c b/xen/common/memory.c
index e0976b1f08..907c6fdbde 100644
--- a/xen/common/memory.c
+++ b/xen/common/memory.c
@@ -200,6 +200,7 @@ int guest_remove_page(struct domain *d, unsigned long gmfn)
if ( mem_sharing_unshare_page(d, gmfn, 0) )
{
put_gfn(d, gmfn);
+ (void)mem_sharing_notify_enomem(d, gmfn, 0);
return 0;
}
/* Maybe the mfn changed */