From patchwork Tue Jul 25 09:34:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: =?utf-8?b?S3Vhbi1ZaW5nIExlZSAo5p2O5Yag56mOKQ==?= X-Patchwork-Id: 13326208 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9F8FFC04A6A for ; Tue, 25 Jul 2023 09:36:26 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 8BD3A6B0071; Tue, 25 Jul 2023 05:36:24 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 86D2E8D0002; Tue, 25 Jul 2023 05:36:24 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 696B66B0078; Tue, 25 Jul 2023 05:36:24 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0017.hostedemail.com [216.40.44.17]) by kanga.kvack.org (Postfix) with ESMTP id 40C0E6B0071 for ; Tue, 25 Jul 2023 05:36:24 -0400 (EDT) Received: from smtpin20.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay04.hostedemail.com (Postfix) with ESMTP id 127FF1A0D21 for ; Tue, 25 Jul 2023 09:36:24 +0000 (UTC) X-FDA: 81049628688.20.A725F7D Received: from mailgw02.mediatek.com (mailgw02.mediatek.com [216.200.240.185]) by imf18.hostedemail.com (Postfix) with ESMTP id C09D61C000F for ; Tue, 25 Jul 2023 09:36:21 +0000 (UTC) Authentication-Results: imf18.hostedemail.com; dkim=pass header.d=mediatek.com header.s=dk header.b=rhCXYQ0D; dmarc=pass (policy=quarantine) header.from=mediatek.com; spf=pass (imf18.hostedemail.com: domain of kuan-ying.lee@mediatek.com designates 216.200.240.185 as permitted sender) smtp.mailfrom=kuan-ying.lee@mediatek.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1690277782; h=from:from:sender: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: in-reply-to:in-reply-to:references:references:dkim-signature; bh=qV3yiLcapY79UYhQ2yxqusTw/Je4hCg71heXhG6JWXs=; b=VKnJnOjjRiruuAI/m5SNTOieRoVAnb70n32SSMFSoZBMNBQLoycUPAjNqUS6pPLjRnCY+f /ZK+S9UFBSSX/T1UYiBVXK0LfRMSt3B2KDek3IWHIxtDaeVyc8NYNi+DqLFYWoiAx/iFYJ pptUxWxF6STQTd3YgvjpET3rht73GuA= ARC-Authentication-Results: i=1; imf18.hostedemail.com; dkim=pass header.d=mediatek.com header.s=dk header.b=rhCXYQ0D; dmarc=pass (policy=quarantine) header.from=mediatek.com; spf=pass (imf18.hostedemail.com: domain of kuan-ying.lee@mediatek.com designates 216.200.240.185 as permitted sender) smtp.mailfrom=kuan-ying.lee@mediatek.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1690277782; a=rsa-sha256; cv=none; b=GLOI0wFwN70izyOUN8LNw7eb7/iFdT+5YENMklhacKjuXcWLrtDYAAn9j3U82UsfG60cBX RAO6VdHGwcFwg14Q/YHtSDZ90FANQqwmj/liIbLYTfXTomeeXc2Lu4mDKf7uBM+3ZAUgHg 1uFJ6wKJ6w7krqtaXiGf/pGOPOZfF7U= X-UUID: b1ea93822ace11ee83ed1395ce914268-20230725 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mediatek.com; s=dk; h=Content-Type:MIME-Version:References:In-Reply-To:Message-ID:Date:Subject:CC:To:From; bh=qV3yiLcapY79UYhQ2yxqusTw/Je4hCg71heXhG6JWXs=; b=rhCXYQ0DMRq+4NbCpXmpyFMsstvAgBZ/mTgAYX7LwOP/itmW1dpIJtIv5wYnFDYOZJkraX/PtvyvW/Q7xKq2em1+ErEm82H23PIwPwGMMwloQTyO47wMq89ioY4MlNtsMj6uvogAnBCwRG4DzwGCQ6/Uje+xikZ/FlUf8cW8yhg=; X-CID-P-RULE: Release_Ham X-CID-O-INFO: VERSION:1.1.29,REQID:349d45fc-37f9-4750-9ba1-fa1f7995ea7e,IP:0,U RL:0,TC:0,Content:0,EDM:0,RT:0,SF:0,FILE:0,BULK:0,RULE:Release_Ham,ACTION: release,TS:0 X-CID-META: VersionHash:e7562a7,CLOUDID:ebd2c3b3-a467-4aa9-9e04-f584452e3794,B ulkID:nil,BulkQuantity:0,Recheck:0,SF:102,TC:nil,Content:0,EDM:-3,IP:nil,U RL:11|1,File:nil,Bulk:nil,QS:nil,BEC:nil,COL:0,OSI:0,OSA:0,AV:0,LES:1,SPR: NO,DKR:0,DKP:0,BRR:0,BRE:0 X-CID-BVR: 0 X-CID-BAS: 0,_,0,_ X-CID-FACTOR: TF_CID_SPAM_SNR,TF_CID_SPAM_ULN X-UUID: b1ea93822ace11ee83ed1395ce914268-20230725 Received: from mtkmbs13n2.mediatek.inc [(172.21.101.108)] by mailgw02.mediatek.com (envelope-from ) (musrelay.mediatek.com ESMTP with TLSv1.2 ECDHE-RSA-AES256-GCM-SHA384 256/256) with ESMTP id 987966792; Tue, 25 Jul 2023 02:36:13 -0700 Received: from mtkmbs11n1.mediatek.inc (172.21.101.185) by mtkmbs10n2.mediatek.inc (172.21.101.183) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.26; Tue, 25 Jul 2023 17:35:42 +0800 Received: from mtksdccf07.mediatek.inc (172.21.84.99) by mtkmbs11n1.mediatek.inc (172.21.101.73) with Microsoft SMTP Server id 15.2.1118.26 via Frontend Transport; Tue, 25 Jul 2023 17:35:42 +0800 From: Kuan-Ying Lee To: Jan Kiszka , Kieran Bingham , Matthias Brugger , AngeloGioacchino Del Regno CC: , , , , , , , Kuan-Ying Lee , , Subject: [PATCH 7/8] scripts/gdb/slab: Add slab support Date: Tue, 25 Jul 2023 17:34:57 +0800 Message-ID: <20230725093458.30064-8-Kuan-Ying.Lee@mediatek.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20230725093458.30064-1-Kuan-Ying.Lee@mediatek.com> References: <20230725093458.30064-1-Kuan-Ying.Lee@mediatek.com> MIME-Version: 1.0 X-MTK: N X-Rspam-User: X-Rspamd-Server: rspam12 X-Rspamd-Queue-Id: C09D61C000F X-Stat-Signature: 84531n7j7yb1m8pdwx5pxdn6s11grgzn X-HE-Tag: 1690277781-762365 X-HE-Meta: U2FsdGVkX1/aWDcFNpRlD/UgDuN6XdxI9dAnKMtWhBK+Yb4cRCFgPj3Km14I/XfKKp4m/Os9CXCtykDTglqWd37HjYswxG8RTWuxnMKvBoVL5qvl8NcHcEG4IGA3/4YVY7VkkT+RQUwP7B/I0m75AI/rx4sZed5Q1xOTiuiU7frNxZvKkAiYB0be6BrW1DxUzi+Fp4lC0nBU3+s798NPly0b65IF4qHrNKR5l2eq59mGj1vedmWW/Is9kDEmOJnqaivs8tKXG2jUEkbPGBkoriqbf5CLKz5GxOEAdhvFwvauYiY8TUaLAjZxg/RW9l5NpUFoRN8jZeC+/USvOV+i5AuX/E3rx5+paClJAYX1GibRBG3+9SE7t8O7KuxdBU5DgU46VudWFIYBAxz0kuTDtADcrllMgChsEafq/Kg9rMTAxiODzGZh/b2aDgUsY9umbEKodPfBCHCn3n5eEgWoN0LUVgTRvPy5915HZzdvfmiT/7LZC0IViBvA4mmhPkT5s66JqYsa21M3pspEJ9V4NIpBF/bSKlEzvR6WqaDvQ6fCWc41UXKmMTzvjoAzD2kbUt23Dq6b3/yTgSGTgsT1Zs1aF1MQX1jE41nWPluH18F+e7xtHFx1m52VNEYkxKVKIa+JUCJZpIZ5tgmUwBEwXUEtbD6NfFcduLFGpwyjtWDenrptSQNbNlmSUwwg6tNcIb6an4VjfaIEujsvDG4oorrmVGFCvjWKklMKaIOQKbS8RuCUcWuUTXKYcJrWat0gFH6r/rfKO47sOG5vGkpeozW5DpL4spauZ8DmfCjdHRSGfJ+JcN3mj8VIFof8CfUTKaPkhsrIVvjxtPLxAcHJtGG020KnErVJbGie/3V4Fu9vTCRJhKw4LYDM2E6kOELU4N3oxvPGo5Y+Xu7NmivpmZkORvQNt5mGOhAx6ggW853ss6lA1UK4ZMf4++XMsfxeJDQZzeHDb///36Ua5lA BNsGxrGD Y4ju8hvYtP3QUV2vICqTZVY1fSdS6MNFeEUa6ZfwJWGM/GeNULG+/+Ry0XdVAhEZrMeiCm8jmjSAXQo+Ej6KR4cjo8A44DLV1SHrFOJ6UYztgxtETJgg952bbodg5WwKwckhM80vnkSyMZLrW9i12dSPJIwhv4YPA6QnKFddDoEIBDOhlemP9kDURQBC9F2flT1w+nCQXSK2BkWQ70RE0LWFAZ+1fQcDFrejS7IergdjxiAdmiTjchLaFQg== X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: Add 'lx-slabinfo' and 'lx-slabtrace' support. This GDB scripts print slabinfo and slabtrace for user to analyze slab memory usage. Example output like below: (gdb) lx-slabinfo Pointer | name | active_objs | num_objs | objsize | objperslab | pagesperslab ------------------ | -------------------- | ------------ | ------------ | -------- | ----------- | ------------- 0xffff0000c59df480 | p9_req_t | 0 | 0 | 280 | 29 | 2 0xffff0000c59df280 | isp1760_qh | 0 | 0 | 160 | 25 | 1 0xffff0000c59df080 | isp1760_qtd | 0 | 0 | 184 | 22 | 1 0xffff0000c59dee80 | isp1760_urb_listite | 0 | 0 | 136 | 30 | 1 0xffff0000c59dec80 | asd_sas_event | 0 | 0 | 256 | 32 | 2 0xffff0000c59dea80 | sas_task | 0 | 0 | 448 | 36 | 4 0xffff0000c59de880 | bio-120 | 18 | 21 | 384 | 21 | 2 0xffff0000c59de680 | io_kiocb | 0 | 0 | 448 | 36 | 4 0xffff0000c59de480 | bfq_io_cq | 0 | 0 | 1504 | 21 | 8 0xffff0000c59de280 | bfq_queue | 0 | 0 | 720 | 22 | 4 0xffff0000c59de080 | mqueue_inode_cache | 1 | 28 | 1152 | 28 | 8 0xffff0000c59dde80 | v9fs_inode_cache | 0 | 0 | 832 | 39 | 8 ... (gdb) lx-slabtrace --cache_name kmalloc-1k 63 waste=16632/264 age=46856/46871/46888 pid=1 cpus=6, 0xffff800008720240 <__kmem_cache_alloc_node+236>: mov x22, x0 0xffff80000862a4fc : mov x21, x0 0xffff8000095d086c : mov x19, x0 0xffff8000095d0f98 : cmn x0, #0x1, lsl #12 0xffff80000c2677e8 : Cannot access memory at address 0xffff80000c2677e8 0xffff80000c265a10 : Cannot access memory at address 0xffff80000c265a10 0xffff80000c26d3c4 : Cannot access memory at address 0xffff80000c26d3c4 0xffff8000080161d4 : mov w21, w0 0xffff80000c1c1b58 : Cannot access memory at address 0xffff80000c1c1b58 0xffff80000acf1334 : bl 0xffff8000081ac040 0xffff800008018d00 : mrs x28, sp_el0 (gdb) lx-slabtrace --cache_name kmalloc-1k --free 428 age=4294958600 pid=0 cpus=0, Signed-off-by: Kuan-Ying Lee --- scripts/gdb/linux/constants.py.in | 13 ++ scripts/gdb/linux/slab.py | 322 ++++++++++++++++++++++++++++++ scripts/gdb/vmlinux-gdb.py | 1 + 3 files changed, 336 insertions(+) create mode 100644 scripts/gdb/linux/slab.py diff --git a/scripts/gdb/linux/constants.py.in b/scripts/gdb/linux/constants.py.in index 7e375b89fb99..fa23f4e3546a 100644 --- a/scripts/gdb/linux/constants.py.in +++ b/scripts/gdb/linux/constants.py.in @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -99,6 +100,16 @@ if IS_BUILTIN(CONFIG_ARM64): LX_GDBPARSED(PAGE_EXT_OWNER) LX_GDBPARSED(PAGE_EXT_OWNER_ALLOCATED) +/* linux/slab.h */ +LX_GDBPARSED(SLAB_RED_ZONE) +LX_GDBPARSED(SLAB_POISON) +LX_GDBPARSED(SLAB_KMALLOC) +LX_GDBPARSED(SLAB_HWCACHE_ALIGN) +LX_GDBPARSED(SLAB_CACHE_DMA) +LX_GDBPARSED(SLAB_CACHE_DMA32) +LX_GDBPARSED(SLAB_STORE_USER) +LX_GDBPARSED(SLAB_PANIC) + /* Kernel Configs */ LX_CONFIG(CONFIG_GENERIC_CLOCKEVENTS) LX_CONFIG(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST) @@ -140,3 +151,5 @@ if IS_BUILTIN(CONFIG_NUMA): LX_CONFIG(CONFIG_DEBUG_VIRTUAL) LX_CONFIG(CONFIG_STACKDEPOT) LX_CONFIG(CONFIG_PAGE_OWNER) +LX_CONFIG(CONFIG_SLUB_DEBUG) +LX_CONFIG(CONFIG_SLAB_FREELIST_HARDENED) diff --git a/scripts/gdb/linux/slab.py b/scripts/gdb/linux/slab.py new file mode 100644 index 000000000000..665bd249f2fb --- /dev/null +++ b/scripts/gdb/linux/slab.py @@ -0,0 +1,322 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (c) 2023 MediaTek Inc. +# +# Authors: +# Kuan-Ying Lee +# + +import gdb +import re +import traceback +from linux import lists, utils, stackdepot, constants, mm + +SLAB_RED_ZONE = constants.LX_SLAB_RED_ZONE +SLAB_POISON = constants.LX_SLAB_POISON +SLAB_KMALLOC = constants.LX_SLAB_KMALLOC +SLAB_HWCACHE_ALIGN = constants.LX_SLAB_HWCACHE_ALIGN +SLAB_CACHE_DMA = constants.LX_SLAB_CACHE_DMA +SLAB_CACHE_DMA32 = constants.LX_SLAB_CACHE_DMA32 +SLAB_STORE_USER = constants.LX_SLAB_STORE_USER +SLAB_PANIC = constants.LX_SLAB_PANIC + +OO_SHIFT = 16 +OO_MASK = (1 << OO_SHIFT) - 1 + +slab_type = utils.CachedType("struct slab") +slab_ptr_type = slab_type.get_type().pointer() +kmem_cache_type = utils.CachedType("struct kmem_cache") +kmem_cache_ptr_type = kmem_cache_type.get_type().pointer() + +track_type = gdb.lookup_type('struct track') +track_alloc = int(gdb.parse_and_eval('TRACK_ALLOC')) +track_free = int(gdb.parse_and_eval('TRACK_FREE')) + +def slab_folio(slab): + return slab.cast(gdb.lookup_type("struct folio").pointer()) + +def slab_address(slab): + p_ops = mm.page_ops().ops + folio = slab_folio(slab) + return p_ops.folio_address(folio) + +def for_each_object(cache, addr, slab_objects): + p = addr + if cache['flags'] & SLAB_RED_ZONE: + p += int(cache['red_left_pad']) + while p < addr + (slab_objects * cache['size']): + yield p + p = p + int(cache['size']) + +def get_info_end(cache): + if (cache['offset'] >= cache['inuse']): + return cache['inuse'] + gdb.lookup_type("void").pointer().sizeof + else: + return cache['inuse'] + +def get_orig_size(cache, obj): + if cache['flags'] & SLAB_STORE_USER and cache['flags'] & SLAB_KMALLOC: + p = mm.page_ops().ops.kasan_reset_tag(obj) + p += get_info_end(cache) + p += gdb.lookup_type('struct track').sizeof * 2 + p = p.cast(utils.get_uint_type().pointer()) + return p.dereference() + else: + return cache['object_size'] + +def get_track(cache, object_pointer, alloc): + p = object_pointer + get_info_end(cache) + p += (alloc * track_type.sizeof) + return p + +def oo_objects(x): + return int(x['x']) & OO_MASK + +def oo_order(x): + return int(x['x']) >> OO_SHIFT + +def reciprocal_divide(a, R): + t = (a * int(R['m'])) >> 32 + return (t + ((a - t) >> int(R['sh1']))) >> int(R['sh2']) + +def __obj_to_index(cache, addr, obj): + return reciprocal_divide(int(mm.page_ops().ops.kasan_reset_tag(obj)) - addr, cache['reciprocal_size']) + +def swab64(x): + result = (((x & 0x00000000000000ff) << 56) | \ + ((x & 0x000000000000ff00) << 40) | \ + ((x & 0x0000000000ff0000) << 24) | \ + ((x & 0x00000000ff000000) << 8) | \ + ((x & 0x000000ff00000000) >> 8) | \ + ((x & 0x0000ff0000000000) >> 24) | \ + ((x & 0x00ff000000000000) >> 40) | \ + ((x & 0xff00000000000000) >> 56)) + return result + +def freelist_ptr(cache, ptr, ptr_addr): + if constants.LX_CONFIG_SLAB_FREELIST_HARDENED: + return ptr ^ cache['random'] ^ swab64(int(ptr_addr)) + else: + return ptr + +def freelist_dereference(cache, ptr_addr): + ptr = ptr_addr.cast(utils.get_ulong_type().pointer()).dereference() + return freelist_ptr(cache, ptr, ptr_addr) + +def get_freepointer(cache, obj): + obj = mm.page_ops().ops.kasan_reset_tag(obj) + return freelist_dereference(cache, obj + cache['offset']) + +def loc_exist(loc_track, addr, handle, waste): + for loc in loc_track: + if loc['addr'] == addr and loc['handle'] == handle and loc['waste'] == waste: + return loc + return None + +def add_location(loc_track, cache, track, orig_size): + jiffies = gdb.parse_and_eval("jiffies_64") + age = jiffies - track['when'] + handle = 0 + waste = cache['object_size'] - int(orig_size) + pid = int(track['pid']) + cpuid = int(track['cpu']) + addr = track['addr'] + if constants.LX_CONFIG_STACKDEPOT: + handle = track['handle'] + + loc = loc_exist(loc_track, addr, handle, waste) + if loc: + loc['count'] += 1 + if track['when']: + loc['sum_time'] += age + loc['min_time'] = min(loc['min_time'], age) + loc['max_time'] = max(loc['max_time'], age) + loc['min_pid'] = min(loc['min_pid'], pid) + loc['max_pid'] = max(loc['max_pid'], pid) + loc['cpus'].add(cpuid) + else: + loc_track.append({ + 'count' : 1, + 'addr' : addr, + 'sum_time' : age, + 'min_time' : age, + 'max_time' : age, + 'min_pid' : pid, + 'max_pid' : pid, + 'handle' : handle, + 'waste' : waste, + 'cpus' : {cpuid} + } + ) + +def slabtrace(alloc, cache_name): + + def __fill_map(obj_map, cache, slab): + p = slab['freelist'] + addr = slab_address(slab) + while p != gdb.Value(0): + index = __obj_to_index(cache, addr, p) + obj_map[index] = True # free objects + p = get_freepointer(cache, p) + + # process every slab page on the slab_list (partial and full list) + def process_slab(loc_track, slab_list, alloc, cache): + for slab in lists.list_for_each_entry(slab_list, slab_ptr_type, "slab_list"): + obj_map[:] = [False] * oo_objects(cache['oo']) + __fill_map(obj_map, cache, slab) + addr = slab_address(slab) + for object_pointer in for_each_object(cache, addr, slab['objects']): + if obj_map[__obj_to_index(cache, addr, object_pointer)] == True: + continue + p = get_track(cache, object_pointer, alloc) + track = gdb.Value(p).cast(track_type.pointer()) + if alloc == track_alloc: + size = get_orig_size(cache, object_pointer) + else: + size = cache['object_size'] + add_location(loc_track, cache, track, size) + continue + + slab_caches = gdb.parse_and_eval("slab_caches") + if mm.page_ops().ops.MAX_NUMNODES > 1: + nr_node_ids = int(gdb.parse_and_eval("nr_node_ids")) + else: + nr_node_ids = 1 + + target_cache = None + loc_track = [] + + for cache in lists.list_for_each_entry(slab_caches, kmem_cache_ptr_type, 'list'): + if cache['name'].string() == cache_name: + target_cache = cache + break + + obj_map = [False] * oo_objects(target_cache['oo']) + + if target_cache['flags'] & SLAB_STORE_USER: + for i in range(0, nr_node_ids): + cache_node = target_cache['node'][i] + if cache_node['nr_slabs']['counter'] == 0: + continue + process_slab(loc_track, cache_node['partial'], alloc, target_cache) + process_slab(loc_track, cache_node['full'], alloc, target_cache) + else: + raise gdb.GdbError("SLAB_STORE_USER is not set in %s" % target_cache['name'].string()) + + for loc in sorted(loc_track, key=lambda x:x['count'], reverse=True): + if loc['addr']: + addr = loc['addr'].cast(utils.get_ulong_type().pointer()) + gdb.write("%d %s" % (loc['count'], str(addr).split(' ')[-1])) + else: + gdb.write("%d " % loc['count']) + + if loc['waste']: + gdb.write(" waste=%d/%d" % (loc['count'] * loc['waste'], loc['waste'])) + + if loc['sum_time'] != loc['min_time']: + gdb.write(" age=%d/%d/%d" % (loc['min_time'], loc['sum_time']/loc['count'], loc['max_time'])) + else: + gdb.write(" age=%d" % loc['min_time']) + + if loc['min_pid'] != loc['max_pid']: + gdb.write(" pid=%d-%d" % (loc['min_pid'], loc['max_pid'])) + else: + gdb.write(" pid=%d" % loc['min_pid']) + + if constants.LX_NR_CPUS > 1: + nr_cpu = gdb.parse_and_eval('__num_online_cpus')['counter'] + if nr_cpu > 1: + gdb.write(" cpus=") + for i in loc['cpus']: + gdb.write("%d," % i) + gdb.write("\n") + if constants.LX_CONFIG_STACKDEPOT: + if loc['handle']: + stackdepot.stack_depot_print(loc['handle']) + gdb.write("\n") + +def help(): + t = """Usage: lx-slabtrace --cache_name [cache_name] [Options] + Options: + --alloc + print information of allocation trace of the allocated objects + --free + print information of freeing trace of the allocated objects + Example: + lx-slabtrace --cache_name kmalloc-1k --alloc + lx-slabtrace --cache_name kmalloc-1k --free\n""" + gdb.write("Unrecognized command\n") + raise gdb.GdbError(t) + +class LxSlabTrace(gdb.Command): + """Show specific cache slabtrace""" + + def __init__(self): + super(LxSlabTrace, self).__init__("lx-slabtrace", gdb.COMMAND_DATA) + + def invoke(self, arg, from_tty): + argv = gdb.string_to_argv(arg) + alloc = track_alloc # default show alloc_traces + + if len(argv) == 3: + if argv[2] == '--alloc': + alloc = track_alloc + elif argv[2] == '--free': + alloc = track_free + else: + help() + if len(argv) >= 2 and argv[0] == '--cache_name': + slabtrace(alloc, argv[1]) + else: + help() +LxSlabTrace() + +def slabinfo(): + nr_node_ids = None + + if not constants.LX_CONFIG_SLUB_DEBUG: + raise gdb.GdbError("CONFIG_SLUB_DEBUG is not enabled") + + def count_free(slab): + total_free = 0 + for slab in lists.list_for_each_entry(slab, slab_ptr_type, 'slab_list'): + total_free += int(slab['objects'] - slab['inuse']) + return total_free + + gdb.write("{:^18} | {:^20} | {:^12} | {:^12} | {:^8} | {:^11} | {:^13}\n".format('Pointer', 'name', 'active_objs', 'num_objs', 'objsize', 'objperslab', 'pagesperslab')) + gdb.write("{:-^18} | {:-^20} | {:-^12} | {:-^12} | {:-^8} | {:-^11} | {:-^13}\n".format('', '', '', '', '', '', '')) + + slab_caches = gdb.parse_and_eval("slab_caches") + if mm.page_ops().ops.MAX_NUMNODES > 1: + nr_node_ids = int(gdb.parse_and_eval("nr_node_ids")) + else: + nr_node_ids = 1 + + for cache in lists.list_for_each_entry(slab_caches, kmem_cache_ptr_type, 'list'): + nr_objs = 0 + nr_free = 0 + nr_slabs = 0 + for i in range(0, nr_node_ids): + cache_node = cache['node'][i] + try: + nr_slabs += cache_node['nr_slabs']['counter'] + nr_objs = int(cache_node['total_objects']['counter']) + nr_free = count_free(cache_node['partial']) + except: + raise gdb.GdbError(traceback.format_exc()) + active_objs = nr_objs - nr_free + num_objs = nr_objs + active_slabs = nr_slabs + objects_per_slab = oo_objects(cache['oo']) + cache_order = oo_order(cache['oo']) + gdb.write("{:18s} | {:20.19s} | {:12} | {:12} | {:8} | {:11} | {:13}\n".format(hex(cache), cache['name'].string(), str(active_objs), str(num_objs), str(cache['size']), str(objects_per_slab), str(1 << cache_order))) + +class LxSlabInfo(gdb.Command): + """Show slabinfo""" + + def __init__(self): + super(LxSlabInfo, self).__init__("lx-slabinfo", gdb.COMMAND_DATA) + + def invoke(self, arg, from_tty): + slabinfo() +LxSlabInfo() diff --git a/scripts/gdb/vmlinux-gdb.py b/scripts/gdb/vmlinux-gdb.py index 89465f0de548..2526364f31fd 100644 --- a/scripts/gdb/vmlinux-gdb.py +++ b/scripts/gdb/vmlinux-gdb.py @@ -47,3 +47,4 @@ else: import linux.mm import linux.stackdepot import linux.page_owner + import linux.slab