]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
mm: memcg: factor out trylock_stock() and unlock_stock()
authorJohannes Weiner <jweiner@meta.com>
Mon, 2 Mar 2026 19:50:14 +0000 (14:50 -0500)
committerAndrew Morton <akpm@linux-foundation.org>
Sun, 5 Apr 2026 20:53:16 +0000 (13:53 -0700)
Patch series "memcg: obj stock and slab stat caching cleanups".

This is a follow-up to `[PATCH] memcg: fix slab accounting in
refill_obj_stock() trylock path`.  The way the slab stat cache and the
objcg charge cache interact appears a bit too fragile.  This series
factors those paths apart as much as practical.

This patch (of 5):

Consolidate the local lock acquisition and the local stock lookup.  This
allows subsequent patches to use !!stock as an easy way to disambiguate
the locked vs.  contended cases through the callstack.

Link: https://lkml.kernel.org/r/20260302195305.620713-1-hannes@cmpxchg.org
Link: https://lkml.kernel.org/r/20260302195305.620713-2-hannes@cmpxchg.org
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
Acked-by: Shakeel Butt <shakeel.butt@linux.dev>
Acked-by: Roman Gushchin <roman.gushchin@linux.dev>
Reviewed-by: Vlastimil Babka (SUSE) <vbabka@kernel.org>
Reviewed-by: Hao Li <hao.li@linux.dev>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Muchun Song <muchun.song@linux.dev>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
mm/memcontrol.c

index 87614cfc4a3ee6a4c0470fa7ba1fd8c0f6dd70ed..5262533d0828718ca992121e18376a684e7f9403 100644 (file)
@@ -2950,6 +2950,19 @@ void __memcg_kmem_uncharge_page(struct page *page, int order)
        obj_cgroup_put(objcg);
 }
 
+static struct obj_stock_pcp *trylock_stock(void)
+{
+       if (local_trylock(&obj_stock.lock))
+               return this_cpu_ptr(&obj_stock);
+
+       return NULL;
+}
+
+static void unlock_stock(struct obj_stock_pcp *stock)
+{
+       local_unlock(&obj_stock.lock);
+}
+
 static void __account_obj_stock(struct obj_cgroup *objcg,
                                struct obj_stock_pcp *stock, int nr,
                                struct pglist_data *pgdat, enum node_stat_item idx)
@@ -3005,10 +3018,10 @@ static bool consume_obj_stock(struct obj_cgroup *objcg, unsigned int nr_bytes,
        struct obj_stock_pcp *stock;
        bool ret = false;
 
-       if (!local_trylock(&obj_stock.lock))
+       stock = trylock_stock();
+       if (!stock)
                return ret;
 
-       stock = this_cpu_ptr(&obj_stock);
        if (objcg == READ_ONCE(stock->cached_objcg) && stock->nr_bytes >= nr_bytes) {
                stock->nr_bytes -= nr_bytes;
                ret = true;
@@ -3017,7 +3030,7 @@ static bool consume_obj_stock(struct obj_cgroup *objcg, unsigned int nr_bytes,
                        __account_obj_stock(objcg, stock, nr_bytes, pgdat, idx);
        }
 
-       local_unlock(&obj_stock.lock);
+       unlock_stock(stock);
 
        return ret;
 }
@@ -3108,7 +3121,8 @@ static void refill_obj_stock(struct obj_cgroup *objcg, unsigned int nr_bytes,
        struct obj_stock_pcp *stock;
        unsigned int nr_pages = 0;
 
-       if (!local_trylock(&obj_stock.lock)) {
+       stock = trylock_stock();
+       if (!stock) {
                if (pgdat)
                        mod_objcg_mlstate(objcg, pgdat, idx, nr_acct);
                nr_pages = nr_bytes >> PAGE_SHIFT;
@@ -3117,7 +3131,6 @@ static void refill_obj_stock(struct obj_cgroup *objcg, unsigned int nr_bytes,
                goto out;
        }
 
-       stock = this_cpu_ptr(&obj_stock);
        if (READ_ONCE(stock->cached_objcg) != objcg) { /* reset if necessary */
                drain_obj_stock(stock);
                obj_cgroup_get(objcg);
@@ -3137,7 +3150,7 @@ static void refill_obj_stock(struct obj_cgroup *objcg, unsigned int nr_bytes,
                stock->nr_bytes &= (PAGE_SIZE - 1);
        }
 
-       local_unlock(&obj_stock.lock);
+       unlock_stock(stock);
 out:
        if (nr_pages)
                obj_cgroup_uncharge_pages(objcg, nr_pages);