DAMON development mailing list
 help / color / mirror / Atom feed
* [RFC PATCH v1.2 0/8] mm/damon: fix DAMOS bugs in core, paddr and vaddr
@ 2026-08-31 14:02 SJ Park
  2026-08-31 14:02 ` [RFC PATCH v1.2 1/8] mm/damon/core: skip applying scheme if region split for quota fails SJ Park
                   ` (8 more replies)
  0 siblings, 9 replies; 20+ messages in thread
From: SJ Park @ 2026-08-31 14:02 UTC (permalink / raw)
  Cc: SJ Park, stable, Andrew Morton, Usama Arif, Yueyang Pan, damon,
	linux-kernel, linux-mm

Fix misc bugs of DAMOS.  Patch 1 makes DAMOS less stress memory
allocator under extreme situation.  Patches 2 and 3 fix wrong folios
walking in DAMON_PADDR.  Patches 4 and 5 fix wrong folios walking in
DAMON_VADDR.  Patches 6-8 handle extreme and unlikely memory situations
that can cause divide by zero and underflow.

All bugs are discovered by Sashiko.

The bugs are not very critical, but better to be merged sooner than
later.  Since mm.git is closed for urgent changes, I aim for 7.3-rcX.  I
will drop the RFC tag after 7.3-rc1.

Changes from RFC v1.1
- RFC v1.1: https://lore.kernel.org/20260802162631.90304-1-sj@kernel.org
- Fix wrong commit message (patch 7).
- Return 100% and 0% for used and free memory (patches 7 and 8).
- Drop incomplete last_psi_total initialization (patch 2).
- Rebase to latest mm-new.
Changes from RFC
- RFC: https://lore.kernel.org/20260801173554.94710-1-sj@kernel.org
- Use cached pte content (patch 5 and 6).
- Handle totalram < freeram case (patch 7).
- Fix wrong function name in commit message (patch 9).

SJ Park (8):
  mm/damon/core: skip applying scheme if region split for quota fails
  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  | 18 ++++++++++++++++--
 mm/damon/paddr.c |  8 ++++----
 mm/damon/vaddr.c | 10 ++++++++--
 3 files changed, 28 insertions(+), 8 deletions(-)


base-commit: 59a8d789d9478797978640a7a640b086ad400b37
-- 
2.47.3

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [RFC PATCH v1.2 1/8] mm/damon/core: skip applying scheme if region split for quota fails
  2026-08-31 14:02 [RFC PATCH v1.2 0/8] mm/damon: fix DAMOS bugs in core, paddr and vaddr SJ Park
@ 2026-08-31 14:02 ` SJ Park
  2026-08-31 17:45   ` sashiko-bot
  2026-08-31 14:02 ` [RFC PATCH v1.2 2/8] mm/damon/paddr: respect folio end for DAMOS_STAT SJ Park
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 20+ messages in thread
From: SJ Park @ 2026-08-31 14:02 UTC (permalink / raw)
  Cc: SJ Park, stable, Andrew Morton, damon, linux-kernel, linux-mm

damos_apply_scheme() splits a region and apply the action to the
subregion if it is needed for not violating the quota.  The split
operation (damon_split_region_at()) could fail for allocation failure.
In the case, the quota could be violated.  From the user's perspective,
DAMOS becomes more aggressive than expected under the extreme situation.
Handle the failure.

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/20260718171523.87547-1-sj@kernel.org

Fixes: 2b8a248d5873 ("mm/damon/schemes: implement size quota for schemes application speed control")
Cc: <stable@vger.kernel.org> # 5.16.x
Signed-off-by: SJ Park <sj@kernel.org>
---
 mm/damon/core.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/mm/damon/core.c b/mm/damon/core.c
index 644daf5a16560..e2900d0c984c9 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -2613,7 +2613,8 @@ static void damos_apply_scheme(struct damon_ctx *c, struct damon_target *t,
 					c->min_region_sz);
 			if (!sz)
 				goto update_stat;
-			damon_split_region_at(t, r, sz);
+			if (damon_split_region_at(t, r, sz))
+				goto update_stat;
 		}
 		if (damos_core_filter_out(c, t, r, s))
 			return;
-- 
2.47.3

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [RFC PATCH v1.2 2/8] mm/damon/paddr: respect folio end for DAMOS_STAT
  2026-08-31 14:02 [RFC PATCH v1.2 0/8] mm/damon: fix DAMOS bugs in core, paddr and vaddr SJ Park
  2026-08-31 14:02 ` [RFC PATCH v1.2 1/8] mm/damon/core: skip applying scheme if region split for quota fails SJ Park
@ 2026-08-31 14:02 ` SJ Park
  2026-08-31 17:54   ` sashiko-bot
  2026-08-31 14:02 ` [RFC PATCH v1.2 3/8] mm/damon/paddr: respect folio end for DAMOS actions except STAT SJ Park
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 20+ messages in thread
From: SJ Park @ 2026-08-31 14:02 UTC (permalink / raw)
  Cc: SJ Park, stable, Andrew Morton, Usama Arif, damon, linux-kernel,
	linux-mm

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.

Fixes: bdbe1d7bc325 ("mm/damon/paddr: increment pa_stat damon address range by folio size")
Cc: <stable@vger.kernel.org> # 6.14.x
Signed-off-by: SJ Park <sj@kernel.org>
---
 mm/damon/paddr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mm/damon/paddr.c b/mm/damon/paddr.c
index 5c6c3a597fd0b..2ab7b3842701e 100644
--- a/mm/damon/paddr.c
+++ b/mm/damon/paddr.c
@@ -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;
-- 
2.47.3

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [RFC PATCH v1.2 3/8] mm/damon/paddr: respect folio end for DAMOS actions except STAT
  2026-08-31 14:02 [RFC PATCH v1.2 0/8] mm/damon: fix DAMOS bugs in core, paddr and vaddr SJ Park
  2026-08-31 14:02 ` [RFC PATCH v1.2 1/8] mm/damon/core: skip applying scheme if region split for quota fails SJ Park
  2026-08-31 14:02 ` [RFC PATCH v1.2 2/8] mm/damon/paddr: respect folio end for DAMOS_STAT SJ Park
@ 2026-08-31 14:02 ` SJ Park
  2026-08-31 18:06   ` sashiko-bot
  2026-08-31 14:02 ` [RFC PATCH v1.2 4/8] mm/damon/vaddr: respect folio end for DAMOS_STAT SJ Park
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 20+ messages in thread
From: SJ Park @ 2026-08-31 14:02 UTC (permalink / raw)
  Cc: SJ Park, stable, Andrew Morton, Usama Arif, damon, linux-kernel,
	linux-mm

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.

The issue was discovered [1] by Sashiko.

[1] https://lore.kernel.org/20260517234112.89245-1-sj@kernel.org

Fixes: 3a06696305e7 ("mm/damon/ops: have damon_get_folio return folio even for tail pages")
Cc: <stable@vger.kernel.org> # 6.15.x
Signed-off-by: SJ Park <sj@kernel.org>
---
 mm/damon/paddr.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/mm/damon/paddr.c b/mm/damon/paddr.c
index 2ab7b3842701e..9ddd1ec8202b7 100644
--- a/mm/damon/paddr.c
+++ b/mm/damon/paddr.c
@@ -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);
-- 
2.47.3

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [RFC PATCH v1.2 4/8] mm/damon/vaddr: respect folio end for DAMOS_STAT
  2026-08-31 14:02 [RFC PATCH v1.2 0/8] mm/damon: fix DAMOS bugs in core, paddr and vaddr SJ Park
                   ` (2 preceding siblings ...)
  2026-08-31 14:02 ` [RFC PATCH v1.2 3/8] mm/damon/paddr: respect folio end for DAMOS actions except STAT SJ Park
@ 2026-08-31 14:02 ` SJ Park
  2026-08-31 18:14   ` sashiko-bot
  2026-08-31 14:02 ` [RFC PATCH v1.2 5/8] mm/damon/vaddr: respect folio end for DAMOS_MIGRATE_{HOT,COLD} SJ Park
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 20+ messages in thread
From: SJ Park @ 2026-08-31 14:02 UTC (permalink / raw)
  Cc: SJ Park, stable, Andrew Morton, Yueyang Pan, damon, linux-kernel,
	linux-mm

For 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/20260514015053.149396-1-sj@kernel.org

Fixes: 63f39737d1e3 ("mm/damon/vaddr: support stat-purpose DAMOS filters")
Cc: <stable@vger.kernel.org> # 6.18.x
Signed-off-by: SJ Park <sj@kernel.org>
---
 mm/damon/vaddr.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/mm/damon/vaddr.c b/mm/damon/vaddr.c
index 0648400b2d65b..4b0b5edf67952 100644
--- a/mm/damon/vaddr.c
+++ b/mm/damon/vaddr.c
@@ -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);
-- 
2.47.3

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [RFC PATCH v1.2 5/8] mm/damon/vaddr: respect folio end for DAMOS_MIGRATE_{HOT,COLD}
  2026-08-31 14:02 [RFC PATCH v1.2 0/8] mm/damon: fix DAMOS bugs in core, paddr and vaddr SJ Park
                   ` (3 preceding siblings ...)
  2026-08-31 14:02 ` [RFC PATCH v1.2 4/8] mm/damon/vaddr: respect folio end for DAMOS_STAT SJ Park
@ 2026-08-31 14:02 ` SJ Park
  2026-08-31 18:23   ` sashiko-bot
  2026-08-31 14:02 ` [RFC PATCH v1.2 6/8] mm/damon/core: handle extreme memory state in damon_get_node_mem_bp() SJ Park
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 20+ messages in thread
From: SJ Park @ 2026-08-31 14:02 UTC (permalink / raw)
  Cc: SJ Park, stable, Andrew Morton, damon, linux-kernel, linux-mm

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.

The issue was discovered [1] by Sashiko.

[1] https://lore.kernel.org/20260514015053.149396-1-sj@kernel.org

Fixes: 09efc56a3b1c ("mm/damon/vaddr: consistently use only pmd_entry for damos_migrate")
Cc: <stable@vger.kernel.org> # 6.19.x
Signed-off-by: SJ Park <sj@kernel.org>
---
 mm/damon/vaddr.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/mm/damon/vaddr.c b/mm/damon/vaddr.c
index 4b0b5edf67952..c8c32b2ae0402 100644
--- a/mm/damon/vaddr.c
+++ b/mm/damon/vaddr.c
@@ -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;
-- 
2.47.3

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [RFC PATCH v1.2 6/8] mm/damon/core: handle extreme memory state in damon_get_node_mem_bp()
  2026-08-31 14:02 [RFC PATCH v1.2 0/8] mm/damon: fix DAMOS bugs in core, paddr and vaddr SJ Park
                   ` (4 preceding siblings ...)
  2026-08-31 14:02 ` [RFC PATCH v1.2 5/8] mm/damon/vaddr: respect folio end for DAMOS_MIGRATE_{HOT,COLD} SJ Park
@ 2026-08-31 14:02 ` SJ Park
  2026-08-31 18:29   ` sashiko-bot
  2026-08-31 14:02 ` [RFC PATCH v1.2 7/8] mm/damon/core: handle extreme memory state in get_node_memcg_used_bp() SJ Park
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 20+ messages in thread
From: SJ Park @ 2026-08-31 14:02 UTC (permalink / raw)
  Cc: SJ Park, stable, Andrew Morton, damon, linux-kernel, linux-mm

In 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/20260328133216.9697-1-sj@kernel.org

Fixes: 0e1c773b501f ("mm/damon/core: introduce damos quota goal metrics for memory node utilization")
Cc: <stable@vger.kernel.org> # 6.16.x
Signed-off-by: SJ Park <sj@kernel.org>
---
 mm/damon/core.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/mm/damon/core.c b/mm/damon/core.c
index e2900d0c984c9..75d71ac09515e 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -2816,6 +2816,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 */
-- 
2.47.3

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [RFC PATCH v1.2 7/8] mm/damon/core: handle extreme memory state in get_node_memcg_used_bp()
  2026-08-31 14:02 [RFC PATCH v1.2 0/8] mm/damon: fix DAMOS bugs in core, paddr and vaddr SJ Park
                   ` (5 preceding siblings ...)
  2026-08-31 14:02 ` [RFC PATCH v1.2 6/8] mm/damon/core: handle extreme memory state in damon_get_node_mem_bp() SJ Park
@ 2026-08-31 14:02 ` SJ Park
  2026-08-31 18:41   ` sashiko-bot
  2026-08-31 14:02 ` [RFC PATCH v1.2 8/8] mm/damon/core: handle extreme memory state in get_in_active_mem_bp() SJ Park
  2026-09-01  0:50 ` [RFC PATCH v1.2 0/8] mm/damon: fix DAMOS bugs in core, paddr and vaddr SJ Park
  8 siblings, 1 reply; 20+ messages in thread
From: SJ Park @ 2026-08-31 14:02 UTC (permalink / raw)
  Cc: SJ Park, stable, Andrew Morton, damon, linux-kernel, linux-mm

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.

This issue was discovered [1] by Sashiko.

[1] https://lore.kernel.org/20260329154813.47382-1-sj@kernel.org

Fixes: b74a120bcf50 ("mm/damon/core: implement DAMOS_QUOTA_NODE_MEMCG_USED_BP")
Cc: <stable@vger.kernel.org> # 6.19.x
Signed-off-by: SJ Park <sj@kernel.org>
---
 mm/damon/core.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/mm/damon/core.c b/mm/damon/core.c
index 75d71ac09515e..3779a04753061 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -2863,6 +2863,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 */
-- 
2.47.3

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [RFC PATCH v1.2 8/8] mm/damon/core: handle extreme memory state in get_in_active_mem_bp()
  2026-08-31 14:02 [RFC PATCH v1.2 0/8] mm/damon: fix DAMOS bugs in core, paddr and vaddr SJ Park
                   ` (6 preceding siblings ...)
  2026-08-31 14:02 ` [RFC PATCH v1.2 7/8] mm/damon/core: handle extreme memory state in get_node_memcg_used_bp() SJ Park
@ 2026-08-31 14:02 ` SJ Park
  2026-08-31 18:49   ` sashiko-bot
  2026-09-01  0:50 ` [RFC PATCH v1.2 0/8] mm/damon: fix DAMOS bugs in core, paddr and vaddr SJ Park
  8 siblings, 1 reply; 20+ messages in thread
From: SJ Park @ 2026-08-31 14:02 UTC (permalink / raw)
  Cc: SJ Park, stable, Andrew Morton, damon, linux-kernel, linux-mm

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.

The issue was discovered [1] by Sashiko.

[1] https://lore.kernel.org/20260721034756.147011-1-sj@kernel.org

Fixes: 4835e2871321 ("mm/damon/core: introduce [in]active memory ratio damos quota goal metric")
Cc: <stable@vger.kernel.org> # 7.0.x
Signed-off-by: SJ Park <sj@kernel.org>
---
 mm/damon/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mm/damon/core.c b/mm/damon/core.c
index 3779a04753061..f8dddbff74a77 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -3015,7 +3015,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);
-- 
2.47.3

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH v1.2 1/8] mm/damon/core: skip applying scheme if region split for quota fails
  2026-08-31 14:02 ` [RFC PATCH v1.2 1/8] mm/damon/core: skip applying scheme if region split for quota fails SJ Park
@ 2026-08-31 17:45   ` sashiko-bot
  0 siblings, 0 replies; 20+ messages in thread
From: sashiko-bot @ 2026-08-31 17:45 UTC (permalink / raw)
  To: SJ Park; +Cc: damon

> damos_apply_scheme() splits a region and apply the action to the
> subregion if it is needed for not violating the quota.  The split
> operation (damon_split_region_at()) could fail for allocation failure.
> In the case, the quota could be violated.  From the user's perspective,
> DAMOS becomes more aggressive than expected under the extreme situation.
> Handle the failure.
> 
> 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/20260718171523.87547-1-sj@kernel.org
> 
> Fixes: 2b8a248d5873 ("mm/damon/schemes: implement size quota for schemes application speed control")
> Cc: <stable@vger.kernel.org> # 5.16.x
> Signed-off-by: SJ Park <sj@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260831140254.72004-1-sj@kernel.org?part=1


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH v1.2 2/8] mm/damon/paddr: respect folio end for DAMOS_STAT
  2026-08-31 14:02 ` [RFC PATCH v1.2 2/8] mm/damon/paddr: respect folio end for DAMOS_STAT SJ Park
@ 2026-08-31 17:54   ` sashiko-bot
  0 siblings, 0 replies; 20+ messages in thread
From: sashiko-bot @ 2026-08-31 17:54 UTC (permalink / raw)
  To: SJ Park; +Cc: damon

> 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.
> 
> Fixes: bdbe1d7bc325 ("mm/damon/paddr: increment pa_stat damon address range by folio size")
> Cc: <stable@vger.kernel.org> # 6.14.x
> Signed-off-by: SJ Park <sj@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260831140254.72004-1-sj@kernel.org?part=2


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH v1.2 3/8] mm/damon/paddr: respect folio end for DAMOS actions except STAT
  2026-08-31 14:02 ` [RFC PATCH v1.2 3/8] mm/damon/paddr: respect folio end for DAMOS actions except STAT SJ Park
@ 2026-08-31 18:06   ` sashiko-bot
  0 siblings, 0 replies; 20+ messages in thread
From: sashiko-bot @ 2026-08-31 18:06 UTC (permalink / raw)
  To: SJ Park; +Cc: damon

> 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.
> 
> The issue was discovered [1] by Sashiko.
> 
> [1] https://lore.kernel.org/20260517234112.89245-1-sj@kernel.org
> 
> Fixes: 3a06696305e7 ("mm/damon/ops: have damon_get_folio return folio even for tail pages")
> Cc: <stable@vger.kernel.org> # 6.15.x
> Signed-off-by: SJ Park <sj@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260831140254.72004-1-sj@kernel.org?part=3


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH v1.2 4/8] mm/damon/vaddr: respect folio end for DAMOS_STAT
  2026-08-31 14:02 ` [RFC PATCH v1.2 4/8] mm/damon/vaddr: respect folio end for DAMOS_STAT SJ Park
@ 2026-08-31 18:14   ` sashiko-bot
  0 siblings, 0 replies; 20+ messages in thread
From: sashiko-bot @ 2026-08-31 18:14 UTC (permalink / raw)
  To: SJ Park; +Cc: damon

> For 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/20260514015053.149396-1-sj@kernel.org
> 
> Fixes: 63f39737d1e3 ("mm/damon/vaddr: support stat-purpose DAMOS filters")
> Cc: <stable@vger.kernel.org> # 6.18.x
> Signed-off-by: SJ Park <sj@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260831140254.72004-1-sj@kernel.org?part=4


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH v1.2 5/8] mm/damon/vaddr: respect folio end for DAMOS_MIGRATE_{HOT,COLD}
  2026-08-31 14:02 ` [RFC PATCH v1.2 5/8] mm/damon/vaddr: respect folio end for DAMOS_MIGRATE_{HOT,COLD} SJ Park
@ 2026-08-31 18:23   ` sashiko-bot
  0 siblings, 0 replies; 20+ messages in thread
From: sashiko-bot @ 2026-08-31 18:23 UTC (permalink / raw)
  To: SJ Park; +Cc: damon

> 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.
> 
> The issue was discovered [1] by Sashiko.
> 
> [1] https://lore.kernel.org/20260514015053.149396-1-sj@kernel.org
> 
> Fixes: 09efc56a3b1c ("mm/damon/vaddr: consistently use only pmd_entry for damos_migrate")
> Cc: <stable@vger.kernel.org> # 6.19.x
> Signed-off-by: SJ Park <sj@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260831140254.72004-1-sj@kernel.org?part=5


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH v1.2 6/8] mm/damon/core: handle extreme memory state in damon_get_node_mem_bp()
  2026-08-31 14:02 ` [RFC PATCH v1.2 6/8] mm/damon/core: handle extreme memory state in damon_get_node_mem_bp() SJ Park
@ 2026-08-31 18:29   ` sashiko-bot
  0 siblings, 0 replies; 20+ messages in thread
From: sashiko-bot @ 2026-08-31 18:29 UTC (permalink / raw)
  To: SJ Park; +Cc: damon

> In 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/20260328133216.9697-1-sj@kernel.org
> 
> Fixes: 0e1c773b501f ("mm/damon/core: introduce damos quota goal metrics for memory node utilization")
> Cc: <stable@vger.kernel.org> # 6.16.x
> Signed-off-by: SJ Park <sj@kernel.org>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260831140254.72004-1-sj@kernel.org?part=6


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH v1.2 7/8] mm/damon/core: handle extreme memory state in get_node_memcg_used_bp()
  2026-08-31 14:02 ` [RFC PATCH v1.2 7/8] mm/damon/core: handle extreme memory state in get_node_memcg_used_bp() SJ Park
@ 2026-08-31 18:41   ` sashiko-bot
  2026-09-01  0:36     ` SJ Park
  0 siblings, 1 reply; 20+ messages in thread
From: sashiko-bot @ 2026-08-31 18:41 UTC (permalink / raw)
  To: SJ Park; +Cc: damon

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] Incorrect fallback values in `damos_get_node_mem_bp` when `i.freeram` exceeds `i.totalram`.
--

commit a048cc23be81d8e450e9ee2ce22eb0a86b0cb1ba
Author: SJ Park <sj@kernel.org>

mm/damon/core: handle extreme memory state in get_node_memcg_used_bp()

This commit handles extreme corner cases where total memory is zero or
reported used memory exceeds total memory. It updates
damos_get_node_memcg_used_bp() to prevent division by zero or underflows by
clamping the results to 100% or 0% appropriately.

Link: https://lore.kernel.org/20260329154813.47382-1-sj@kernel.org

> diff --git a/mm/damon/core.c b/mm/damon/core.c
> index 75d71ac09515e..3779a04753061 100644
> --- a/mm/damon/core.c
> +++ b/mm/damon/core.c
> @@ -2863,6 +2863,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;
> +	}

[Severity: High]
This is a pre-existing issue, but I noticed a similar block of code just
above this in damos_get_node_mem_bp() that appears to handle the fallback
logic incorrectly:

mm/damon/core.c: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;
    }
    ...
}

When i.freeram exceeds i.totalram (which can happen due to per-CPU stat drift
during large frees or memory hot-remove), this logic returns 10000 (100%) for
DAMOS_QUOTA_NODE_MEM_USED_BP and 0 for DAMOS_QUOTA_NODE_MEM_FREE_BP.

Since the node is effectively completely free, shouldn't it return 0 for used
and 10000 for free?

Could this cause DAMON memory reclaim schemes to trigger aggressively on
nodes that are actually completely free, potentially causing performance
regressions?

>  	if (goal->metric == DAMOS_QUOTA_NODE_MEMCG_USED_BP)
>  		numerator = used_pages;
>  	else	/* DAMOS_QUOTA_NODE_MEMCG_FREE_BP */

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260831140254.72004-1-sj@kernel.org?part=7

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH v1.2 8/8] mm/damon/core: handle extreme memory state in get_in_active_mem_bp()
  2026-08-31 14:02 ` [RFC PATCH v1.2 8/8] mm/damon/core: handle extreme memory state in get_in_active_mem_bp() SJ Park
@ 2026-08-31 18:49   ` sashiko-bot
  2026-09-01  0:37     ` SJ Park
  0 siblings, 1 reply; 20+ messages in thread
From: sashiko-bot @ 2026-08-31 18:49 UTC (permalink / raw)
  To: SJ Park; +Cc: damon

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] Silent integer overflow on 32-bit systems in mult_frac() usage across DAMON quota metrics, leading to drastically incorrect memory metrics.
--

commit ba2ca9efc083502fb5555a81a42e9de1ab623b4d
Author: SJ Park <sj@kernel.org>

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.

Link: https://lore.kernel.org/20260721034756.147011-1-sj@kernel.org

> diff --git a/mm/damon/core.c b/mm/damon/core.c
> index 3779a04753061..f8dddbff74a77 100644
> --- a/mm/damon/core.c
> +++ b/mm/damon/core.c
> @@ -3015,7 +3015,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 isn't a bug introduced by this patch, but does the use of mult_frac()
here cause a silent integer overflow on 32-bit systems?

The mult_frac(x, n, d) macro calculates (x / d) * n + (x % d) * n / d. On
32-bit architectures, intermediate multiplications like (x % d) * n are
evaluated as 32-bit unsigned integers if x is an unsigned long. This
silently overflows if the result exceeds ~4.29 billion.

For example, in damos_get_in_active_mem_bp(), active is counted in pages.
If active memory reaches roughly 429,496 pages (about 1.7 GB),
429,496 * 10,000 exceeds the 32-bit maximum of 4,294,967,295 and wraps
around, resulting in drastically incorrect memory metrics.

This same unsigned long overflow seems to be pre-existing in other DAMON
quota metrics in mm/damon/core.c as well:

- damos_get_node_mem_bp(): same issue with node memory.
- damos_get_node_eligible_mem_bp(): node_eligible is cast to unsigned
  long bytes, which can overflow if eligible memory exceeds ~419 KB.
- damos_set_effective_quota(): total_charged_sz is in bytes, which
  overflows when multiplied by 1,000,000 if it exceeds 4294 bytes.
- damos_quota_score(): goal->current_value tracks PSI in microseconds,
  which can easily be millions, overflowing when multiplied by 10,000.

Could these calculations be performed using 64-bit math on 32-bit systems
to prevent runaway aggressive memory reclaim or total failure to reclaim?

>  	return mult_frac(inactive, 10000, total);
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260831140254.72004-1-sj@kernel.org?part=8

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH v1.2 7/8] mm/damon/core: handle extreme memory state in get_node_memcg_used_bp()
  2026-08-31 18:41   ` sashiko-bot
@ 2026-09-01  0:36     ` SJ Park
  0 siblings, 0 replies; 20+ messages in thread
From: SJ Park @ 2026-09-01  0:36 UTC (permalink / raw)
  To: sashiko-bot; +Cc: SJ Park, damon

On Mon, 31 Aug 2026 18:41:52 +0000 sashiko-bot@kernel.org wrote:

> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> 
> Pre-existing issues:
> - [High] Incorrect fallback values in `damos_get_node_mem_bp` when `i.freeram` exceeds `i.totalram`.
> --
> 
> commit a048cc23be81d8e450e9ee2ce22eb0a86b0cb1ba
> Author: SJ Park <sj@kernel.org>
> 
> mm/damon/core: handle extreme memory state in get_node_memcg_used_bp()
> 
> This commit handles extreme corner cases where total memory is zero or
> reported used memory exceeds total memory. It updates
> damos_get_node_memcg_used_bp() to prevent division by zero or underflows by
> clamping the results to 100% or 0% appropriately.
> 
> Link: https://lore.kernel.org/20260329154813.47382-1-sj@kernel.org
> 
> > diff --git a/mm/damon/core.c b/mm/damon/core.c
> > index 75d71ac09515e..3779a04753061 100644
> > --- a/mm/damon/core.c
> > +++ b/mm/damon/core.c
> > @@ -2863,6 +2863,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;
> > +	}
> 
> [Severity: High]
> This is a pre-existing issue, but I noticed a similar block of code just
> above this in damos_get_node_mem_bp() that appears to handle the fallback
> logic incorrectly:
> 
> mm/damon/core.c: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;
>     }
>     ...
> }
> 
> When i.freeram exceeds i.totalram (which can happen due to per-CPU stat drift
> during large frees or memory hot-remove), this logic returns 10000 (100%) for
> DAMOS_QUOTA_NODE_MEM_USED_BP and 0 for DAMOS_QUOTA_NODE_MEM_FREE_BP.
> 
> Since the node is effectively completely free, shouldn't it return 0 for used
> and 10000 for free?

There could be different perspective, but I think that's fine.

> 
> Could this cause DAMON memory reclaim schemes to trigger aggressively on
> nodes that are actually completely free, potentially causing performance
> regressions?

Anyway it is a corner case.  And even in this case, quota will be changed only
up to 2x.  So no real problem in my opinion.  We can revisit if we find a real
issue from this in real usage.

> 
> >  	if (goal->metric == DAMOS_QUOTA_NODE_MEMCG_USED_BP)
> >  		numerator = used_pages;
> >  	else	/* DAMOS_QUOTA_NODE_MEMCG_FREE_BP */
> 
> -- 
> Sashiko AI review · https://sashiko.dev/#/patchset/20260831140254.72004-1-sj@kernel.org?part=7


Thanks,
SJ

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH v1.2 8/8] mm/damon/core: handle extreme memory state in get_in_active_mem_bp()
  2026-08-31 18:49   ` sashiko-bot
@ 2026-09-01  0:37     ` SJ Park
  0 siblings, 0 replies; 20+ messages in thread
From: SJ Park @ 2026-09-01  0:37 UTC (permalink / raw)
  To: sashiko-bot; +Cc: SJ Park, damon

On Mon, 31 Aug 2026 18:49:55 +0000 sashiko-bot@kernel.org wrote:

> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> 
> Pre-existing issues:
> - [High] Silent integer overflow on 32-bit systems in mult_frac() usage across DAMON quota metrics, leading to drastically incorrect memory metrics.
> --
> 
> commit ba2ca9efc083502fb5555a81a42e9de1ab623b4d
> Author: SJ Park <sj@kernel.org>
> 
> 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.
> 
> Link: https://lore.kernel.org/20260721034756.147011-1-sj@kernel.org
> 
> > diff --git a/mm/damon/core.c b/mm/damon/core.c
> > index 3779a04753061..f8dddbff74a77 100644
> > --- a/mm/damon/core.c
> > +++ b/mm/damon/core.c
> > @@ -3015,7 +3015,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 isn't a bug introduced by this patch, but does the use of mult_frac()
> here cause a silent integer overflow on 32-bit systems?
> 
> The mult_frac(x, n, d) macro calculates (x / d) * n + (x % d) * n / d. On
> 32-bit architectures, intermediate multiplications like (x % d) * n are
> evaluated as 32-bit unsigned integers if x is an unsigned long. This
> silently overflows if the result exceeds ~4.29 billion.
> 
> For example, in damos_get_in_active_mem_bp(), active is counted in pages.
> If active memory reaches roughly 429,496 pages (about 1.7 GB),
> 429,496 * 10,000 exceeds the 32-bit maximum of 4,294,967,295 and wraps
> around, resulting in drastically incorrect memory metrics.
> 
> This same unsigned long overflow seems to be pre-existing in other DAMON
> quota metrics in mm/damon/core.c as well:
> 
> - damos_get_node_mem_bp(): same issue with node memory.
> - damos_get_node_eligible_mem_bp(): node_eligible is cast to unsigned
>   long bytes, which can overflow if eligible memory exceeds ~419 KB.
> - damos_set_effective_quota(): total_charged_sz is in bytes, which
>   overflows when multiplied by 1,000,000 if it exceeds 4294 bytes.
> - damos_quota_score(): goal->current_value tracks PSI in microseconds,
>   which can easily be millions, overflowing when multiplied by 10,000.
> 
> Could these calculations be performed using 64-bit math on 32-bit systems
> to prevent runaway aggressive memory reclaim or total failure to reclaim?

Known low priority issue.

> 
> >  	return mult_frac(inactive, 10000, total);
> >  }
> 
> -- 
> Sashiko AI review · https://sashiko.dev/#/patchset/20260831140254.72004-1-sj@kernel.org?part=8


Thanks,
SJ

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [RFC PATCH v1.2 0/8] mm/damon: fix DAMOS bugs in core, paddr and vaddr
  2026-08-31 14:02 [RFC PATCH v1.2 0/8] mm/damon: fix DAMOS bugs in core, paddr and vaddr SJ Park
                   ` (7 preceding siblings ...)
  2026-08-31 14:02 ` [RFC PATCH v1.2 8/8] mm/damon/core: handle extreme memory state in get_in_active_mem_bp() SJ Park
@ 2026-09-01  0:50 ` SJ Park
  8 siblings, 0 replies; 20+ messages in thread
From: SJ Park @ 2026-09-01  0:50 UTC (permalink / raw)
  To: SJ Park
  Cc: stable, Andrew Morton, Usama Arif, Yueyang Pan, damon,
	linux-kernel, linux-mm

On Mon, 31 Aug 2026 07:02:39 -0700 SJ Park <sj@kernel.org> wrote:

> Fix misc bugs of DAMOS.  Patch 1 makes DAMOS less stress memory
> allocator under extreme situation.  Patches 2 and 3 fix wrong folios
> walking in DAMON_PADDR.  Patches 4 and 5 fix wrong folios walking in
> DAMON_VADDR.  Patches 6-8 handle extreme and unlikely memory situations
> that can cause divide by zero and underflow.

Sashiko found no blocker for this series.  Sashiko sent findings to damon@
mailing list [1], and I replied to all the comments.  Please read those for
details.

[1] https://lore.kernel.org/damon/



Thanks,
SJ

[...]

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2026-09-01  0:50 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-31 14:02 [RFC PATCH v1.2 0/8] mm/damon: fix DAMOS bugs in core, paddr and vaddr SJ Park
2026-08-31 14:02 ` [RFC PATCH v1.2 1/8] mm/damon/core: skip applying scheme if region split for quota fails SJ Park
2026-08-31 17:45   ` sashiko-bot
2026-08-31 14:02 ` [RFC PATCH v1.2 2/8] mm/damon/paddr: respect folio end for DAMOS_STAT SJ Park
2026-08-31 17:54   ` sashiko-bot
2026-08-31 14:02 ` [RFC PATCH v1.2 3/8] mm/damon/paddr: respect folio end for DAMOS actions except STAT SJ Park
2026-08-31 18:06   ` sashiko-bot
2026-08-31 14:02 ` [RFC PATCH v1.2 4/8] mm/damon/vaddr: respect folio end for DAMOS_STAT SJ Park
2026-08-31 18:14   ` sashiko-bot
2026-08-31 14:02 ` [RFC PATCH v1.2 5/8] mm/damon/vaddr: respect folio end for DAMOS_MIGRATE_{HOT,COLD} SJ Park
2026-08-31 18:23   ` sashiko-bot
2026-08-31 14:02 ` [RFC PATCH v1.2 6/8] mm/damon/core: handle extreme memory state in damon_get_node_mem_bp() SJ Park
2026-08-31 18:29   ` sashiko-bot
2026-08-31 14:02 ` [RFC PATCH v1.2 7/8] mm/damon/core: handle extreme memory state in get_node_memcg_used_bp() SJ Park
2026-08-31 18:41   ` sashiko-bot
2026-09-01  0:36     ` SJ Park
2026-08-31 14:02 ` [RFC PATCH v1.2 8/8] mm/damon/core: handle extreme memory state in get_in_active_mem_bp() SJ Park
2026-08-31 18:49   ` sashiko-bot
2026-09-01  0:37     ` SJ Park
2026-09-01  0:50 ` [RFC PATCH v1.2 0/8] mm/damon: fix DAMOS bugs in core, paddr and vaddr SJ Park

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox