From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from out-178.mta0.migadu.com (out-178.mta0.migadu.com [91.218.175.178]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5633779CD for ; Wed, 22 Apr 2026 09:31:15 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.178 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776850277; cv=none; b=V4ke8AjyqfYnVxfvn/ipc+6Ptuh1CFQTIgoDOu0Qp1hBmqdKsAzkxc94PLE5Y2p2OK3Xz5joWORiML2nc3svsYlZYlrUSn8mKolND1ntt3wSayjDkatJB7oPeeW0JcyVdD2oHtZD6iImP/6fj9D39H3PY6TFZ9pqaZxJwWTQhOA= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776850277; c=relaxed/simple; bh=eCVdFjh1aqD5eM/xznznTP1YP4xWCdUVWxN2OIrcZ3I=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=aFJfHmmMSHgIdCg6A/oKnzZv2gLCQBovFwsA9lRyy+b7gQTOJYQADwTNkNi3eVEU/foeti9xWL0y7abTcFCMGcDrzmBkYrF3poeTPlQ0XLivFfnlAyOubq7e+YWR79NsnHbgNbHZnkWgxZc5umnd2Zx91r59DSSD1IOKrw6I6Hc= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=j0gcjLW1; arc=none smtp.client-ip=91.218.175.178 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="j0gcjLW1" Message-ID: <30ed6e19-0d96-4d61-b991-6d0ab5198757@linux.dev> DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1776850273; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=3lo8TVtgfArfghz+oUureKTbqMqnDdblWKzNFGF4O6o=; b=j0gcjLW1qZRpEkHP1GtHNKnZwnK5eNqb9WJMCosYu4T5HZsewwv2dZmojVTZXYRvSClriY pYSlHRGrPWNhNJN0dE9Fd3R0DG7T18ZJx/faKe7WeIdCCizMivsI6ex33+dNCbvACrHuSV ZljpgHi0E6SxQrAYKDwsdaWg1xOk+LM= Date: Wed, 22 Apr 2026 17:30:30 +0800 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Subject: Re: [PATCH v3] tools/cgroup/slabinfo: Fix use of slab.memcg_data To: Hongfu Li , harry@kernel.org, willy@infradead.org, vbabka@kernel.org, roman.gushchin@linux.dev, akpm@linux-foundation.org, surenb@google.com, pasha.tatashin@soleen.com, hao.li@linux.dev Cc: linux-kernel@vger.kernel.org References: <20260422073900.107311-1-lihongfu@kylinos.cn> Content-Language: en-US X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. From: Hao Ge In-Reply-To: <20260422073900.107311-1-lihongfu@kylinos.cn> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit X-Migadu-Flow: FLOW_OUT Hi Hongfu On 2026/4/22 15:39, Hongfu Li wrote: > After the introduce slabobj_ext to support slab object extensions, the > memcg_slabinfo tool broke. An attempt to run it produces a trace like > this: > Traceback (most recent call last): > File "/usr/local/bin/drgn", line 8, in > sys.exit(_main()) > ^^^^^^^ > File "/usr/local/lib64/python3.11/site-packages/drgn/cli.py", line 688, in _main > runpy.run_path( > File "", line 291, in run_path > File "", line 98, in _run_module_code > File "", line 88, in _run_code > File "/root/memcg_slabinfo.py", line 225, in > main() > File "/root/memcg_slabinfo.py", line 195, in main > objcg_vec_raw = slab.memcg_data.value_() > AttributeError: 'struct slab' has no member 'memcg_data' > > Fixes: 21c690a349ba ("mm: introduce slabobj_ext to support slab object extensions") > Fixes: 5ba6bc27b1f9 ("slab: decouple pointer to barn from kmem_cache_node") > Signed-off-by: Hongfu Li > --- > v3: > - Add a compatibility accessor for per-node cache state (per_node[nid].node vs node[nid]) > - Link to v2: https://lore.kernel.org/all/20260421055829.3930289-1-lihongfu@kylinos.cn/ > v2: > - Skip slabs after masking when the base is zero (OBJEXTS_ALLOC_FAIL). > - Walk slab->obj_exts using base + stride * i (same indexing as slab_obj_ext()). > - Link to v1: https://lore.kernel.org/all/20260417020729.952897-1-lihongfu@kylinos.cn/ > --- > tools/cgroup/memcg_slabinfo.py | 45 ++++++++++++++++++++++++++++------ > 1 file changed, 38 insertions(+), 7 deletions(-) > > diff --git a/tools/cgroup/memcg_slabinfo.py b/tools/cgroup/memcg_slabinfo.py > index 6bf4bde77903..f49512831d6a 100644 > --- a/tools/cgroup/memcg_slabinfo.py > +++ b/tools/cgroup/memcg_slabinfo.py > @@ -33,6 +33,21 @@ def err(s): > sys.exit(1) > > > +def objexts_flags_mask(): > + try: > + return int(prog.constant('__NR_OBJEXTS_FLAGS')) - 1 > + except: > + return 0x7 > + > + > +def slab_obj_ext_stride(slab): > + # Match slab_obj_ext() for both layouts: contiguous ext[] or ext-in-object > + try: > + return slab.stride.value_() > + except AttributeError: > + return prog.type('struct slabobj_ext').size > + > + > def find_memcg_ids(css=prog['root_mem_cgroup'].css, prefix=''): > if not list_empty(css.children.address_of_()): > for css in list_for_each_entry('struct cgroup_subsys_state', > @@ -68,6 +83,13 @@ def oo_objects(s): > return s.oo.x & OO_MASK > > > +def kmem_cache_get_node(s, nid): > + try: > + return s.per_node[nid].node > + except AttributeError: > + return s.node[nid] > + This gives me another idea. So actually, we don't need to forcibly convert memcg_data to obj_exts, right? like this: try:       raw = slab.memcg_data.value_()       new_layout = False   except AttributeError:       raw = slab.obj_exts.value_()       new_layout = True and then take the new path based on new_layout. But I'm not sure if we need to do this, as it would indeed make the helper handle more and more cases. Thanks Best Regards Hao > + > def count_partial(n, fn): > nr_objs = 0 > for slab in list_for_each_entry('struct slab', n.partial.address_of_(), > @@ -86,7 +108,9 @@ def slub_get_slabinfo(s, cfg): > nr_free = 0 > > for node in range(cfg['nr_nodes']): > - n = s.node[node] > + n = kmem_cache_get_node(s, node) > + if not n.value_(): > + continue > nr_slabs += n.nr_slabs.counter.value_() > nr_objs += n.total_objects.counter.value_() > nr_free += count_partial(n, count_free) > @@ -192,23 +216,30 @@ def main(): > # look over all slab folios and look for objects belonging > # to the given memory cgroup > for slab in for_each_slab(prog): > - objcg_vec_raw = slab.memcg_data.value_() > - if objcg_vec_raw == 0: > + objext_vec_raw = slab.obj_exts.value_() > + if objext_vec_raw == 0: > continue > cache = slab.slab_cache > if not cache: > continue > addr = cache.value_() > caches[addr] = cache > - # clear the lowest bit to get the true obj_cgroups > - objcg_vec = Object(prog, 'struct obj_cgroup **', > - value=objcg_vec_raw & ~1) > > if addr not in stats: > stats[addr] = 0 > > + # clear OBJEXTS_FLAGS_MASK bits to get the true slabobj_ext base. > + # If OBJEXTS_ALLOC_FAIL, masked base is 0 - not tied to any cgroup. > + mask = objexts_flags_mask() > + objext_base = objext_vec_raw & ~mask > + if objext_base == 0: > + continue > + > + stride = slab_obj_ext_stride(slab) > for i in range(oo_objects(cache)): > - if objcg_vec[i].value_() in obj_cgroups: > + objext = Object(prog, 'struct slabobj_ext *', > + value=objext_base + stride * i) > + if objext.objcg.value_() in obj_cgroups: > stats[addr] += 1 > > for addr in caches: