Skip to content

Commit 1da602e

Browse files
jacobpanliuw
authored andcommitted
hv_balloon: Fallback to generic_online_page() for non-HV hot added mem
The Hyper-V balloon driver installs a custom callback for handling page onlining operations performed by the memory hotplug subsystem. This custom callback is global, and overrides the default callback (generic_online_page) that Linux otherwise uses. The custom callback properly handles memory that is hot-added by the balloon driver as part of a Hyper-V hot-add region. But memory can also be hot-added directly by a device driver for a vPCI device, particularly GPUs. In such a case, the custom callback installed by the balloon driver runs, but won't find the page in its hot-add region list and doesn't online it, which could cause driver initialization failures. Fix this by having the balloon custom callback run generic_online_page() when the page isn't part of a Hyper-V hot-add region, thereby doing the default Linux behavior. This allows device driver hot-adds to work properly. Similar cases are handled the same way in the virtio-mem driver. Suggested-by: Vikram Sethi <[email protected]> Tested-by: Michael Frohlich <[email protected]> Reviewed-by: Michael Kelley <[email protected]> Signed-off-by: Jacob Pan <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Wei Liu <[email protected]> Message-ID: <[email protected]>
1 parent fcf5203 commit 1da602e

File tree

1 file changed

+10
-8
lines changed

1 file changed

+10
-8
lines changed

drivers/hv/hv_balloon.c

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -766,16 +766,18 @@ static void hv_online_page(struct page *pg, unsigned int order)
766766
struct hv_hotadd_state *has;
767767
unsigned long pfn = page_to_pfn(pg);
768768

769-
guard(spinlock_irqsave)(&dm_device.ha_lock);
770-
list_for_each_entry(has, &dm_device.ha_region_list, list) {
771-
/* The page belongs to a different HAS. */
772-
if (pfn < has->start_pfn ||
773-
(pfn + (1UL << order) > has->end_pfn))
774-
continue;
769+
scoped_guard(spinlock_irqsave, &dm_device.ha_lock) {
770+
list_for_each_entry(has, &dm_device.ha_region_list, list) {
771+
/* The page belongs to a different HAS. */
772+
if (pfn < has->start_pfn ||
773+
(pfn + (1UL << order) > has->end_pfn))
774+
continue;
775775

776-
hv_bring_pgs_online(has, pfn, 1UL << order);
777-
break;
776+
hv_bring_pgs_online(has, pfn, 1UL << order);
777+
return;
778+
}
778779
}
780+
generic_online_page(pg, order);
779781
}
780782

781783
static int pfn_covered(unsigned long start_pfn, unsigned long pfn_cnt)

0 commit comments

Comments
 (0)