|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] dom0 linux 3.6.0-rc4, crash due to ballooning althoug dom0_mem=X, max:X set
Tuesday, September 11, 2012, 6:02:47 PM, you wrote:
> On Wed, 5 Sep 2012, Konrad Rzeszutek Wilk wrote:
>> On Tue, Sep 04, 2012 at 04:27:20PM -0400, Robert Phillips wrote:
>> > Ben,
>> >
>> > You have asked me to provide the rationale behind the gnttab_old_mfn
>> > patch, which you emailed to Sander earlier today.
>> > Here are my findings.
>> >
>> > I found that xen_blkbk_map() in drivers/block/xen-blkback/blkback.c has
>> > changed from our previous version. It now calls gnttab_map_refs() in
>> > drivers/xen/grant-table.c.
>> >
>> > That function first calls
>> > HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, ... ) and then calls
>> > m2p_add_override() in p2m.c
>>
>> And HYPERVISOR_grant_table_op .. would populate map_ops[i].bus_addr with the
>> machine address..
>>
>> > which is where I made my change.
>> >
>> > The unpatched code was saving the pfn's old mfn in kmap_op->dev_bus_addr.
>> >
>> > kmap_op is of type struct gnttab_map_grant_ref. That data type is used to
>> > record grant table mappings so later they can be unmapped correctly.
>>
>> Right, but the blkback makes a distinction by passing NULL as kmap_op, which
>> means it should
>> use the old mechanism. Meaning that once the hypercall is done, the
>> map_ops[i].bus_addr is not
>> used anymore..
>>
>> >
>> > The problem with saving the old mfn in kmap_op->dev_bus_addr is that it is
>> > later overwritten by __gnttab_map_grant_ref() in xen/common/grant_table.c
>>
>> Uh, so the problem of saving the old mfn in dev_bus_addr has been there for
>> a long long time then?
>> Even before this patch set?
> I think that Robert identified the real problem: dev_bus_addr shouldn't
> have been used here. However the bug only shows up if we are batching
> the grant table operations, that we started doing since
> f62805f1f30a40e354bd036b4cb799863a39be4b.
> That's why Sander's bisection found that
> f62805f1f30a40e354bd036b4cb799863a39be4b is the culprit.
> However the fix is incorrect because it is modifying a struct that is
> part of the Xen ABI.
> I am appending an alternative fix that doesn't need any changes to
> public headers.
> Sander, could you please let me know if it fixes the problem for you?
It does !
Tested-By: Sander Eikelenboom <linux@xxxxxxxxxxxxxx>
> ---
> diff --git a/arch/x86/include/asm/xen/page.h b/arch/x86/include/asm/xen/page.h
> index 93971e8..472b9b7 100644
> --- a/arch/x86/include/asm/xen/page.h
> +++ b/arch/x86/include/asm/xen/page.h
> @@ -51,7 +51,8 @@ extern unsigned long set_phys_range_identity(unsigned long
> pfn_s,
>
> extern int m2p_add_override(unsigned long mfn, struct page *page,
> struct gnttab_map_grant_ref *kmap_op);
> -extern int m2p_remove_override(struct page *page, bool clear_pte);
> +extern int m2p_remove_override(struct page *page,
> + struct gnttab_map_grant_ref *kmap_op);
> extern struct page *m2p_find_override(unsigned long mfn);
> extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long
> pfn);
>
> diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c
> index 64effdc..2825594 100644
> --- a/arch/x86/xen/p2m.c
> +++ b/arch/x86/xen/p2m.c
> @@ -734,9 +734,6 @@ int m2p_add_override(unsigned long mfn, struct page *page,
>
> xen_mc_issue(PARAVIRT_LAZY_MMU);
> }
> - /* let's use dev_bus_addr to record the old mfn instead */
> - kmap_op->dev_bus_addr = page->index;
> - page->index = (unsigned long) kmap_op;
> }
> spin_lock_irqsave(&m2p_override_lock, flags);
> list_add(&page->lru, &m2p_overrides[mfn_hash(mfn)]);
> @@ -763,7 +760,8 @@ int m2p_add_override(unsigned long mfn, struct page *page,
> return 0;
> }
> EXPORT_SYMBOL_GPL(m2p_add_override);
> -int m2p_remove_override(struct page *page, bool clear_pte)
> +int m2p_remove_override(struct page *page,
> + struct gnttab_map_grant_ref *kmap_op)
> {
> unsigned long flags;
> unsigned long mfn;
> @@ -793,10 +791,8 @@ int m2p_remove_override(struct page *page, bool
> clear_pte)
> WARN_ON(!PagePrivate(page));
> ClearPagePrivate(page);
>
> - if (clear_pte) {
> - struct gnttab_map_grant_ref *map_op =
> - (struct gnttab_map_grant_ref *) page->index;
> - set_phys_to_machine(pfn, map_op->dev_bus_addr);
> + set_phys_to_machine(pfn, page->index);
> + if (kmap_op != NULL) {
> if (!PageHighMem(page)) {
> struct multicall_space mcs;
> struct gnttab_unmap_grant_ref *unmap_op;
> @@ -808,13 +804,13 @@ int m2p_remove_override(struct page *page, bool
> clear_pte)
> * issued. In this case handle is going to -1 because
> * it hasn't been modified yet.
> */
> - if (map_op->handle == -1)
> + if (kmap_op->handle == -1)
> xen_mc_flush();
> /*
> - * Now if map_op->handle is negative it means that the
> + * Now if kmap_op->handle is negative it means that
> the
> * hypercall actually returned an error.
> */
> - if (map_op->handle == GNTST_general_error) {
> + if (kmap_op->handle == GNTST_general_error) {
> printk(KERN_WARNING "m2p_remove_override: "
> "pfn %lx mfn %lx, failed to
> modify kernel mappings",
> pfn, mfn);
> @@ -824,8 +820,8 @@ int m2p_remove_override(struct page *page, bool clear_pte)
> mcs = xen_mc_entry(
> sizeof(struct
> gnttab_unmap_grant_ref));
> unmap_op = mcs.args;
> - unmap_op->host_addr = map_op->host_addr;
> - unmap_op->handle = map_op->handle;
> + unmap_op->host_addr = kmap_op->host_addr;
> + unmap_op->handle = kmap_op->handle;
> unmap_op->dev_bus_addr = 0;
>
> MULTI_grant_table_op(mcs.mc,
> @@ -836,10 +832,9 @@ int m2p_remove_override(struct page *page, bool
> clear_pte)
> set_pte_at(&init_mm, address, ptep,
> pfn_pte(pfn, PAGE_KERNEL));
> __flush_tlb_single(address);
> - map_op->host_addr = 0;
> + kmap_op->host_addr = 0;
> }
> - } else
> - set_phys_to_machine(pfn, page->index);
> + }
>
> /* p2m(m2p(mfn)) == FOREIGN_FRAME(mfn): the mfn is already present
> * somewhere in this domain, even before being added to the
> diff --git a/drivers/block/xen-blkback/blkback.c
> b/drivers/block/xen-blkback/blkback.c
> index 73f196c..c6decb9 100644
> --- a/drivers/block/xen-blkback/blkback.c
> +++ b/drivers/block/xen-blkback/blkback.c
> @@ -337,7 +337,7 @@ static void xen_blkbk_unmap(struct pending_req *req)
> invcount++;
> }
>
> - ret = gnttab_unmap_refs(unmap, pages, invcount, false);
> + ret = gnttab_unmap_refs(unmap, NULL, pages, invcount);
> BUG_ON(ret);
> }
>
> diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
> index 1ffd03b..7f12416 100644
> --- a/drivers/xen/gntdev.c
> +++ b/drivers/xen/gntdev.c
> @@ -314,8 +314,9 @@ static int __unmap_grant_pages(struct grant_map *map, int
> offset, int pages)
> }
> }
>
> - err = gnttab_unmap_refs(map->unmap_ops + offset, map->pages + offset,
> - pages, true);
> + err = gnttab_unmap_refs(map->unmap_ops + offset,
> + use_ptemod ? map->kmap_ops + offset : NULL,
> map->pages + offset,
> + pages);
> if (err)
> return err;
>
> diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
> index 0bfc1ef..0067266 100644
> --- a/drivers/xen/grant-table.c
> +++ b/drivers/xen/grant-table.c
> @@ -870,7 +870,8 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
> EXPORT_SYMBOL_GPL(gnttab_map_refs);
>
> int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
> - struct page **pages, unsigned int count, bool clear_pte)
> + struct gnttab_map_grant_ref *kmap_ops,
> + struct page **pages, unsigned int count)
> {
> int i, ret;
> bool lazy = false;
> @@ -888,7 +889,8 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref
> *unmap_ops,
> }
>
> for (i = 0; i < count; i++) {
> - ret = m2p_remove_override(pages[i], clear_pte);
> + ret = m2p_remove_override(pages[i], kmap_ops ?
> + &kmap_ops[i] : NULL);
> if (ret)
> return ret;
> }
> diff --git a/include/xen/grant_table.h b/include/xen/grant_table.h
> index 11e27c3..f19fff8 100644
> --- a/include/xen/grant_table.h
> +++ b/include/xen/grant_table.h
> @@ -187,6 +187,7 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
> struct gnttab_map_grant_ref *kmap_ops,
> struct page **pages, unsigned int count);
> int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
> - struct page **pages, unsigned int count, bool
> clear_pte);
> + struct gnttab_map_grant_ref *kunmap_ops,
> + struct page **pages, unsigned int count);
>
> #endif /* __ASM_GNTTAB_H__ */
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |