kho: fix order calculation for kho_unpreserve_pages()
Commitmaster91e74fa8b1("kho: make sure preservations do not span multiple NUMA nodes") made sure preservations from kho_preserve_pages() do not span multiple NUMA nodes. If they do, the order is reduced and tried again. The same logic was not implemented for kho_unpreserve_pages(). This can result in unpreserve calculating a different order than preserve, and thus not actually unpreserving the pages. Fix this by moving the order calculation logic to __kho_preserve_pages_order() and use it from both preserve and unpreserve paths. Move __kho_unpreserve() down to avoid having a forward declaration. Its users are further down in the file anyway. Also, it results in grouping for all the page-level preservation and unpreservation functions. This unfortunately makes the diff hard to read, but the main change in __kho_unpreserve() is to call __kho_preserve_pages_order() instead of open-coding the order calculation. Fixes:91e74fa8b1("kho: make sure preservations do not span multiple NUMA nodes") Cc: stable@vger.kernel.org Signed-off-by: Pratyush Yadav (Google) <pratyush@kernel.org> Reviewed-by: Samiullah Khawaja <skhawaja@google.com> Reviewed-by: Pasha Tatashin <pasha.tatashin@soleen.com> Link: https://patch.msgid.link/20260519133332.2498092-1-pratyush@kernel.org Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
parent
d64b037276
commit
8fd2f26fa2
|
|
@ -357,20 +357,6 @@ int kho_radix_walk_tree(struct kho_radix_tree *tree,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(kho_radix_walk_tree);
|
EXPORT_SYMBOL_GPL(kho_radix_walk_tree);
|
||||||
|
|
||||||
static void __kho_unpreserve(struct kho_radix_tree *tree,
|
|
||||||
unsigned long pfn, unsigned long end_pfn)
|
|
||||||
{
|
|
||||||
unsigned int order;
|
|
||||||
|
|
||||||
while (pfn < end_pfn) {
|
|
||||||
order = min(count_trailing_zeros(pfn), ilog2(end_pfn - pfn));
|
|
||||||
|
|
||||||
kho_radix_del_page(tree, pfn, order);
|
|
||||||
|
|
||||||
pfn += 1 << order;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* For physically contiguous 0-order pages. */
|
/* For physically contiguous 0-order pages. */
|
||||||
static void kho_init_pages(struct page *page, unsigned long nr_pages)
|
static void kho_init_pages(struct page *page, unsigned long nr_pages)
|
||||||
{
|
{
|
||||||
|
|
@ -860,6 +846,37 @@ void kho_unpreserve_folio(struct folio *folio)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(kho_unpreserve_folio);
|
EXPORT_SYMBOL_GPL(kho_unpreserve_folio);
|
||||||
|
|
||||||
|
static unsigned int __kho_preserve_pages_order(unsigned long start_pfn,
|
||||||
|
unsigned long end_pfn)
|
||||||
|
{
|
||||||
|
unsigned int order = min(count_trailing_zeros(start_pfn),
|
||||||
|
ilog2(end_pfn - start_pfn));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make sure all the pages in a single preservation are in the same NUMA
|
||||||
|
* node. The restore machinery can not cope with a preservation spanning
|
||||||
|
* multiple NUMA nodes.
|
||||||
|
*/
|
||||||
|
while (pfn_to_nid(start_pfn) != pfn_to_nid(start_pfn + (1UL << order) - 1))
|
||||||
|
order--;
|
||||||
|
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __kho_unpreserve(struct kho_radix_tree *tree,
|
||||||
|
unsigned long pfn, unsigned long end_pfn)
|
||||||
|
{
|
||||||
|
unsigned int order;
|
||||||
|
|
||||||
|
while (pfn < end_pfn) {
|
||||||
|
order = __kho_preserve_pages_order(pfn, end_pfn);
|
||||||
|
|
||||||
|
kho_radix_del_page(tree, pfn, order);
|
||||||
|
|
||||||
|
pfn += 1 << order;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* kho_preserve_pages - preserve contiguous pages across kexec
|
* kho_preserve_pages - preserve contiguous pages across kexec
|
||||||
* @page: first page in the list.
|
* @page: first page in the list.
|
||||||
|
|
@ -885,16 +902,7 @@ int kho_preserve_pages(struct page *page, unsigned long nr_pages)
|
||||||
}
|
}
|
||||||
|
|
||||||
while (pfn < end_pfn) {
|
while (pfn < end_pfn) {
|
||||||
unsigned int order =
|
unsigned int order = __kho_preserve_pages_order(pfn, end_pfn);
|
||||||
min(count_trailing_zeros(pfn), ilog2(end_pfn - pfn));
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Make sure all the pages in a single preservation are in the
|
|
||||||
* same NUMA node. The restore machinery can not cope with a
|
|
||||||
* preservation spanning multiple NUMA nodes.
|
|
||||||
*/
|
|
||||||
while (pfn_to_nid(pfn) != pfn_to_nid(pfn + (1UL << order) - 1))
|
|
||||||
order--;
|
|
||||||
|
|
||||||
err = kho_radix_add_page(tree, pfn, order);
|
err = kho_radix_add_page(tree, pfn, order);
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue