From: Ross Lagerwall Date: Thu, 11 Jan 2018 09:36:37 +0000 (+0000) Subject: xen/grant-table: Use put_page instead of free_page X-Git-Tag: v4.9.104~240 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=240ef711607a8b53e185b1e15b7f3920f677493d;p=platform%2Fkernel%2Flinux-amlogic.git xen/grant-table: Use put_page instead of free_page [ Upstream commit 3ac7292a25db1c607a50752055a18aba32ac2176 ] The page given to gnttab_end_foreign_access() to free could be a compound page so use put_page() instead of free_page() since it can handle both compound and single pages correctly. This bug was discovered when migrating a Xen VM with several VIFs and CONFIG_DEBUG_VM enabled. It hits a BUG usually after fewer than 10 iterations. All netfront devices disconnect from the backend during a suspend/resume and this will call gnttab_end_foreign_access() if a netfront queue has an outstanding skb. The mismatch between calling get_page() and free_page() on a compound page causes a reference counting error which is detected when DEBUG_VM is enabled. Signed-off-by: Ross Lagerwall Reviewed-by: Boris Ostrovsky Signed-off-by: Juergen Gross Signed-off-by: Sasha Levin Signed-off-by: Greg Kroah-Hartman --- diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index bb36b1e..775d419 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c @@ -327,7 +327,7 @@ static void gnttab_handle_deferred(unsigned long unused) if (entry->page) { pr_debug("freeing g.e. %#x (pfn %#lx)\n", entry->ref, page_to_pfn(entry->page)); - __free_page(entry->page); + put_page(entry->page); } else pr_info("freeing g.e. %#x\n", entry->ref); kfree(entry); @@ -383,7 +383,7 @@ void gnttab_end_foreign_access(grant_ref_t ref, int readonly, if (gnttab_end_foreign_access_ref(ref, readonly)) { put_free_entry(ref); if (page != 0) - free_page(page); + put_page(virt_to_page(page)); } else gnttab_add_deferred(ref, readonly, page ? virt_to_page(page) : NULL);