[PATCH v2 1/4] mm: memcontrol: correct the type of stats_updates to unsigned long

Qi Zheng posted 4 patches 1 week, 1 day ago
There is a newer version of this series
[PATCH v2 1/4] mm: memcontrol: correct the type of stats_updates to unsigned long
Posted by Qi Zheng 1 week, 1 day ago
From: Qi Zheng <zhengqi.arch@bytedance.com>

The memcg_rstat_updated() tracks updates for vmstats_percpu->state
and lruvec_stats_percpu->state. Since these state values are of type long,
change the val parameter passed to memcg_rstat_updated() to long as well.

Correspondingly, change the type of stats_updates in struct
memcg_vmstats_percpu and struct memcg_vmstats from unsigned int and
atomic_t to unsigned long and atomic_long_t respectively to prevent
potential overflow when handling large state updates during the
reparenting of LRU folios.

Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
---
 mm/memcontrol.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index a47fb68dd65f1..7fb9cbc10dfbb 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -608,7 +608,7 @@ static inline int memcg_events_index(enum vm_event_item idx)
 
 struct memcg_vmstats_percpu {
 	/* Stats updates since the last flush */
-	unsigned int			stats_updates;
+	unsigned long			stats_updates;
 
 	/* Cached pointers for fast iteration in memcg_rstat_updated() */
 	struct memcg_vmstats_percpu __percpu	*parent_pcpu;
@@ -639,7 +639,7 @@ struct memcg_vmstats {
 	unsigned long		events_pending[NR_MEMCG_EVENTS];
 
 	/* Stats updates since the last flush */
-	atomic_t		stats_updates;
+	atomic_long_t		stats_updates;
 };
 
 /*
@@ -665,16 +665,16 @@ static u64 flush_last_time;
 
 static bool memcg_vmstats_needs_flush(struct memcg_vmstats *vmstats)
 {
-	return atomic_read(&vmstats->stats_updates) >
+	return atomic_long_read(&vmstats->stats_updates) >
 		MEMCG_CHARGE_BATCH * num_online_cpus();
 }
 
-static inline void memcg_rstat_updated(struct mem_cgroup *memcg, int val,
+static inline void memcg_rstat_updated(struct mem_cgroup *memcg, long val,
 				       int cpu)
 {
 	struct memcg_vmstats_percpu __percpu *statc_pcpu;
 	struct memcg_vmstats_percpu *statc;
-	unsigned int stats_updates;
+	unsigned long stats_updates;
 
 	if (!val)
 		return;
@@ -697,7 +697,7 @@ static inline void memcg_rstat_updated(struct mem_cgroup *memcg, int val,
 			continue;
 
 		stats_updates = this_cpu_xchg(statc_pcpu->stats_updates, 0);
-		atomic_add(stats_updates, &statc->vmstats->stats_updates);
+		atomic_long_add(stats_updates, &statc->vmstats->stats_updates);
 	}
 }
 
@@ -705,7 +705,7 @@ static void __mem_cgroup_flush_stats(struct mem_cgroup *memcg, bool force)
 {
 	bool needs_flush = memcg_vmstats_needs_flush(memcg->vmstats);
 
-	trace_memcg_flush_stats(memcg, atomic_read(&memcg->vmstats->stats_updates),
+	trace_memcg_flush_stats(memcg, atomic_long_read(&memcg->vmstats->stats_updates),
 		force, needs_flush);
 
 	if (!force && !needs_flush)
@@ -4406,8 +4406,8 @@ static void mem_cgroup_css_rstat_flush(struct cgroup_subsys_state *css, int cpu)
 	}
 	WRITE_ONCE(statc->stats_updates, 0);
 	/* We are in a per-cpu loop here, only do the atomic write once */
-	if (atomic_read(&memcg->vmstats->stats_updates))
-		atomic_set(&memcg->vmstats->stats_updates, 0);
+	if (atomic_long_read(&memcg->vmstats->stats_updates))
+		atomic_long_set(&memcg->vmstats->stats_updates, 0);
 }
 
 static void mem_cgroup_fork(struct task_struct *task)
-- 
2.20.1
Re: [PATCH v2 1/4] mm: memcontrol: correct the type of stats_updates to unsigned long
Posted by Lorenzo Stoakes (Oracle) 1 week, 1 day ago
On Wed, Mar 25, 2026 at 10:13:22PM +0800, Qi Zheng wrote:
> From: Qi Zheng <zhengqi.arch@bytedance.com>
>
> The memcg_rstat_updated() tracks updates for vmstats_percpu->state
> and lruvec_stats_percpu->state. Since these state values are of type long,
> change the val parameter passed to memcg_rstat_updated() to long as well.
>
> Correspondingly, change the type of stats_updates in struct
> memcg_vmstats_percpu and struct memcg_vmstats from unsigned int and
> atomic_t to unsigned long and atomic_long_t respectively to prevent
> potential overflow when handling large state updates during the
> reparenting of LRU folios.

Do we need a Fixes, possibly cc: stable for that? Apologies if already
asked + answered.

>
> Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>

Anyway logic seems fine to me, so:

Reviewed-by: Lorenzo Stoakes (Oracle) <ljs@kernel.org>

> ---
>  mm/memcontrol.c | 18 +++++++++---------
>  1 file changed, 9 insertions(+), 9 deletions(-)
>
> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
> index a47fb68dd65f1..7fb9cbc10dfbb 100644
> --- a/mm/memcontrol.c
> +++ b/mm/memcontrol.c
> @@ -608,7 +608,7 @@ static inline int memcg_events_index(enum vm_event_item idx)
>
>  struct memcg_vmstats_percpu {
>  	/* Stats updates since the last flush */
> -	unsigned int			stats_updates;
> +	unsigned long			stats_updates;
>
>  	/* Cached pointers for fast iteration in memcg_rstat_updated() */
>  	struct memcg_vmstats_percpu __percpu	*parent_pcpu;
> @@ -639,7 +639,7 @@ struct memcg_vmstats {
>  	unsigned long		events_pending[NR_MEMCG_EVENTS];
>
>  	/* Stats updates since the last flush */
> -	atomic_t		stats_updates;
> +	atomic_long_t		stats_updates;
>  };
>
>  /*
> @@ -665,16 +665,16 @@ static u64 flush_last_time;
>
>  static bool memcg_vmstats_needs_flush(struct memcg_vmstats *vmstats)
>  {
> -	return atomic_read(&vmstats->stats_updates) >
> +	return atomic_long_read(&vmstats->stats_updates) >
>  		MEMCG_CHARGE_BATCH * num_online_cpus();
>  }
>
> -static inline void memcg_rstat_updated(struct mem_cgroup *memcg, int val,
> +static inline void memcg_rstat_updated(struct mem_cgroup *memcg, long val,
>  				       int cpu)
>  {
>  	struct memcg_vmstats_percpu __percpu *statc_pcpu;
>  	struct memcg_vmstats_percpu *statc;
> -	unsigned int stats_updates;
> +	unsigned long stats_updates;
>
>  	if (!val)
>  		return;
> @@ -697,7 +697,7 @@ static inline void memcg_rstat_updated(struct mem_cgroup *memcg, int val,
>  			continue;
>
>  		stats_updates = this_cpu_xchg(statc_pcpu->stats_updates, 0);
> -		atomic_add(stats_updates, &statc->vmstats->stats_updates);
> +		atomic_long_add(stats_updates, &statc->vmstats->stats_updates);
>  	}
>  }
>
> @@ -705,7 +705,7 @@ static void __mem_cgroup_flush_stats(struct mem_cgroup *memcg, bool force)
>  {
>  	bool needs_flush = memcg_vmstats_needs_flush(memcg->vmstats);
>
> -	trace_memcg_flush_stats(memcg, atomic_read(&memcg->vmstats->stats_updates),
> +	trace_memcg_flush_stats(memcg, atomic_long_read(&memcg->vmstats->stats_updates),
>  		force, needs_flush);
>
>  	if (!force && !needs_flush)
> @@ -4406,8 +4406,8 @@ static void mem_cgroup_css_rstat_flush(struct cgroup_subsys_state *css, int cpu)
>  	}
>  	WRITE_ONCE(statc->stats_updates, 0);
>  	/* We are in a per-cpu loop here, only do the atomic write once */
> -	if (atomic_read(&memcg->vmstats->stats_updates))
> -		atomic_set(&memcg->vmstats->stats_updates, 0);
> +	if (atomic_long_read(&memcg->vmstats->stats_updates))
> +		atomic_long_set(&memcg->vmstats->stats_updates, 0);
>  }
>
>  static void mem_cgroup_fork(struct task_struct *task)
> --
> 2.20.1
>
Re: [PATCH v2 1/4] mm: memcontrol: correct the type of stats_updates to unsigned long
Posted by Qi Zheng 1 week ago

On 3/25/26 11:28 PM, Lorenzo Stoakes (Oracle) wrote:
> On Wed, Mar 25, 2026 at 10:13:22PM +0800, Qi Zheng wrote:
>> From: Qi Zheng <zhengqi.arch@bytedance.com>
>>
>> The memcg_rstat_updated() tracks updates for vmstats_percpu->state
>> and lruvec_stats_percpu->state. Since these state values are of type long,
>> change the val parameter passed to memcg_rstat_updated() to long as well.
>>
>> Correspondingly, change the type of stats_updates in struct
>> memcg_vmstats_percpu and struct memcg_vmstats from unsigned int and
>> atomic_t to unsigned long and atomic_long_t respectively to prevent
>> potential overflow when handling large state updates during the
>> reparenting of LRU folios.
> 
> Do we need a Fixes, possibly cc: stable for that? Apologies if already
> asked + answered.

Before LRU folio reparenting was introduced, we wouldn’t pass in such a
large value, so this wasn’t a problem. Since LRU folio reparenting is
still in mm-unstable, so I didn't add a Fixes tag in [4/4].

> 
>>
>> Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
> 
> Anyway logic seems fine to me, so:
> 
> Reviewed-by: Lorenzo Stoakes (Oracle) <ljs@kernel.org>

Thanks!


Re: [PATCH v2 1/4] mm: memcontrol: correct the type of stats_updates to unsigned long
Posted by Lorenzo Stoakes (Oracle) 1 week ago
On Thu, Mar 26, 2026 at 10:32:43AM +0800, Qi Zheng wrote:
>
>
> On 3/25/26 11:28 PM, Lorenzo Stoakes (Oracle) wrote:
> > On Wed, Mar 25, 2026 at 10:13:22PM +0800, Qi Zheng wrote:
> > > From: Qi Zheng <zhengqi.arch@bytedance.com>
> > >
> > > The memcg_rstat_updated() tracks updates for vmstats_percpu->state
> > > and lruvec_stats_percpu->state. Since these state values are of type long,
> > > change the val parameter passed to memcg_rstat_updated() to long as well.
> > >
> > > Correspondingly, change the type of stats_updates in struct
> > > memcg_vmstats_percpu and struct memcg_vmstats from unsigned int and
> > > atomic_t to unsigned long and atomic_long_t respectively to prevent
> > > potential overflow when handling large state updates during the
> > > reparenting of LRU folios.
> >
> > Do we need a Fixes, possibly cc: stable for that? Apologies if already
> > asked + answered.
>
> Before LRU folio reparenting was introduced, we wouldn’t pass in such a
> large value, so this wasn’t a problem. Since LRU folio reparenting is
> still in mm-unstable, so I didn't add a Fixes tag in [4/4].

Ah, well these patches should be _before_ the LRU folio reparenting then?

Andrew - can we ensure correct ordering here?

>
> >
> > >
> > > Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
> >
> > Anyway logic seems fine to me, so:
> >
> > Reviewed-by: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
>
> Thanks!
>
>

Thanks, Lorenzo
Re: [PATCH v2 1/4] mm: memcontrol: correct the type of stats_updates to unsigned long
Posted by Qi Zheng 1 week ago

On 3/26/26 4:05 PM, Lorenzo Stoakes (Oracle) wrote:
> On Thu, Mar 26, 2026 at 10:32:43AM +0800, Qi Zheng wrote:
>>
>>
>> On 3/25/26 11:28 PM, Lorenzo Stoakes (Oracle) wrote:
>>> On Wed, Mar 25, 2026 at 10:13:22PM +0800, Qi Zheng wrote:
>>>> From: Qi Zheng <zhengqi.arch@bytedance.com>
>>>>
>>>> The memcg_rstat_updated() tracks updates for vmstats_percpu->state
>>>> and lruvec_stats_percpu->state. Since these state values are of type long,
>>>> change the val parameter passed to memcg_rstat_updated() to long as well.
>>>>
>>>> Correspondingly, change the type of stats_updates in struct
>>>> memcg_vmstats_percpu and struct memcg_vmstats from unsigned int and
>>>> atomic_t to unsigned long and atomic_long_t respectively to prevent
>>>> potential overflow when handling large state updates during the
>>>> reparenting of LRU folios.
>>>
>>> Do we need a Fixes, possibly cc: stable for that? Apologies if already
>>> asked + answered.
>>
>> Before LRU folio reparenting was introduced, we wouldn’t pass in such a
>> large value, so this wasn’t a problem. Since LRU folio reparenting is
>> still in mm-unstable, so I didn't add a Fixes tag in [4/4].
> 
> Ah, well these patches should be _before_ the LRU folio reparenting then?
> 
> Andrew - can we ensure correct ordering here?

There are some dependencies for this.

To be precise, it should be applied after:

[PATCH v6 29/33] mm: memcontrol: refactor mod_memcg_state() and 
mod_memcg_lruvec_state()

and before:

[PATCH v6 32/33] mm: memcontrol: eliminate the problem of dying memory 
cgroup for LRU folios

and there might be conflicts.

Would it be okay to merge them together into v7.1-rcX? Otherwise,
perhaps updating to v7 would be more convenient for Andrew.

Hi Andrew, what do you think?

Thanks,
Qi

> 
>>
>>>
>>>>
>>>> Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
>>>
>>> Anyway logic seems fine to me, so:
>>>
>>> Reviewed-by: Lorenzo Stoakes (Oracle) <ljs@kernel.org>
>>
>> Thanks!
>>
>>
> 
> Thanks, Lorenzo

Re: [PATCH v2 1/4] mm: memcontrol: correct the type of stats_updates to unsigned long
Posted by Harry Yoo (Oracle) 1 week ago
On Thu, Mar 26, 2026 at 08:05:57AM +0000, Lorenzo Stoakes (Oracle) wrote:
> On Thu, Mar 26, 2026 at 10:32:43AM +0800, Qi Zheng wrote:
> >
> >
> > On 3/25/26 11:28 PM, Lorenzo Stoakes (Oracle) wrote:
> > > On Wed, Mar 25, 2026 at 10:13:22PM +0800, Qi Zheng wrote:
> > > > From: Qi Zheng <zhengqi.arch@bytedance.com>
> > > >
> > > > The memcg_rstat_updated() tracks updates for vmstats_percpu->state
> > > > and lruvec_stats_percpu->state. Since these state values are of type long,
> > > > change the val parameter passed to memcg_rstat_updated() to long as well.
> > > >
> > > > Correspondingly, change the type of stats_updates in struct
> > > > memcg_vmstats_percpu and struct memcg_vmstats from unsigned int and
> > > > atomic_t to unsigned long and atomic_long_t respectively to prevent
> > > > potential overflow when handling large state updates during the
> > > > reparenting of LRU folios.
> > >
> > > Do we need a Fixes, possibly cc: stable for that? Apologies if already
> > > asked + answered.
> >
> > Before LRU folio reparenting was introduced, we wouldn’t pass in such a
> > large value, so this wasn’t a problem. Since LRU folio reparenting is
> > still in mm-unstable, so I didn't add a Fixes tag in [4/4].
> 
> Ah, well these patches should be _before_ the LRU folio reparenting then?

Yes. I think that'll be the best option.

If that's too much of a headache at this point (I'm not sure),
it should be at least part of 7.1-rcX, given that it's quite unlikely
that people will notice it during bisection anyway...

-- 
Cheers,
Harry / Hyeonggon