On Fri, Apr 09, 2021 at 07:18:38PM -0400, Waiman Long wrote: > The caller of mod_memcg_lruvec_state() has both memcg and lruvec readily > available. So both of them are now passed to mod_memcg_lruvec_state() > and __mod_memcg_lruvec_state(). The __mod_memcg_lruvec_state() is > updated to allow either of the two parameters to be set to null. This > makes mod_memcg_lruvec_state() equivalent to mod_memcg_state() if lruvec > is null. This patch seems to be correct, but it's a bit hard to understand why it's required without looking into the rest of the series. Can you, please, add a couple of words about it? E.g. we need it to handle stats which do not exist on the lruvec level... Otherwise, Acked-by: Roman Gushchin <guro@xxxxxx> Thanks! > > Signed-off-by: Waiman Long <longman@xxxxxxxxxx> > --- > include/linux/memcontrol.h | 12 +++++++----- > mm/memcontrol.c | 19 +++++++++++++------ > mm/slab.h | 2 +- > 3 files changed, 21 insertions(+), 12 deletions(-) > > diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h > index 0c04d39a7967..95f12996e66c 100644 > --- a/include/linux/memcontrol.h > +++ b/include/linux/memcontrol.h > @@ -955,8 +955,8 @@ static inline unsigned long lruvec_page_state_local(struct lruvec *lruvec, > return x; > } > > -void __mod_memcg_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx, > - int val); > +void __mod_memcg_lruvec_state(struct mem_cgroup *memcg, struct lruvec *lruvec, > + enum node_stat_item idx, int val); > void __mod_lruvec_kmem_state(void *p, enum node_stat_item idx, int val); > > static inline void mod_lruvec_kmem_state(void *p, enum node_stat_item idx, > @@ -969,13 +969,14 @@ static inline void mod_lruvec_kmem_state(void *p, enum node_stat_item idx, > local_irq_restore(flags); > } > > -static inline void mod_memcg_lruvec_state(struct lruvec *lruvec, > +static inline void mod_memcg_lruvec_state(struct mem_cgroup *memcg, > + struct lruvec *lruvec, > enum node_stat_item idx, int val) > { > unsigned long flags; > > local_irq_save(flags); > - __mod_memcg_lruvec_state(lruvec, idx, val); > + __mod_memcg_lruvec_state(memcg, lruvec, idx, val); > local_irq_restore(flags); > } > > @@ -1369,7 +1370,8 @@ static inline unsigned long lruvec_page_state_local(struct lruvec *lruvec, > return node_page_state(lruvec_pgdat(lruvec), idx); > } > > -static inline void __mod_memcg_lruvec_state(struct lruvec *lruvec, > +static inline void __mod_memcg_lruvec_state(struct mem_cgroup *memcg, > + struct lruvec *lruvec, > enum node_stat_item idx, int val) > { > } > diff --git a/mm/memcontrol.c b/mm/memcontrol.c > index e064ac0d850a..d66e1e38f8ac 100644 > --- a/mm/memcontrol.c > +++ b/mm/memcontrol.c > @@ -799,20 +799,27 @@ parent_nodeinfo(struct mem_cgroup_per_node *pn, int nid) > return mem_cgroup_nodeinfo(parent, nid); > } > > -void __mod_memcg_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx, > - int val) > +/* > + * Either one of memcg or lruvec can be NULL, but not both. > + */ > +void __mod_memcg_lruvec_state(struct mem_cgroup *memcg, struct lruvec *lruvec, > + enum node_stat_item idx, int val) > { > struct mem_cgroup_per_node *pn; > - struct mem_cgroup *memcg; > long x, threshold = MEMCG_CHARGE_BATCH; > > + /* Update lruvec */ > pn = container_of(lruvec, struct mem_cgroup_per_node, lruvec); > - memcg = pn->memcg; > + > + if (!memcg) > + memcg = pn->memcg; > > /* Update memcg */ > __mod_memcg_state(memcg, idx, val); > > - /* Update lruvec */ > + if (!lruvec) > + return; > + > __this_cpu_add(pn->lruvec_stat_local->count[idx], val); > > if (vmstat_item_in_bytes(idx)) > @@ -848,7 +855,7 @@ void __mod_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx, > > /* Update memcg and lruvec */ > if (!mem_cgroup_disabled()) > - __mod_memcg_lruvec_state(lruvec, idx, val); > + __mod_memcg_lruvec_state(NULL, lruvec, idx, val); > } > > void __mod_lruvec_page_state(struct page *page, enum node_stat_item idx, > diff --git a/mm/slab.h b/mm/slab.h > index 076582f58f68..bc6c7545e487 100644 > --- a/mm/slab.h > +++ b/mm/slab.h > @@ -293,7 +293,7 @@ static inline void mod_objcg_state(struct obj_cgroup *objcg, > rcu_read_lock(); > memcg = obj_cgroup_memcg(objcg); > lruvec = mem_cgroup_lruvec(memcg, pgdat); > - mod_memcg_lruvec_state(lruvec, idx, nr); > + mod_memcg_lruvec_state(memcg, lruvec, idx, nr); > rcu_read_unlock(); > } > > -- > 2.18.1 >