diff options
author | Tim Deegan <tim@xen.org> | 2012-03-15 11:12:44 +0000 |
---|---|---|
committer | Tim Deegan <tim@xen.org> | 2012-03-15 11:12:44 +0000 |
commit | 0806e3965914990286b62c120e95f09e4962152c (patch) | |
tree | 2c7da2078ca2aec05371fffde8c56d11ddbefdb6 /xen/common/memory.c | |
parent | 9ccfacd4706c785434848b9b31701945eceefe0f (diff) | |
download | xen-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.c | 1 |
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 */ |