Commit cdc5dc5b authored by Vitaly Kuznetsov's avatar Vitaly Kuznetsov Committed by Greg Kroah-Hartman

hv_balloon: avoid touching uninitialized struct page during tail onlining

commit da8ced36 upstream.

Hyper-V memory hotplug protocol has 2M granularity and in Linux x86 we use
128M. To deal with it we implement partial section onlining by registering
custom page onlining callback (hv_online_page()). Later, when more memory
arrives we try to online the 'tail' (see hv_bring_pgs_online()).

It was found that in some cases this 'tail' onlining causes issues:

 BUG: Bad page state in process kworker/0:2  pfn:109e3a
 page:ffffe08344278e80 count:0 mapcount:1 mapping:0000000000000000 index:0x0
 flags: 0xfffff80000000()
 raw: 000fffff80000000 dead000000000100 dead000000000200 0000000000000000
 raw: 0000000000000000 0000000000000000 0000000000000000 0000000000000000
 page dumped because: nonzero mapcount
 Workqueue: events hot_add_req [hv_balloon]
 Call Trace:
  hv_page_online_one+0x5c/0x80 [hv_balloon]
  hot_add_req.cold.24+0x182/0x835 [hv_balloon]

Turns out that we now have deferred struct page initialization for memory
hotplug so e.g. memory_block_action() in drivers/base/memory.c does
pages_correctly_probed() check and in that check it avoids inspecting
struct pages and checks sections instead. But in Hyper-V balloon driver we
do PageReserved(pfn_to_page()) check and this is now wrong.

Switch to checking online_section_nr() instead.
Signed-off-by: 's avatarVitaly Kuznetsov <>
Signed-off-by: 's avatarSasha Levin <>
Signed-off-by: 's avatarGreg Kroah-Hartman <>
parent aefa51ad
......@@ -888,12 +888,14 @@ static unsigned long handle_pg_range(unsigned long pg_start,
pfn_cnt -= pgs_ol;
* Check if the corresponding memory block is already
* online by checking its last previously backed page.
* In case it is we need to bring rest (which was not
* backed previously) online too.
* online. It is possible to observe struct pages still
* being uninitialized here so check section instead.
* In case the section is online we need to bring the
* rest of pfns (which were not backed previously)
* online too.
if (start_pfn > has->start_pfn &&
!PageReserved(pfn_to_page(start_pfn - 1)))
hv_bring_pgs_online(has, start_pfn, pgs_ol);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment