mm, page_alloc: Fix a division by zero error when boosting watermarks
Subsystems (2)
PATCH 1/1 mm, page_alloc: Fix a division by zero error when boosting watermarks
Yury Norov reported that an arm64 KVM instance could not boot since after v5.0-rc1 and could addressed by reverting the patches
1c30844d2dfe272d58c ("mm: reclaim small amounts of memory when an external 73444bc4d8f92e46a20 ("mm, page_alloc: do not wake kswapd with zone lock held")
The problem is that a division by zero error is possible if boosting occurs either very early in boot or if the high watermark is very small. This patch checks for the conditions and avoids boosting in those cases.
--- mm/page_alloc.c | 5 +++++ 1 file changed, 5 insertions(+)
mm/page_alloc.c +5 -0
@@ -2170,6 +2170,11 @@ static inline void boost_watermark(struct zone *zone) max_boost =mult_frac (zone->_watermark[WMARK_HIGH ], watermark_boost_factor,10000 ); + +/* high watermark be be uninitialised or very small */ +if (!max_boost) +return ; + max_boost =max (pageblock_nr_pages, max_boost); zone->watermark_boost = min(zone->watermark_boost + pageblock_nr_pages,
Signature · 2 lines
Mel Gorman SUSE Labs
Quoted 23 lines · Mel Gorman
Yury Norov reported that an arm64 KVM instance could not boot since after v5.0-rc1 and could addressed by reverting the patches
1c30844d2dfe272d58c("mm: reclaim small amounts of memory when an external73444bc4d8f92e46a20("mm,page_alloc: do not wake kswapd with zone lock held")The problem is that a division by zero error is possible if boosting occurs either very early in boot or if the high watermark is very small. This patch checks for the conditions and avoids boosting in those cases.
Fixes 1c30844d2dfe ("mm: reclaim small amounts of memory when an external fragmentation event occurs")Reported-and-tested-by Yury Norov <[email protected]>Signed-off-by Mel Gorman <[email protected]>--- mm/page_alloc.c | 5 +++++ 1 file changed, 5 insertions(+)mm/page_alloc.c +0
-0@@ -2170,6 +2170,11 @@ static inline void boost_watermark(struct zone *zone)
mm/page_alloc.c static inline void boost_watermark(struct zone *zone) · line 2180
Quoted 10 lines
mm/page_alloc.c +5
-0max_boost =mult_frac (zone->_watermark[WMARK_HIGH ], watermark_boost_factor,10000 ); + +/* high watermark be be uninitialised or very small */ +if (!max_boost) +return ; + max_boost =max (pageblock_nr_pages, max_boost); zone->watermark_boost = min(zone->watermark_boost + pageblock_nr_pages,
I can confirm that this also allows my KVM guest to boot:
Will
Quoted 9 lines · Mel Gorman
Yury Norov reported that an arm64 KVM instance could not boot since after v5.0-rc1 and could addressed by reverting the patches
1c30844d2dfe272d58c("mm: reclaim small amounts of memory when an external73444bc4d8f92e46a20("mm,page_alloc: do not wake kswapd with zone lock held")The problem is that a division by zero error is possible if boosting occurs either very early in boot or if the high watermark is very small. This patch checks for the conditions and avoids boosting in those cases.
Hmm is it really a division by zero? The following line sets max_boost to pageblock_nr_pages if it's zero. And where would the division happen anyway?
So I wonder what's going on, your patch should AFAICS only take effect when zone->_watermark[WMARK_HIGH] is 0 or 1 to begin with, otherwise max_boost is at least 2?
Also upon closer look, I think that (prior to the patch), boost_watermark() could be reduced (thanks to the max+min capping) to
zone->watermark_boost = pageblock_nr_pages
?
Quoted 25 lines
Fixes 1c30844d2dfe ("mm: reclaim small amounts of memory when an external fragmentation event occurs")Reported-and-tested-by Yury Norov <[email protected]>Signed-off-by Mel Gorman <[email protected]>--- mm/page_alloc.c | 5 +++++ 1 file changed, 5 insertions(+)mm/page_alloc.c +5
-0@@ -2170,6 +2170,11 @@ static inline void boost_watermark(struct zone *zone) max_boost =mult_frac (zone->_watermark[WMARK_HIGH ], watermark_boost_factor,10000 ); + +/* high watermark be be uninitialised or very small */ +if (!max_boost) +return ; + max_boost =max (pageblock_nr_pages, max_boost); zone->watermark_boost = min(zone->watermark_boost + pageblock_nr_pages,
Quoted 11 lines · Vlastimil Babka
Quoted 9 lines · Mel Gorman
Yury Norov reported that an arm64 KVM instance could not boot since after v5.0-rc1 and could addressed by reverting the patches
1c30844d2dfe272d58c("mm: reclaim small amounts of memory when an external73444bc4d8f92e46a20("mm,page_alloc: do not wake kswapd with zone lock held")The problem is that a division by zero error is possible if boosting occurs either very early in boot or if the high watermark is very small. This patch checks for the conditions and avoids boosting in those cases.
Quoted 7 lines
Hmm is it really a division by zero? The following line sets
max_boosttopageblock_nr_pagesif it's zero. And where would the division happen anyway?So I wonder what's going on, your patch should AFAICS only take effect when zone->_watermark[WMARK_HIGH] is 0 or 1 to begin with, otherwise
max_boostis at least 2?
The issue can occur if pageblock_nr_pages is also zero or not yet initialised. It means the changelog is misleading because it has to trigger very early in boot as happened with Yury.
Quoted 5 lines
Also upon closer look, I think that (prior to the patch),
boost_watermark()could be reduced (thanks to the max+min capping) to
zone->watermark_boost=pageblock_nr_pages
I don't think it's worth being fancy about it if we're hitting fragmentation issues that early in boot.
Signature · 2 lines
Mel Gorman SUSE Labs
PATCH 1/1 mm, page_alloc: Fix a division by zero error when boosting watermarks v2
In reply to Mel GormanYury Norov reported that an arm64 KVM instance could not boot since after v5.0-rc1 and could addressed by reverting the patches
1c30844d2dfe272d58c ("mm: reclaim small amounts of memory when an external 73444bc4d8f92e46a20 ("mm, page_alloc: do not wake kswapd with zone lock held")
The problem is that a division by zero error is possible if boosting occurs very early in boot if the system has very little memory. This patch avoids the division by zero error.
--- mm/page_alloc.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
mm/page_alloc.c +12 -0
@@ -2170,6 +2170,18 @@ static inline void boost_watermark(struct zone *zone) max_boost =mult_frac (zone->_watermark[WMARK_HIGH ], watermark_boost_factor,10000 ); + +/* +* high watermark may be uninitialised if fragmentation occurs +* very early in boot so do not boost. We do not fall +* through and boost by pageblock_nr_pages as failing +* allocations that early means that reclaim is not going +* to help and it may even be impossible to reclaim the +* boosted watermark resulting in a hang. +*/ +if (!max_boost) +return ; + max_boost =max (pageblock_nr_pages, max_boost); zone->watermark_boost = min(zone->watermark_boost + pageblock_nr_pages,
Signature · 2 lines
Mel Gorman SUSE Labs
Re: [PATCH] mm, page_alloc: Fix a division by zero error when boosting watermarks v2
Quoted 6 lines · Mel Gorman
Yury Norov reported that an arm64 KVM instance could not boot since after v5.0-rc1 and could addressed by reverting the patches
1c30844d2dfe272d58c("mm: reclaim small amounts of memory when an external73444bc4d8f92e46a20("mm,page_alloc: do not wake kswapd with zone lock held")
Quoted 8 lines
The problem is that a division by zero error is possible if boosting occurs very early in boot if the system has very little memory. This patch avoids the division by zero error.
Fixes 1c30844d2dfe ("mm: reclaim small amounts of memory when an external fragmentation event occurs")Reported-and-tested-by Yury Norov <[email protected]>Tested-by Will Deacon <[email protected]>Signed-off-by Mel Gorman <[email protected]>
Thanks, sorry for the noise before.
Quoted 28 lines
--- mm/page_alloc.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)mm/page_alloc.c +12
-0@@ -2170,6 +2170,18 @@ static inline void boost_watermark(struct zone *zone) max_boost =mult_frac (zone->_watermark[WMARK_HIGH ], watermark_boost_factor,10000 ); + +/* +* high watermark may be uninitialised if fragmentation occurs +* very early in boot so do not boost. We do not fall +* through and boost by pageblock_nr_pages as failing +* allocations that early means that reclaim is not going +* to help and it may even be impossible to reclaim the +* boosted watermark resulting in a hang. +*/ +if (!max_boost) +return ; + max_boost =max (pageblock_nr_pages, max_boost); zone->watermark_boost = min(zone->watermark_boost + pageblock_nr_pages,