From: Keir Fraser Date: Tue, 17 Mar 2009 15:29:20 +0000 (+0000) Subject: x86: Fix get_page() to not drop reference count if it wasn't incremented. X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~13992^2~52 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=11c121640c88f17b4c78738ffa92c0dd2500b314;p=xen.git x86: Fix get_page() to not drop reference count if it wasn't incremented. Signed-off-by: Keir Fraser --- diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 006964498f..4f58720fed 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -1948,9 +1948,12 @@ struct domain *page_get_owner_and_reference(struct page_info *page) do { x = y; - if ( unlikely((x & PGC_count_mask) == 0) || /* Not allocated? */ - /* Keep one spare reference to be acquired by get_page_light(). */ - unlikely(((x + 2) & PGC_count_mask) <= 1) ) /* Overflow? */ + /* + * Count == 0: Page is not allocated, so we cannot take a reference. + * Count == -1: Reference count would wrap, which is invalid. + * Count == -2: Remaining unused ref is reserved for get_page_light(). + */ + if ( unlikely(((x + 2) & PGC_count_mask) <= 2) ) return NULL; } while ( (y = cmpxchg(&page->count_info, x, x + 1)) != x ); @@ -1966,7 +1969,8 @@ int get_page(struct page_info *page, struct domain *domain) if ( likely(owner == domain) ) return 1; - put_page(page); + if ( owner != NULL ) + put_page(page); if ( !_shadow_mode_refcounts(domain) && !domain->is_dying ) gdprintk(XENLOG_INFO,