|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v2 2/6] x86/mem-paging: correct p2m_mem_paging_prep()'s error handling
On 23/04/2020 09:37, Jan Beulich wrote:
> Communicating errors from p2m_set_entry() to the caller is not enough:
> Neither the M2P nor the stats updates should occur in such a case.
"neither". Following a colon/semicolon isn't the start of a new sentence.
> Instead the allocated page needs to be freed again; for cleanliness
> reasons also properly take into account _PGC_allocated there.
>
> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
>
> --- a/xen/arch/x86/mm/p2m.c
> +++ b/xen/arch/x86/mm/p2m.c
> @@ -1781,7 +1781,7 @@ void p2m_mem_paging_populate(struct doma
> */
> int p2m_mem_paging_prep(struct domain *d, unsigned long gfn_l, uint64_t
> buffer)
> {
> - struct page_info *page;
> + struct page_info *page = NULL;
> p2m_type_t p2mt;
> p2m_access_t a;
> gfn_t gfn = _gfn(gfn_l);
> @@ -1816,9 +1816,19 @@ int p2m_mem_paging_prep(struct domain *d
> goto out;
> /* Get a free page */
> ret = -ENOMEM;
> - page = alloc_domheap_page(p2m->domain, 0);
> + page = alloc_domheap_page(d, 0);
> if ( unlikely(page == NULL) )
> goto out;
> + if ( unlikely(!get_page(page, d)) )
> + {
> + /*
> + * The domain can't possibly know about this page yet, so failure
> + * here is a clear indication of something fishy going on.
> + */
This needs a gprintk(XENLOG_ERR, ...) of some form. (which also reminds
me that I *still* need to finish my patch forcing everyone to provide
something to qualify the domain crash, so release builds of Xen get some
hint as to what went on or why.)
> + domain_crash(d);
> + page = NULL;
> + goto out;
> + }
> mfn = page_to_mfn(page);
> page_extant = 0;
>
> @@ -1832,7 +1842,6 @@ int p2m_mem_paging_prep(struct domain *d
> "Failed to load paging-in gfn %lx Dom%d bytes left
> %d\n",
> gfn_l, d->domain_id, ret);
> ret = -EFAULT;
> - put_page(page); /* Don't leak pages */
> goto out;
> }
> }
> @@ -1843,13 +1852,24 @@ int p2m_mem_paging_prep(struct domain *d
> ret = p2m_set_entry(p2m, gfn, mfn, PAGE_ORDER_4K,
> paging_mode_log_dirty(d) ? p2m_ram_logdirty
> : p2m_ram_rw, a);
> - set_gpfn_from_mfn(mfn_x(mfn), gfn_l);
> + if ( !ret )
> + {
> + set_gpfn_from_mfn(mfn_x(mfn), gfn_l);
>
> - if ( !page_extant )
> - atomic_dec(&d->paged_pages);
> + if ( !page_extant )
> + atomic_dec(&d->paged_pages);
> + }
>
> out:
> gfn_unlock(p2m, gfn, 0);
> +
> + if ( page )
> + {
> + if ( ret )
> + put_page_alloc_ref(page);
> + put_page(page);
This is a very long way from clear enough to follow, and buggy if anyone
inserts a new goto out path.
~Andrew
> + }
> +
> return ret;
> }
>
>
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |