damos_apply_scheme() splits a region and apply the action to the
Subsystems (3)
SJ Park
maintainercover damos_apply_scheme() splits a region and apply the action to the
The user impact is not critical. The failure of damon_split_region_at() is unlikely since it is arguably too small to fail. Also DAMOS being aggressive is limited to the single region. Users can set min_nr_regions to set the maximum size of each region. If it is reasonably set, the transient overhead shouldn't be critical.
The issue was discovered [1] by Sashiko.
[1] https://lore.kernel.org/[email protected]
SJ Park (7):
mm/damon/paddr: respect folio end for DAMOS_STAT mm/damon/paddr: respect folio end for DAMOS actions except STAT mm/damon/vaddr: respect folio end for DAMOS_STAT mm/damon/vaddr: respect folio end for DAMOS_MIGRATE_{HOT,COLD} mm/damon/core: handle extreme memory state in damon_get_node_mem_bp() mm/damon/core: handle extreme memory state in get_node_memcg_used_bp() mm/damon/core: handle extreme memory state in get_in_active_mem_bp()
mm/damon/core.c | 15 ++++++++++++++- mm/damon/paddr.c | 8 ++++---- mm/damon/vaddr.c | 10 ++++++++-- 3 files changed, 26 insertions(+), 7 deletions(-)
base-commit: d93d8b0181065f8375af61e3a18bbc7c066a8159
Signature · 1 line
2.47.3
SJ Park
maintainerPATCH 1/7 mm/damon/paddr: respect folio end for DAMOS_STAT
The function for applying DAMOS_STAT in DAMON physical address space operation set (paddr), namely damon_pa_stat(), applies DAMOS filters to folios of the given region. For that, it gets folios of addresses in the region. It starts from the region start address and advances the address by the size of the folio of the address until it goes out of the region. If the start address is in the middle of a large folio, and if the next folios are small, some of the next folios could be skipped. Fix the issue by advancing the address to exactly the start address of the next folio.
The user impact is that the DAMOS_STAT-based page level monitoring results become inaccurate. Since the page level monitoring is supposed to provide relatively high precision, this is definitely a problem. It is arguably not critical since it is only monitoring quality degradation.
--- mm/damon/paddr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
mm/damon/paddr.c +1 -1
@@ -379,7 +379,7 @@ static unsigned long damon_pa_stat(struct damon_region *r,if (!damos_pa_filter_out (s, folio)) *sz_filter_passed +=folio_size (folio) / addr_unit; - addr +=folio_size (folio); + addr =PFN_PHYS (folio_pfn (folio)) +folio_size (folio);folio_put (folio); } s->last_applied = folio;
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 1/7] mm/damon/paddr: respect folio end for DAMOS_STAT
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 16 lines
The function for applying
DAMOS_STATin DAMON physical address space operation set (paddr), namelydamon_pa_stat(), applies DAMOS filters to folios of the given region. For that, it gets folios of addresses in the region. It starts from the region start address and advances the address by the size of the folio of the address until it goes out of the region. If the start address is in the middle of a large folio, and if the next folios are small, some of the next folios could be skipped. Fix the issue by advancing the address to exactly the start address of the next folio.The user impact is that the DAMOS_STAT-based page level monitoring results become inaccurate. Since the page level monitoring is supposed to provide relatively high precision, this is definitely a problem. It is arguably not critical since it is only monitoring quality degradation.
Quoted 3 lines
Fixes bdbe1d7bc325 ("mm/damon/paddr: increment pa_stat damon address range by folio size")Cc <[email protected]> # 6.14.xSigned-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
SJ Park
maintainerPATCH 2/7 mm/damon/paddr: respect folio end for DAMOS actions except STAT
In reply to SJ ParkA few functions for applying DAMOS actions including pageout, lru_[de]prio and migrate_{hot,cold} in DAMON physical address space operation set (paddr) collect folios of the given region by getting the folios of region-internal addresses. Then, those functions apply the action to the collected folios at once. The collection starts from the region start address and advances the address by the size of the folio of the address until it goes out of the region. If the start address is in the middle of a large folio, and if the next folios are small, some of the next folios could be skipped. Fix the issue by advancing the address to exactly the start address of the next folio.
The user impact is that DAMOS action is applied to less than expected amount of memory. Given the best effort nature of DAMON, it is no big problem, but it is clearly a bug that is better to be fixed.
The issue was discovered [1] by Sashiko.
[1] https://lore.kernel.org/[email protected]
--- mm/damon/paddr.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
mm/damon/paddr.c +3 -3
@@ -264,7 +264,7 @@ static unsigned long damon_pa_pageout(struct damon_region *r,else list_add (&folio->lru, &folio_list); put_folio: - addr +=folio_size (folio); + addr =PFN_PHYS (folio_pfn (folio)) +folio_size (folio);folio_put (folio); }if (install_young_filter)
@@ -302,7 +302,7 @@ static inline unsigned long damon_pa_de_activate(folio_deactivate (folio); applied +=folio_nr_pages (folio); put_folio: - addr +=folio_size (folio); + addr =PFN_PHYS (folio_pfn (folio)) +folio_size (folio);folio_put (folio); } s->last_applied = folio;
@@ -350,7 +350,7 @@ static unsigned long damon_pa_migrate(struct damon_region *r, folio_is_file_lru(folio));list_add (&folio->lru, &folio_list); put_folio: - addr +=folio_size (folio); + addr =PFN_PHYS (folio_pfn (folio)) +folio_size (folio);folio_put (folio); } applied =damon_migrate_pages (&folio_list, s->target_nid);
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 2/7] mm/damon/paddr: respect folio end for DAMOS actions except STAT
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 15 lines
A few functions for applying DAMOS actions including pageout, lru_[de]prio and migrate_{hot,cold} in DAMON physical address space operation set (paddr) collect folios of the given region by getting the folios of region-internal addresses. Then, those functions apply the action to the collected folios at once. The collection starts from the region start address and advances the address by the size of the folio of the address until it goes out of the region. If the start address is in the middle of a large folio, and if the next folios are small, some of the next folios could be skipped. Fix the issue by advancing the address to exactly the start address of the next folio.
The user impact is that DAMOS action is applied to less than expected amount of memory. Given the best effort nature of DAMON, it is no big problem, but it is clearly a bug that is better to be fixed.
Quoted 7 lines
The issue was discovered [1] by Sashiko.
[1] https://lore.kernel.org/[email protected]
Fixes 3a06696305e7 ("mm/damon/ops: have damon_get_folio return folio even for tail pages")Cc <[email protected]> # 6.15.xSigned-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
SJ Park
maintainerPATCH 3/7 mm/damon/vaddr: respect folio end for DAMOS_STAT
In reply to SJ ParkFor applying DAMOS_STAT action to a region, DAMON virtual address space operation set (vaddr) calls walk_page_range[_vma]() for the region. The pmd walk entry function, namely damon_va_stat_pmd_entry(), applies DAMOS filters to folios of addresses of the region in the pmd. It starts from the walking address and advances the address by the size of the folio of the address until it goes out of the pmd or the region.
Let's suppose it is for the first pmd of the region, and the region start address is in the middle of a large folio. Also, the next folios are small. Then, some of the next folios could be skipped. Fix the issue by advancing the address to exactly the start address of the next folio.
The user impact is that the DAMOS_STAT-based page level monitoring results become inaccurate. Since the page level monitoring is supposed to provide relatively high precision, this is definitely a problem. It is arguably not critical since it is only monitoring quality degradation.
The issue was discovered [1] by Sashiko.
[1] https://lore.kernel.org/[email protected]
--- mm/damon/vaddr.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
mm/damon/vaddr.c +4 -1
@@ -831,6 +831,8 @@ static int damos_va_stat_pmd_entry(pmd_t *pmd, unsigned long addr,return 0 ;for (; addr < next; pte += nr, addr += nr *PAGE_SIZE ) { +unsigned long page_idx; + nr =1 ; ptent =ptep_get (pte);
@@ -844,7 +846,8 @@ static int damos_va_stat_pmd_entry(pmd_t *pmd, unsigned long addr,if (!damos_va_filter_out (s, folio, vma, addr, pte,NULL )) *sz_filter_passed +=folio_size (folio); - nr =folio_nr_pages (folio); + page_idx =folio_page_idx (folio,pte_page (ptent)); + nr =folio_nr_pages (folio) - page_idx; s->last_applied = folio; }pte_unmap_unlock (start_pte, ptl);
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 3/7] mm/damon/vaddr: respect folio end for DAMOS_STAT
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 19 lines
For applying
DAMOS_STATaction to a region, DAMON virtual address space operation set (vaddr) calls walk_page_range[_vma]() for the region. The pmd walk entry function, namelydamon_va_stat_pmd_entry(), applies DAMOS filters to folios of addresses of the region in the pmd. It starts from the walking address and advances the address by the size of the folio of the address until it goes out of the pmd or the region.Let's suppose it is for the first pmd of the region, and the region start address is in the middle of a large folio. Also, the next folios are small. Then, some of the next folios could be skipped. Fix the issue by advancing the address to exactly the start address of the next folio.
The user impact is that the DAMOS_STAT-based page level monitoring results become inaccurate. Since the page level monitoring is supposed to provide relatively high precision, this is definitely a problem. It is arguably not critical since it is only monitoring quality degradation.
Quoted 7 lines
The issue was discovered [1] by Sashiko.
[1] https://lore.kernel.org/[email protected]
Fixes 63f39737d1e3 ("mm/damon/vaddr: support stat-purpose DAMOS filters")Cc <[email protected]> # 6.18.xSigned-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=3
SJ Park
maintainerPATCH 4/7 mm/damon/vaddr: respect folio end for DAMOS_MIGRATE_{HOT,COLD}
In reply to SJ ParkFor applying DAMOS_MIGRATE_{HOT,COLD} actions to a region, DAMON virtual address space operation set (vaddr) calls walk_page_range[_vma]() for the region. The pmd walk entry function, namely damon_va_migrate_pmd_entry(), collects folios of addresses of the region in the pmd. It starts from the walking address and advances the address by the size of the folio of the address until it goes out of the pmd or the region.
Let's suppose it is for the first pmd of the region, and the region start address is in the middle of a large folio. Also, the next folios are small. Then, some of the next folios could be skipped. Fix the issue by advancing the address to exactly the start address of the next folio.
The user impact is that DAMOS action is applied to less than expected amount of memory. Given the best effort nature of DAMON, it is no big problem, but it is clearly a bug that is better to be fixed.
The issue was discovered [1] by Sashiko.
[1] https://lore.kernel.org/[email protected]
--- mm/damon/vaddr.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
mm/damon/vaddr.c +4 -1
@@ -669,6 +669,8 @@ static int damos_va_migrate_pmd_entry(pmd_t *pmd, unsigned long addr,return 0 ;for (; addr < next; pte += nr, addr += nr *PAGE_SIZE ) { +unsigned long page_idx; + nr =1 ; ptent =ptep_get (pte);
@@ -681,7 +683,8 @@ static int damos_va_migrate_pmd_entry(pmd_t *pmd, unsigned long addr,continue ;damos_va_migrate_dests_add (folio, walk->vma, addr, dests, migration_lists); - nr =folio_nr_pages (folio); + page_idx =folio_page_idx (folio,pte_page (ptent)); + nr =folio_nr_pages (folio) - page_idx; }pte_unmap_unlock (start_pte, ptl);return 0 ;
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 4/7] mm/damon/vaddr: respect folio end for DAMOS_MIGRATE_{HOT,COLD}
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 18 lines
For applying DAMOS_MIGRATE_{HOT,COLD} actions to a region, DAMON virtual address space operation set (vaddr) calls walk_page_range[_vma]() for the region. The pmd walk entry function, namely
damon_va_migrate_pmd_entry(), collects folios of addresses of the region in the pmd. It starts from the walking address and advances the address by the size of the folio of the address until it goes out of the pmd or the region.Let's suppose it is for the first pmd of the region, and the region start address is in the middle of a large folio. Also, the next folios are small. Then, some of the next folios could be skipped. Fix the issue by advancing the address to exactly the start address of the next folio.
The user impact is that DAMOS action is applied to less than expected amount of memory. Given the best effort nature of DAMON, it is no big problem, but it is clearly a bug that is better to be fixed.
Quoted 7 lines
The issue was discovered [1] by Sashiko.
[1] https://lore.kernel.org/[email protected]
Fixes 09efc56a3b1c ("mm/damon/vaddr: consistently use only pmd_entry for damos_migrate")Cc <[email protected]> # 6.19.xSigned-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=4
SJ Park
maintainerPATCH 5/7 mm/damon/core: handle extreme memory state in damon_get_node_mem_bp()
In reply to SJ ParkIn an extreme and unlikely situation, si_meminfo_node() might let the caller show zero total ram. That could cause a divide by zero in damon_get_node_mem_bp(). It could also show free memory larger than the total memory. This could cause underflow and make DAMOS temporarily make unexpected behavior. Thanks to safety guards in the auto-tuning feedback loop, that should not be a real problem, though. Fix the problems by respectively returning 100% and 0% for used and free memory queries in the corner cases.
The issue was discovered [1] by Sashiko.
[1] https://lore.kernel.org/[email protected]
--- mm/damon/core.c | 7 +++++++ 1 file changed, 7 insertions(+)
mm/damon/core.c +7 -0
@@ -2807,6 +2807,13 @@ static __kernel_ulong_t damos_get_node_mem_bp( }si_meminfo_node (&i, goal->nid); +if (!i.totalram || i.totalram < i.freeram) { +if (goal->metric ==DAMOS_QUOTA_NODE_MEM_USED_BP ) +return 10000 ; +else /* DAMOS_QUOTA_NODE_MEM_FREE_BP */ +return 0 ; + } +if (goal->metric ==DAMOS_QUOTA_NODE_MEM_USED_BP ) numerator = i.totalram - i.freeram;else /* DAMOS_QUOTA_NODE_MEM_FREE_BP */
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 5/7] mm/damon/core: handle extreme memory state in damon_get_node_mem_bp()
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 9 lines
In an extreme and unlikely situation,
si_meminfo_node()might let the caller show zero total ram. That could cause a divide by zero indamon_get_node_mem_bp(). It could also show free memory larger than the total memory. This could cause underflow and make DAMOS temporarily make unexpected behavior. Thanks to safety guards in the auto-tuning feedback loop, that should not be a real problem, though. Fix the problems by respectively returning 100% and 0% for used and free memory queries in the corner cases.
Quoted 7 lines
The issue was discovered [1] by Sashiko.
[1] https://lore.kernel.org/[email protected]
Fixes 0e1c773b501f ("mm/damon/core: introduce damos quota goal metrics for memory node utilization")Cc <[email protected]> # 6.16.xSigned-off-by SJ Park <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=5
SJ Park
maintainerPATCH 6/7 mm/damon/core: handle extreme memory state in get_node_memcg_used_bp()
In reply to SJ ParkIn extreme unlikely situations, total memory might be zero. In less extreme but still very unlikely situations, lruvec_page_state() calls might let the caller show used memory larger than total memory. In the two cases, damos_get_node_memcg_used_bp() could cause division by zero, or return underflowed value, respectively. Handle the cases by respectively returning 100% and 0% for used and free memory queries in the corner cases.
This issue was discovered [1] by Sashiko.
[1] https://lore.kernel.org/[email protected]
--- mm/damon/core.c | 6 ++++++ 1 file changed, 6 insertions(+)
mm/damon/core.c +6 -0
@@ -2854,6 +2854,12 @@ static unsigned long damos_get_node_memcg_used_bp(mem_cgroup_put (memcg);si_meminfo_node (&i, goal->nid); +if (!i.totalram || i.totalram < used_pages) { +if (goal->metric ==DAMOS_QUOTA_NODE_MEMCG_USED_BP ) +return 10000 ; +else /* DAMOS_QUOTA_NODE_MEMCG_FREE_BP */ +return 0 ; + }if (goal->metric ==DAMOS_QUOTA_NODE_MEMCG_USED_BP ) numerator = used_pages;else /* DAMOS_QUOTA_NODE_MEMCG_FREE_BP */
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 6/7] mm/damon/core: handle extreme memory state in get_node_memcg_used_bp()
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] 32-bit integer overflow in mult_frac() leads to wildly inaccurate quota calculations on architectures with 32-bit unsigned longs. --
commit f507259fcccb65ad40eabec53de3e020582667f6
Author: SJ Park <[email protected]>
mm/damon/core: handle extreme memory state in get_node_memcg_used_bp()
In extreme unlikely situations, total memory might be zero. In less extreme but still very unlikely situations, lruvec_page_state() calls might let the caller show used memory larger than total memory. In the two cases, damos_get_node_memcg_used_bp() could cause division by zero, or return underflowed value, respectively. Handle the cases by respectively returning 100% and 0% for used and free memory queries in the corner cases.
Quoted 17 lines
mm/damon/core.c +6
-0@@ -2853,6 +2853,12 @@ static unsigned long damos_get_node_memcg_used_bp(mem_cgroup_put (memcg);si_meminfo_node (&i, goal->nid); +if (!i.totalram || i.totalram < used_pages) { +if (goal->metric ==DAMOS_QUOTA_NODE_MEMCG_USED_BP ) +return 10000 ; +else /* DAMOS_QUOTA_NODE_MEMCG_FREE_BP */ +return 0 ; + }if (goal->metric ==DAMOS_QUOTA_NODE_MEMCG_USED_BP ) numerator = used_pages;else /* DAMOS_QUOTA_NODE_MEMCG_FREE_BP */
mm/damon/core.c
Quoted 2 lines
mm/damon/core.c +0
-0numerator = i.totalram - used_pages;return mult_frac (numerator,10000 , i.totalram);
[Severity: High]
This is a pre-existing issue, but does this calculation overflow on 32-bit architectures?
The mult_frac(numerator, 10000, i.totalram) macro computes numerator * 10000 / i.totalram when the numerator is smaller than the totalram. Because numerator is an unsigned long, this multiplication is performed using 32-bit arithmetic on 32-bit architectures.
If the numerator exceeds roughly 429,496 pages (about 1.7 gigabytes of memory), multiplying it by 10,000 exceeds the 32-bit integer maximum of roughly 4.29 billion. This wraparound yields a massively inaccurate fraction.
This same overflow appears to also affect damos_get_node_mem_bp() and damos_get_in_active_mem_bp().
Could numerator be cast to a 64-bit type before multiplication to prevent this issue on larger memory systems with 32-bit kernels?
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=6
SJ Park
maintainerPATCH 7/7 mm/damon/core: handle extreme memory state in get_in_active_mem_bp()
In reply to SJ Parkdamos_get_in_active_mem_bp() uses the sum of the active and inactive memory amount as a denominator. In an extreme and unlikely environment, active and inactive memory might be zero. In this case, hence, it results in a divide by zero problem. Avoid it by changing the denominator to one if it is zero, before it is being used.
The issue was discovered [1] by Sashiko.
[1] https://lore.kernel.org/[email protected]
--- mm/damon/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
mm/damon/core.c +1 -1
@@ -3006,7 +3006,7 @@ static unsigned int damos_get_in_active_mem_bp(bool active_ratio)global_node_page_state (NR_LRU_BASE +LRU_ACTIVE_FILE ); inactive =global_node_page_state (NR_LRU_BASE +LRU_INACTIVE_ANON ) +global_node_page_state (NR_LRU_BASE +LRU_INACTIVE_FILE ); - total = active + inactive; + total =max (active + inactive,1 );if (active_ratio)return mult_frac (active,10000 , total);return mult_frac (inactive,10000 , total);
Signature · 1 line
2.47.3
[email protected]
AI reviewRe: [PATCH 7/7] mm/damon/core: handle extreme memory state in get_in_active_mem_bp()
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] 32-bit integer overflow in mult_frac() macro when calculating memory ratio on 32-bit systems, leading to completely incorrect DAMOS quota metrics. --
commit b2f8512e8018294c2ac5082c2964a0519b9242e8
Author: SJ Park <[email protected]>
mm/damon/core: handle extreme memory state in get_in_active_mem_bp()
damos_get_in_active_mem_bp() uses the sum of the active and inactive memory amount as a denominator. In an extreme and unlikely environment, active and inactive memory might be zero. In this case, hence, it results in a divide by zero problem. Avoid it by changing the denominator to one if it is zero, before it is being used.
[1] https://lore.kernel.org/[email protected]
mm/damon/core.c static unsigned int damos_get_in_active_mem_bp(bool active_ratio) · line 3010
Quoted 12 lines
mm/damon/core.c +1
-1@@ -3005,7 +3005,7 @@ static unsigned int damos_get_in_active_mem_bp(bool active_ratio)global_node_page_state (NR_LRU_BASE +LRU_ACTIVE_FILE ); inactive =global_node_page_state (NR_LRU_BASE +LRU_INACTIVE_ANON ) +global_node_page_state (NR_LRU_BASE +LRU_INACTIVE_FILE ); - total = active + inactive; + total =max (active + inactive,1 );if (active_ratio)return mult_frac (active,10000 , total);
[Severity: High]
This is a pre-existing issue, but does this calculation overflow on 32-bit systems?
If the active memory size exceeds 429,496 pages (about 1.75 GB), multiplying the 32-bit unsigned long active variable by 10,000 inside the mult_frac() macro will overflow ULONG_MAX.
This can result in effectively random DAMON quota metrics on 32-bit systems, leading DAMON to misinterpret memory states and potentially over-reclaim or under-reclaim memory.
A similar overflow can also happen in damos_quota_score():
mm/damon/core.c:damos_quota_score() {
...
return mult_frac(goal->current_value, 10000, goal->target_value);
}Here, goal->current_value multiplied by 10,000 overflows for large values, such as when microseconds of stall time exceed 430ms.
Quoted 1 line
mm/damon/core.c +0
-0return mult_frac (inactive,10000 , total);
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=7
SJ Park
maintainerI sent this series by a mistake. This has wrong cover letter. I will resent. Sorry for the noise.
Thanks,
SJ
[...]