* [PATCH v2 1/2] memcg: acquire peaks_lock when reading memory.peak
[not found] <20260807090000.1532495-1-ridong.chen@linux.dev>
@ 2026-08-07 8:59 ` Ridong
2026-08-07 20:22 ` [PATCH v2 0/2] mm, memcg: fix memory.peak reset clobbering other fds' watermark Andrew Morton
1 sibling, 0 replies; 2+ messages in thread
From: Ridong @ 2026-08-07 8:59 UTC (permalink / raw)
To: Johannes Weiner, Michal Hocko, Roman Gushchin, Shakeel Butt,
Andrew Morton
Cc: Muchun Song, Tejun Heo, Michal Koutný, cgroups, linux-mm,
linux-kernel, Ridong Chen, cui.tao, Ridong Chen
From: Ridong Chen <chenridong@xiaomi.com>
Sashiko reported that a reader can transiently observe a lower peak
within a race window [1]. peak_show() returns
max(local_watermark, ofp->value), but peak_write() updates those two
under peaks_lock while the reader takes no lock. The interleaving is:
writer (reset on fd A) reader (fd B)
---------------------- -------------
usage = page_counter_read(pc)
WRITE_ONCE(local_watermark, usage)
// watermark lowered to usage
lw = READ_ONCE(local_watermark)
// sees the lowered usage
val = READ_ONCE(ofp->value)
// B's value not updated yet
return max(lw, val)
// both low -> low peak
WRITE_ONCE(peer_ctx->value, usage)
// B updated, but too late
Fix it by acquiring peaks_lock when reading the peak, so the reader sees
a consistent snapshot of local_watermark and the per-fd values. The same
race applies to memory.swap.peak, which shares peaks_lock and the
peak_write() path, so take the lock there as well.
[1] https://sashiko.dev/#/patchset/20260730115314.1069089-1-ridong.chen@linux.dev?part=1
Fixes: c6f53ed8f213 ("mm, memcg: cg2 memory{.swap,}.peak write handlers")
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Ridong Chen <chenridong@xiaomi.com>
---
mm/memcontrol.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index dd6b1c298345..2da55b778ae3 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -4711,8 +4711,13 @@ static int peak_show(struct seq_file *sf, void *v, struct page_counter *pc)
static int memory_peak_show(struct seq_file *sf, void *v)
{
struct mem_cgroup *memcg = mem_cgroup_from_css(seq_css(sf));
+ int ret;
- return peak_show(sf, v, &memcg->memory);
+ spin_lock(&memcg->peaks_lock);
+ ret = peak_show(sf, v, &memcg->memory);
+ spin_unlock(&memcg->peaks_lock);
+
+ return ret;
}
static int peak_open(struct kernfs_open_file *of)
@@ -5790,8 +5795,13 @@ static u64 swap_current_read(struct cgroup_subsys_state *css,
static int swap_peak_show(struct seq_file *sf, void *v)
{
struct mem_cgroup *memcg = mem_cgroup_from_css(seq_css(sf));
+ int ret;
- return peak_show(sf, v, &memcg->swap);
+ spin_lock(&memcg->peaks_lock);
+ ret = peak_show(sf, v, &memcg->swap);
+ spin_unlock(&memcg->peaks_lock);
+
+ return ret;
}
static ssize_t swap_peak_write(struct kernfs_open_file *of, char *buf,
--
2.34.1
^ permalink raw reply related [flat|nested] 2+ messages in thread* Re: [PATCH v2 0/2] mm, memcg: fix memory.peak reset clobbering other fds' watermark
[not found] <20260807090000.1532495-1-ridong.chen@linux.dev>
2026-08-07 8:59 ` [PATCH v2 1/2] memcg: acquire peaks_lock when reading memory.peak Ridong
@ 2026-08-07 20:22 ` Andrew Morton
1 sibling, 0 replies; 2+ messages in thread
From: Andrew Morton @ 2026-08-07 20:22 UTC (permalink / raw)
To: Ridong
Cc: Johannes Weiner, Michal Hocko, Roman Gushchin, Shakeel Butt,
Muchun Song, Tejun Heo, Michal Koutný, cgroups, linux-mm,
linux-kernel, cui.tao, Ridong Chen
On Fri, 7 Aug 2026 16:59:58 +0800 Ridong <ridong.chen@linux.dev> wrote:
> Two fixes for the per-fd memory.peak / memory.swap.peak handlers added in
> c6f53ed8f213. Each open fd reads back max(its own value, the shared
> local_watermark), and both bugs live in that scheme.
Thanks.
We're missing the preferred description of the worst-case
userspace-visible effects of the bug. It appears they're quite minor
so I'll assume this series is a post-7.2 thing.
Sashiko might have found a similar race on the writer side:
https://sashiko.dev/#/patchset/20260807090000.1532495-1-ridong.chen@linux.dev
^ permalink raw reply [flat|nested] 2+ messages in thread