Re: [PATCH v2 1/2] memcg: acquire peaks_lock when reading memory.peak

Ridong Chen <[email protected]>
Newsgroups dev.linux.lists.sashiko-reviews
Message-ID <[email protected]>

On 8/7/2026 5:14 PM, [email protected] wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> 
> Pre-existing issues:
> - [High] peak_write() destroys transient peaks for all other watchers by propagating the current usage instead of the old local_watermark.
> --
> 
> --- Patch [1]: [PATCH v2 1/2] memcg: acquire peaks_lock when reading memory.peak ---
> commit 7238a507204c3e18dae7c130c8f9f1da91b169b0
> Author: Ridong Chen <[email protected]>
> 
> memcg: acquire peaks_lock when reading memory.peak
> 
> The commit fixes a race condition where a reader of memory.peak could
> transiently observe a lower peak. It adds peaks_lock acquisition in
> memory_peak_show and swap_peak_show to ensure readers see a consistent
> snapshot of the peak metrics.
> 
> Link: https://sashiko.dev/#/patchset/[email protected]?part=1
> 
>> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
>> index 6061c0ba923bf..15c65249849e3 100644
>> --- a/mm/memcontrol.c
>> +++ b/mm/memcontrol.c
> 
> [ ... ]
> 
>> @@ -5806,8 +5811,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,
> 
> [Severity: High]
> This is a pre-existing issue, but does peak_write() destroy transient peaks
> for other watchers by propagating the current usage instead of the old
> local_watermark?
> 
> Looking at peak_write() in mm/memcontrol.c:
> 
> 	usage = page_counter_read(pc);
> 	WRITE_ONCE(pc->local_watermark, usage);
> 
> 	list_for_each_entry(peer_ctx, watchers, list)
> 		if (usage > peer_ctx->value)
> 			WRITE_ONCE(peer_ctx->value, usage);
> 
> If watcher A resets its peak when usage has dropped, peak_write() uses the
> current lower usage. If watcher B was tracking a previous peak, it seems
> watcher B's value is updated to the current usage rather than the previous
> peak (the old local_watermark).
> 
> For example, if watcher B resets, and then usage spikes to 100 and drops to
> 50, when watcher A resets, peak_write() will see usage is 50. Watcher B's
> value would be updated to 50 instead of 100, and the previous peak of 100
> would be lost.
> 
> Can this cause workload schedulers reading the peak to receive an
> artificially low value, leading them to over-pack workloads?
> 

This is what I am trying to fix with patch 2/2.

-- 
Best regards
Ridong
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.