From patchwork Tue Dec 7 04:02:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xin Long X-Patchwork-Id: 12661009 X-Patchwork-Delegate: kuba@kernel.org 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 715DCC433F5 for ; Tue, 7 Dec 2021 04:02:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234662AbhLGEFm (ORCPT ); Mon, 6 Dec 2021 23:05:42 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39608 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231678AbhLGEFm (ORCPT ); Mon, 6 Dec 2021 23:05:42 -0500 Received: from mail-qt1-x82e.google.com (mail-qt1-x82e.google.com [IPv6:2607:f8b0:4864:20::82e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 94980C061746 for ; Mon, 6 Dec 2021 20:02:12 -0800 (PST) Received: by mail-qt1-x82e.google.com with SMTP id j17so13120579qtx.2 for ; Mon, 06 Dec 2021 20:02:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=KBG6tNJjIQsq9v3D23PK7hQYlXfoAIJAKhzUZoQd6FI=; b=AZbnpbR6YDSwiqE/J4Lexv/JK/stcgXYgK1xyier52Sk1dBnhh2mI4Agm9i3r2+ozy 3mYgSEeOkk90DOucewuhNicw54rth2zLFywsHCoe1Q8FURlx8kOINfgH8JciI6GGS2Iy c6n+Dc7zYGmoPLQ1D4Yx4y4T49LgenRHtcgVYrrc8vV4zmPM92v5gCIUQI7t3qS85jJN e5sqRcCSkFmz2to/FwI2Y+u/0urLka6880tnjTbGHCVBJhV//lXCJ/Ypg62VlbFZd/Qb AD31AyjlijyPoFZr2oZE6yLce6bgIjyVHPs8j7wtno7cPd2SXGKfhTD6MsQMFWlr9bZK SZ6w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=KBG6tNJjIQsq9v3D23PK7hQYlXfoAIJAKhzUZoQd6FI=; b=n1jbMLSyNoObiDF8L9apCzF9+Lf7yxVO0pMGfNF1x3c9J37+gkCHAxymR1l3IdaHAN Fnh9F7Dixjey4U2PgVtoHBVEcuU/g4KY6PXpeDxaSr7XmZyzRZG77/H8MeJm2nfzblEg jTOfspKJ1UpEPXuhpOP4EFhGvjqUv5NQVcsJkEhAh1KU1SiLDnvTlf1YJ0UmiLsUXdRD qOjg4WyzwsXYFz8ryujklKdoQs49QXW+jdbMpUo4GDKLV6UO5we0DPWRF1auEGn8vgHS aujk9iUG1Eiq/7phT4EAU/o/itP8GUrsfhEXDQeaoEnhbiVXESnnVfgkuusB86b6BQZI k9Zg== X-Gm-Message-State: AOAM5335V81BFxCigA9jz8nYi80FRNx0A/M+90MARTnvEwXNLLGeD3rw /7H/OBSf7doTYTwC/E8as94afaGUi3HcRA== X-Google-Smtp-Source: ABdhPJymQ4SeMaIGg8wZ2a3sUfpYp9jFY5qAj8hDdwgSaQ/LxFtJ0cfTGT1AShjKk5t0O3M5FIj3Dw== X-Received: by 2002:a05:622a:1812:: with SMTP id t18mr44682606qtc.455.1638849731540; Mon, 06 Dec 2021 20:02:11 -0800 (PST) Received: from wsfd-netdev15.ntdv.lab.eng.bos.redhat.com (nat-pool-bos-t.redhat.com. [66.187.233.206]) by smtp.gmail.com with ESMTPSA id 14sm8526393qtx.84.2021.12.06.20.02.10 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Dec 2021 20:02:11 -0800 (PST) From: Xin Long To: network dev Cc: Eric Dumazet , davem@davemloft.net, kuba@kernel.org, Marcelo Ricardo Leitner , Davide Caratti , Paolo Abeni Subject: [PATCH net-next 1/5] lib: add obj_cnt infrastructure Date: Mon, 6 Dec 2021 23:02:04 -0500 Message-Id: <0179540815c25f6fbcf0d350ef118fb1a9330698.1638849511.git.lucien.xin@gmail.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org This patch is to create a lib to counter any operatings to objects, the same call to operate the same object will be saved as one node which includes the call trace and object pointer, and the counter in the node will increase next time when the same call comes to this object. There are a few sysctl parameters are exposed to users: 1. Three of them are used to filter the calls with the objects: - index a 'int' type that can be used to match objects, such as netdev's index for netdev, and xfrm_state's spi for xfrm_state; - name a 'char *' type that can be used to match objects, such as netdev's name for netdev, and dst->dev's name for dst. - type a 'bitmap' that can be used to mark which operating is allowed to be counted, such as dev_hold, dev_put, inet6_hold, inet6_put. 2. One is used to 'clear' or 'scan' the test result: - control it uses 'clear' to drop all nodes from the hashtable, and 'scan' to print out the details of all counter nodes. 3. Another one is used to set up the stack depth we want to save: - nr_entries how detailed is a call trace it wants to use (1 to 16), the bigger it set to, the more nodes might be created, as the call might come with different call traces. There are 2 APIs are exported for developers to count any calls to operate objects they want: 1. void obj_cnt_track(type, index, name, obj); check if this call can be matched with type and this object can be matched with any of index, name and obj. If yes, record this call to operate one obj, and create a node including this obj and calli trace if it doesn't exist in the hashtable, and increment the count of this node if it exists. 2. void obj_cnt_set(index, name, obj); this won't be used unless a developer want to set the match condition somewhere in kernel code, especially to match with obj. This lib can typically be used to track one object's refcnt, and all we have to do is put obj_cnt_track() into this object's hold and put functions. More details, see the following patches. Signed-off-by: Xin Long --- include/linux/obj_cnt.h | 12 ++ lib/Kconfig.debug | 7 + lib/Makefile | 1 + lib/obj_cnt.c | 277 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 297 insertions(+) create mode 100644 include/linux/obj_cnt.h create mode 100644 lib/obj_cnt.c diff --git a/include/linux/obj_cnt.h b/include/linux/obj_cnt.h new file mode 100644 index 000000000000..e5185f7022d1 --- /dev/null +++ b/include/linux/obj_cnt.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef _LINUX_OBJ_CNT_H +#define _LINUX_OBJ_CNT_H + +enum { + OBJ_CNT_TYPE_MAX +}; + +void obj_cnt_track(int type, int index, char *name, void *obj); +void obj_cnt_set(int index, char *name, void *obj); + +#endif /* _LINUX_OBJ_CNT_H */ diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 6504b97f8dfd..2c9d14b98783 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -2665,6 +2665,13 @@ config HYPERV_TESTING endmenu # "Kernel Testing and Coverage" +config OBJ_CNT + bool "object operating counter" + select STACKTRACE + help + This lib provide several APIs to count some objects' operating, + and can be used to track refcnt. + source "Documentation/Kconfig" endmenu # Kernel hacking diff --git a/lib/Makefile b/lib/Makefile index b213a7bbf3fd..5dc53da2c0b2 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -271,6 +271,7 @@ KASAN_SANITIZE_stackdepot.o := n KCOV_INSTRUMENT_stackdepot.o := n obj-$(CONFIG_REF_TRACKER) += ref_tracker.o +obj-$(CONFIG_OBJ_CNT) += obj_cnt.o libfdt_files = fdt.o fdt_ro.o fdt_wip.o fdt_rw.o fdt_sw.o fdt_strerror.o \ fdt_empty_tree.o fdt_addresses.o diff --git a/lib/obj_cnt.c b/lib/obj_cnt.c new file mode 100644 index 000000000000..19ced2303452 --- /dev/null +++ b/lib/obj_cnt.c @@ -0,0 +1,277 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +#include +#include +#include +#include +#include +#include + +#define OBJ_CNT_HASHENTRIES (1 << 8) +#define OBJ_CNT_MAX UINT_MAX +#define OBJ_CNT_NRENTRIES 16 +static struct kmem_cache *obj_cnt_cache __read_mostly; +static struct hlist_head *obj_cnt_head; +static unsigned int obj_cnt_num; +static spinlock_t obj_cnt_lock; + +static char *obj_cnt_str[OBJ_CNT_TYPE_MAX] = { +}; + +struct obj_cnt { + struct hlist_node hlist; + void *obj; /* the obj to count its operations */ + u64 cnt; /* how many times it's been operated */ + int type; /* operation to the obj like get put */ + unsigned long entries[OBJ_CNT_NRENTRIES]; /* the stack */ + unsigned int nr_entries; +}; + +static int obj_cnt_index; +static int obj_cnt_type; +static char obj_cnt_name[16]; +static void *obj_cnt_obj; +static int obj_cnt_nr_entries; +static int obj_cnt_max_nr_entries = OBJ_CNT_NRENTRIES; + +static inline struct hlist_head *obj_cnt_hash(unsigned long hash) +{ + return &obj_cnt_head[hash & (OBJ_CNT_HASHENTRIES - 1)]; +} + +static struct obj_cnt *obj_cnt_lookup(void *obj, int type, unsigned long entries[], + unsigned int nr_entries) +{ + struct hlist_head *head; + struct obj_cnt *oc; + + head = obj_cnt_hash(entries[0]); + hlist_for_each_entry(oc, head, hlist) + if (oc->obj == obj && oc->type == type && + oc->nr_entries == nr_entries && + !memcmp(oc->entries, entries, nr_entries * sizeof(unsigned long))) + return oc; + + return NULL; +} + +static struct obj_cnt *obj_cnt_create(void *obj, int type, unsigned long entries[], + unsigned int nr_entries) +{ + struct obj_cnt *oc; + + if (obj_cnt_num == OBJ_CNT_MAX - 1) { + pr_err("OBJ_CNT: %s: too many obj_cnt added\n", __func__); + return NULL; + } + oc = kmem_cache_alloc(obj_cnt_cache, GFP_ATOMIC); + if (!oc) { + pr_err("OBJ_CNT: %s: no memory\n", __func__); + return NULL; + } + oc->nr_entries = nr_entries; + memcpy(oc->entries, entries, nr_entries * sizeof(unsigned long)); + oc->obj = obj; + oc->cnt = 0; + oc->type = type; + hlist_add_head(&oc->hlist, obj_cnt_hash(oc->entries[0])); + obj_cnt_num++; + + return oc; +} + +static bool obj_cnt_allowed(int type, int index, char *name, void *obj) +{ + if (!(obj_cnt_type & (1 << type))) + return false; + if (index && index == obj_cnt_index) + return true; + if (name && !strcmp(name, obj_cnt_name)) + return true; + if (obj && obj == obj_cnt_obj) + return true; + return false; +} + +void obj_cnt_track(int type, int index, char *name, void *obj) +{ + unsigned long entries[OBJ_CNT_NRENTRIES]; + unsigned int nr_entries; + unsigned long flags; + struct obj_cnt *oc; + + if (!obj_cnt_allowed(type, index, name, obj)) + return; + + nr_entries = stack_trace_save(entries, obj_cnt_nr_entries, 1); + nr_entries = filter_irq_stacks(entries, nr_entries); + spin_lock_irqsave(&obj_cnt_lock, flags); /* TODO: use rcu lock for lookup */ + oc = obj_cnt_lookup(obj, type, entries, nr_entries); + if (!oc) + oc = obj_cnt_create(obj, type, entries, nr_entries); + if (oc) { + oc->cnt++; + WARN_ONCE(!oc->cnt, "OBJ_CNT: %s, the counter overflows\n", __func__); + pr_debug("OBJ_CNT: %s: obj: %px, type: %s, cnt: %llu, caller: %pS\n", + __func__, oc->obj, obj_cnt_str[oc->type], oc->cnt, (void *)oc->entries[0]); + } + spin_unlock_irqrestore(&obj_cnt_lock, flags); +} +EXPORT_SYMBOL(obj_cnt_track); + +static void obj_cnt_dump(void *obj, int type) +{ + struct hlist_head *head; + struct obj_cnt *oc; + int h, first = 1; + + spin_lock_bh(&obj_cnt_lock); + for (h = 0; h < OBJ_CNT_HASHENTRIES; h++) { + head = &obj_cnt_head[h]; + hlist_for_each_entry(oc, head, hlist) { + if ((type && oc->type != type) || (obj && oc->obj != obj)) + continue; + if (first) { + pr_info("OBJ_CNT: results =>\n"); + first = 0; + } + pr_info("OBJ_CNT: %s: obj: %px, type: %s, cnt: %llu, caller: %pS, calltrace:\n", + __func__, oc->obj, obj_cnt_str[oc->type], oc->cnt, (void *)oc->entries[0]); + if (oc->nr_entries > 1) + stack_trace_print(oc->entries, oc->nr_entries, 4); + } + } + spin_unlock_bh(&obj_cnt_lock); +} + +void obj_cnt_set(int index, char *name, void *obj) +{ + if (name) + strncpy(obj_cnt_name, name, min_t(size_t, 16, strlen(name))); + if (index) + obj_cnt_index = index; + if (obj) + obj_cnt_obj = obj; +} +EXPORT_SYMBOL(obj_cnt_set); + +static void obj_cnt_free(void) +{ + struct hlist_head *head; + struct hlist_node *tmp; + struct obj_cnt *oc; + int h; + + spin_lock_bh(&obj_cnt_lock); + for (h = 0; h < OBJ_CNT_HASHENTRIES; h++) { + head = &obj_cnt_head[h]; + hlist_for_each_entry_safe(oc, tmp, head, hlist) { + hlist_del(&oc->hlist); + kmem_cache_free(obj_cnt_cache, oc); + } + } + obj_cnt_num = 0; + spin_unlock_bh(&obj_cnt_lock); +} + +static int proc_docntcmd(struct ctl_table *table, int write, void *buffer, + size_t *lenp, loff_t *ppos) +{ + struct ctl_table tbl; + char cmd[8] = {0}; + int ret; + + if (!write) + return -EINVAL; + + memset(&tbl, 0, sizeof(struct ctl_table)); + tbl.data = cmd; + tbl.maxlen = sizeof(cmd); + ret = proc_dostring(&tbl, write, buffer, lenp, ppos); + if (ret) + return ret; + + if (!strcmp(cmd, "clear")) + obj_cnt_free(); + else if (!strcmp(cmd, "scan")) + obj_cnt_dump(NULL, 0); + else + return -EINVAL; + return 0; +} + +static struct ctl_table obj_cnt_table[] = { + { + .procname = "index", + .data = &obj_cnt_index, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec + }, + { + .procname = "name", + .data = obj_cnt_name, + .maxlen = 16, + .mode = 0644, + .proc_handler = proc_dostring + }, + { + .procname = "type", + .data = &obj_cnt_type, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec + }, + { + .procname = "control", + .maxlen = 16, + .mode = 0200, + .proc_handler = proc_docntcmd + }, + { + .procname = "nr_entries", + .data = &obj_cnt_nr_entries, + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, + .extra1 = SYSCTL_ONE, + .extra2 = &obj_cnt_max_nr_entries + }, + { } +}; + +static __init int obj_cnt_init(void) +{ + static struct ctl_table_header *hdr; + int i; + + memset(obj_cnt_name, 0, sizeof(obj_cnt_name)); + obj_cnt_index = 0; + obj_cnt_type = 0; + obj_cnt_obj = NULL; + obj_cnt_nr_entries = 8; + hdr = register_sysctl("obj_cnt", obj_cnt_table); + if (!hdr) + return -ENOMEM; + + obj_cnt_cache = kmem_cache_create("obj_cnt_cache", sizeof(struct obj_cnt), + 0, SLAB_HWCACHE_ALIGN, NULL); + if (!obj_cnt_cache) { + unregister_sysctl_table(hdr); + return -ENOMEM; + } + + obj_cnt_head = kmalloc_array(OBJ_CNT_HASHENTRIES, sizeof(*obj_cnt_head), + GFP_KERNEL); + if (!obj_cnt_head) { + kmem_cache_destroy(obj_cnt_cache); + unregister_sysctl_table(hdr); + return -ENOMEM; + } + for (i = 0; i < OBJ_CNT_HASHENTRIES; i++) + INIT_HLIST_HEAD(&obj_cnt_head[i]); + + spin_lock_init(&obj_cnt_lock); + return 0; +} + +subsys_initcall(obj_cnt_init); From patchwork Tue Dec 7 04:02:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xin Long X-Patchwork-Id: 12661011 X-Patchwork-Delegate: kuba@kernel.org 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1337FC433F5 for ; Tue, 7 Dec 2021 04:02:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234692AbhLGEFq (ORCPT ); Mon, 6 Dec 2021 23:05:46 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39610 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231678AbhLGEFn (ORCPT ); Mon, 6 Dec 2021 23:05:43 -0500 Received: from mail-qv1-xf2d.google.com (mail-qv1-xf2d.google.com [IPv6:2607:f8b0:4864:20::f2d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8DD3CC061746 for ; Mon, 6 Dec 2021 20:02:13 -0800 (PST) Received: by mail-qv1-xf2d.google.com with SMTP id bu11so11996968qvb.0 for ; Mon, 06 Dec 2021 20:02:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=6HDqaaXBBQ7MGDRLLbEs+u7qNrZqI377kTFfTyB8oTM=; b=jhhG3ZXkxCdU01jMRRJFp0V0HiiBqnXZ+xFOgzkiU8LOeRQT1Q16WIHiXDbq2eqNgX rMtyh6mweBEhdvnFFbMtMasxCjfvtcONc3I/XruJjVL+2wo508uawkzyUpvLbmKpBmJH eKu37+sNw9mfBzpO/Taur9sGroYF9Dhl+HnZoKL84AFXgIipZ08FFSJvuKK4XG9JmgAE O/Wk9Dzgh3A/RxvFgafcZtulHfQbbuet07Oer6DbZG329lTiX7eKdwZNAx4WdeMEIRrc mLOYCEDZL6ZKX/0VAzZ9oEP5ORMcfG/hbFO2ZqBXfjKinCMrbtak/BmaYEcma6QkPZoF OW7w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=6HDqaaXBBQ7MGDRLLbEs+u7qNrZqI377kTFfTyB8oTM=; b=Grt3FtF2rcPw/gZCOLTi2vluMwIeXoBPvPRgdH/pzBophda80A4AbiujZEOy9fnc4P 6KcHupKdnMXxLSzYiB9BoSVru+M7G+PqP/a3kFE4B0u7gFet5MRlg5iPXUzdGP2J3fG3 7DzvqPi3A9dTOTbZWXqS9jSIiJMn8wX/GsF0fN0o4VQLBSALc0SW+A6wIxlSxLDwRhAj vwFQN40Yg3N4YAxjo/VtKZ5nclr66Iv/xn7HmjOWz1ABwRsVhzc4nYxbHjxYe9xJr7y8 L2DamBuZFDZb5WIPF5Tdt8OfXZnilw2Xfx+i2yem/cxzji7jL7Sl+UuMz7CC5TzoFKlK Z43A== X-Gm-Message-State: AOAM5324FoP7mWqnwH6YXg8AJ6bJB+ebQYuAkkzGtUq1NGllMHBfjm5s koyh1HITri1CbdwLmG9cVbPRDal0L/Bx/A== X-Google-Smtp-Source: ABdhPJyErIzJcxpyXgxLng4cDQxR9b+Lt08oev8kVH67ksi4N7E9ML0idoS2faRYolAUtOweJj6uZA== X-Received: by 2002:ad4:56a6:: with SMTP id bd6mr41772010qvb.129.1638849732565; Mon, 06 Dec 2021 20:02:12 -0800 (PST) Received: from wsfd-netdev15.ntdv.lab.eng.bos.redhat.com (nat-pool-bos-t.redhat.com. [66.187.233.206]) by smtp.gmail.com with ESMTPSA id 14sm8526393qtx.84.2021.12.06.20.02.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Dec 2021 20:02:12 -0800 (PST) From: Xin Long To: network dev Cc: Eric Dumazet , davem@davemloft.net, kuba@kernel.org, Marcelo Ricardo Leitner , Davide Caratti , Paolo Abeni Subject: [PATCH net-next 2/5] net: track netdev refcnt with obj_cnt Date: Mon, 6 Dec 2021 23:02:05 -0500 Message-Id: X-Mailer: git-send-email 2.27.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Two types are added into obj_cnt to count dev_hold and dev_put, and all it does is put obj_cnt_track_by_dev() into these two functions. Here is an example to track the refcnt of a netdev named dummy0: # sysctl -w obj_cnt.control="clear" # clear the old result # sysctl -w obj_cnt.type=0x3 # enable dev_hold/put track # sysctl -w obj_cnt.name=dummy0 # count dev_hold/put(dummy0) # sysctl -w obj_cnt.nr_entries=4 # save 4 frames' call trace # ip link add dummy0 type dummy # ip link set dummy0 up # ip link set dummy0 down # ip link del dummy0 # sysctl -w obj_cnt.control="scan" # print the new result # dmesg OBJ_CNT: obj_cnt_dump: obj: ffff894402397000, type: dev_put, cnt: 1,: in_dev_finish_destroy+0x6a/0x80 rcu_do_batch+0x164/0x4b0 rcu_core+0x249/0x350 __do_softirq+0xf5/0x2ea OBJ_CNT: obj_cnt_dump: obj: ffff894402397000, type: dev_hold, cnt: 1,: inetdev_init+0xff/0x1c0 inetdev_event+0x4b7/0x600 raw_notifier_call_chain+0x41/0x50 register_netdevice+0x481/0x580 ... OBJ_CNT: obj_cnt_dump: obj: ffff894402397000, type: dev_put, cnt: 1,: rx_queue_release+0xa8/0xb0 kobject_release+0x43/0x140 net_rx_queue_update_kobjects+0x13c/0x190 netdev_unregister_kobject+0x4a/0x80 OBJ_CNT: obj_cnt_dump: obj: ffff894402397000, type: dev_put, cnt: 3,: fib_nh_common_release+0x10f/0x120 fib6_info_destroy_rcu+0x73/0xc0 rcu_do_batch+0x164/0x4b0 rcu_core+0x249/0x350 ... Signed-off-by: Xin Long --- include/linux/netdevice.h | 11 +++++++++++ include/linux/obj_cnt.h | 2 ++ lib/obj_cnt.c | 2 ++ 3 files changed, 15 insertions(+) diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 69dca1edd5a6..4cbcd34829da 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -49,6 +49,7 @@ #include #include #include +#include struct netpoll_info; struct device; @@ -3815,6 +3816,14 @@ extern unsigned int netdev_budget_usecs; /* Called by rtnetlink.c:rtnl_unlock() */ void netdev_run_todo(void); +static inline void obj_cnt_track_by_dev(void *obj, struct net_device *dev, int type) +{ +#ifdef CONFIG_OBJ_CNT + if (dev) + obj_cnt_track(type, dev->ifindex, dev->name, obj); +#endif +} + /** * dev_put - release reference to device * @dev: network device @@ -3825,6 +3834,7 @@ void netdev_run_todo(void); static inline void dev_put(struct net_device *dev) { if (dev) { + obj_cnt_track_by_dev(dev, dev, OBJ_CNT_DEV_PUT); #ifdef CONFIG_PCPU_DEV_REFCNT this_cpu_dec(*dev->pcpu_refcnt); #else @@ -3843,6 +3853,7 @@ static inline void dev_put(struct net_device *dev) static inline void dev_hold(struct net_device *dev) { if (dev) { + obj_cnt_track_by_dev(dev, dev, OBJ_CNT_DEV_HOLD); #ifdef CONFIG_PCPU_DEV_REFCNT this_cpu_inc(*dev->pcpu_refcnt); #else diff --git a/include/linux/obj_cnt.h b/include/linux/obj_cnt.h index e5185f7022d1..bb2d37484a32 100644 --- a/include/linux/obj_cnt.h +++ b/include/linux/obj_cnt.h @@ -3,6 +3,8 @@ #define _LINUX_OBJ_CNT_H enum { + OBJ_CNT_DEV_HOLD, + OBJ_CNT_DEV_PUT, OBJ_CNT_TYPE_MAX }; diff --git a/lib/obj_cnt.c b/lib/obj_cnt.c index 19ced2303452..12a1fdafd632 100644 --- a/lib/obj_cnt.c +++ b/lib/obj_cnt.c @@ -15,6 +15,8 @@ static unsigned int obj_cnt_num; static spinlock_t obj_cnt_lock; static char *obj_cnt_str[OBJ_CNT_TYPE_MAX] = { + "dev_hold", + "dev_put" }; struct obj_cnt { From patchwork Tue Dec 7 04:02:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xin Long X-Patchwork-Id: 12661013 X-Patchwork-Delegate: kuba@kernel.org 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 61F0EC433F5 for ; Tue, 7 Dec 2021 04:02:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234674AbhLGEFr (ORCPT ); Mon, 6 Dec 2021 23:05:47 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39618 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234664AbhLGEFo (ORCPT ); Mon, 6 Dec 2021 23:05:44 -0500 Received: from mail-qt1-x82e.google.com (mail-qt1-x82e.google.com [IPv6:2607:f8b0:4864:20::82e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 75371C061354 for ; Mon, 6 Dec 2021 20:02:14 -0800 (PST) Received: by mail-qt1-x82e.google.com with SMTP id m25so13057660qtq.13 for ; Mon, 06 Dec 2021 20:02:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=MJ0RHEHh6iPlP/wHXmf9A30Q7rZb8zmv5AU20e7Fpng=; b=E6Ev3+v3Z3b/2saNHSHfbMlXQ4a0AT/Bdl8j+pgS20sjZk8PL2yxalNcINW/0rdGpf V6HHNwUAxes+ZFhp6tH0gsu8tdyv+lPeAB4VckdG5Ahe5XeSOGL7z7x4782LsxQTy7AG tVGD9q3jQvV4yeMHPUsYaUM4Z0u7dTLhpz5RuAiKkTqHoIOBW55jIYkiHRLokFiiM8/+ F8/WZYyXpcsdW9tgyhRlhM/goB3zLnHoPjn2/0VmCGI/ssIVK8t+eLi4Rb67bQo0VC/c 2zuvaSUR+xIffqa6oj4zadsqmugbQ2Z6hc+LV7PEDo00LarB6mYGwsxisv3uOqdFsNIF JMcA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=MJ0RHEHh6iPlP/wHXmf9A30Q7rZb8zmv5AU20e7Fpng=; b=MD9Bk1MJR5517YIoY3KwR5ViW3pkZk63FlwyCe+0O7Jw3XGDBmnUjfv3kxG3ltD1/G 37FuNMhKtr4a6xleUxervRmZ9jHwJSfERj1HdYe4FQNHgZkqG/hDMetazy0wuEMhDS4a +2I7UfhlPxU9KNuZWuLOsVdvIk4WtnZaPzxUVJksOSodxEZMuazouoyQcSdMhgFWem4H Kyxnopx4cux4tN66MaKLCh4Gh+zAjOwG8vkvquofaZWeLhnLYlmyxEztJQEhe7BxskBz ObIxKoo7VIF5eMXz8JwfNmXCK/zq0wPgqJqr54/8ZdbU5bUwfPwL29Y4PqcAymTTIQZM ufMg== X-Gm-Message-State: AOAM530iogBUjYphMyhGmsdZAK/Jgle3hgLkeA9rPjOE/ve8Nbx/fgbF MCwluuCShFFNZjSu+c3nm72Y/sD2R6H8Aw== X-Google-Smtp-Source: ABdhPJxBrX5wLP1E4lG8I+DilBK9gQDVtVsEk09pD767Svcp3tB5L8oqoKQoV8jkwJNOobdleHapXw== X-Received: by 2002:ac8:7d50:: with SMTP id h16mr46871829qtb.324.1638849733511; Mon, 06 Dec 2021 20:02:13 -0800 (PST) Received: from wsfd-netdev15.ntdv.lab.eng.bos.redhat.com (nat-pool-bos-t.redhat.com. [66.187.233.206]) by smtp.gmail.com with ESMTPSA id 14sm8526393qtx.84.2021.12.06.20.02.12 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Dec 2021 20:02:13 -0800 (PST) From: Xin Long To: network dev Cc: Eric Dumazet , davem@davemloft.net, kuba@kernel.org, Marcelo Ricardo Leitner , Davide Caratti , Paolo Abeni Subject: [PATCH net-next 3/5] net: track dst refcnt with obj_cnt Date: Mon, 6 Dec 2021 23:02:06 -0500 Message-Id: <9dc7efe678baaafb5203da0c1f2b1127e88e81c5.1638849511.git.lucien.xin@gmail.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Two types are added into obj_cnt to count dst_hold* and dst_release*, and all it does is put obj_cnt_track_by_dev() into these two functions. Here is an example to track the refcnt of a dst whose dev is dummy0: # sysctl -w obj_cnt.control="clear" # clear the old result # sysctl -w obj_cnt.type=0xc # enable dst_hold/put track # sysctl -w obj_cnt.name=dummy0 # count dst_hold/put(dst) # sysctl -w obj_cnt.nr_entries=4 # save 4 frames' call trace # # ip link add dummy0 type dummy # ip link set dummy0 up # ip addr add 1.1.1.1/24 dev dummy0 # ping 1.1.1.2 -c 2 # ip link set dummy0 down # ip link del dummy0 # sysctl -w obj_cnt.control="scan" # print the new result # dmesg OBJ_CNT: obj_cnt_dump: obj: ffff9e45d7e8b780, type: dst_hold, cnt: 1,: rt_cache_route+0x45/0xc0 rt_set_nexthop.constprop.63+0x143/0x3c0 ip_route_output_key_hash_rcu+0x256/0x9a0 ip_route_output_key_hash+0x72/0xa0 OBJ_CNT: obj_cnt_dump: obj: ffff9e45cbef9100, type: dst_put, cnt: 1,: dst_release+0x2a/0x90 __dev_queue_xmit+0x72c/0xc90 ip6_finish_output2+0x2d2/0x660 ip6_output+0x6e/0x130 ... OBJ_CNT: obj_cnt_dump: obj: ffff9e45ca463d00, type: dst_put, cnt: 1,: dst_release+0x2a/0x90 __dev_queue_xmit+0x72c/0xc90 ip6_finish_output2+0x1e8/0x660 ip6_output+0x6e/0x130 OBJ_CNT: obj_cnt_dump: obj: ffff9e45d7e8b780, type: dst_hold, cnt: 2,: ip_route_output_key_hash_rcu+0x88e/0x9a0 ip_route_output_key_hash+0x72/0xa0 ip_route_output_flow+0x19/0x50 raw_sendmsg+0x32b/0xe40 ... Signed-off-by: Xin Long --- include/linux/obj_cnt.h | 2 ++ include/net/dst.h | 8 +++++++- include/net/sock.h | 3 ++- lib/obj_cnt.c | 4 +++- net/core/dst.c | 2 ++ 5 files changed, 16 insertions(+), 3 deletions(-) diff --git a/include/linux/obj_cnt.h b/include/linux/obj_cnt.h index bb2d37484a32..ae4c12beb876 100644 --- a/include/linux/obj_cnt.h +++ b/include/linux/obj_cnt.h @@ -5,6 +5,8 @@ enum { OBJ_CNT_DEV_HOLD, OBJ_CNT_DEV_PUT, + OBJ_CNT_DST_HOLD, + OBJ_CNT_DST_PUT, OBJ_CNT_TYPE_MAX }; diff --git a/include/net/dst.h b/include/net/dst.h index 6aa252c3fc55..e2704495d32f 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -227,6 +227,7 @@ static inline void dst_hold(struct dst_entry *dst) * If your kernel compilation stops here, please check * the placement of __refcnt in struct dst_entry */ + obj_cnt_track_by_dev(dst, dst->dev, OBJ_CNT_DST_HOLD); BUILD_BUG_ON(offsetof(struct dst_entry, __refcnt) & 63); WARN_ON(atomic_inc_not_zero(&dst->__refcnt) == 0); } @@ -298,7 +299,12 @@ static inline void skb_dst_copy(struct sk_buff *nskb, const struct sk_buff *oskb */ static inline bool dst_hold_safe(struct dst_entry *dst) { - return atomic_inc_not_zero(&dst->__refcnt); + if (atomic_inc_not_zero(&dst->__refcnt)) { + obj_cnt_track_by_dev(dst, dst->dev, OBJ_CNT_DST_HOLD); + return true; + } + + return false; } /** diff --git a/include/net/sock.h b/include/net/sock.h index ae61cd0b650d..07d59c27ac11 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -2071,8 +2071,9 @@ sk_dst_get(struct sock *sk) rcu_read_lock(); dst = rcu_dereference(sk->sk_dst_cache); - if (dst && !atomic_inc_not_zero(&dst->__refcnt)) + if (dst && !dst_hold_safe(dst)) dst = NULL; + rcu_read_unlock(); return dst; } diff --git a/lib/obj_cnt.c b/lib/obj_cnt.c index 12a1fdafd632..648adc135080 100644 --- a/lib/obj_cnt.c +++ b/lib/obj_cnt.c @@ -16,7 +16,9 @@ static spinlock_t obj_cnt_lock; static char *obj_cnt_str[OBJ_CNT_TYPE_MAX] = { "dev_hold", - "dev_put" + "dev_put", + "dst_hold", + "dst_put" }; struct obj_cnt { diff --git a/net/core/dst.c b/net/core/dst.c index d16c2c9bfebd..94ff1fe0fc09 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -169,6 +169,7 @@ void dst_release(struct dst_entry *dst) if (dst) { int newrefcnt; + obj_cnt_track_by_dev(dst, dst->dev, OBJ_CNT_DST_PUT); newrefcnt = atomic_dec_return(&dst->__refcnt); if (WARN_ONCE(newrefcnt < 0, "dst_release underflow")) net_warn_ratelimited("%s: dst:%p refcnt:%d\n", @@ -184,6 +185,7 @@ void dst_release_immediate(struct dst_entry *dst) if (dst) { int newrefcnt; + obj_cnt_track_by_dev(dst, dst->dev, OBJ_CNT_DST_PUT); newrefcnt = atomic_dec_return(&dst->__refcnt); if (WARN_ONCE(newrefcnt < 0, "dst_release_immediate underflow")) net_warn_ratelimited("%s: dst:%p refcnt:%d\n", From patchwork Tue Dec 7 04:02:07 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xin Long X-Patchwork-Id: 12661015 X-Patchwork-Delegate: kuba@kernel.org 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 70C90C433FE for ; Tue, 7 Dec 2021 04:02:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234680AbhLGEFs (ORCPT ); Mon, 6 Dec 2021 23:05:48 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39620 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234676AbhLGEFp (ORCPT ); Mon, 6 Dec 2021 23:05:45 -0500 Received: from mail-qt1-x82f.google.com (mail-qt1-x82f.google.com [IPv6:2607:f8b0:4864:20::82f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 63B63C061359 for ; Mon, 6 Dec 2021 20:02:15 -0800 (PST) Received: by mail-qt1-x82f.google.com with SMTP id m25so13057693qtq.13 for ; Mon, 06 Dec 2021 20:02:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=esY9Fo+mTFaNHsky8gYT9I2Vgb9OlmdOWP4kESY2sIE=; b=mNdgPX9xxePYSYlYrYwBRQLScy4P6Fvz7t63+Ij13p+/gv8gyhf1MK5QjCd6tZ2UZ4 DjyXPh/RN+2AACoSDn9oJVubSZjlAxVHZnNPCRDAkG52X2exeEOrZokVW93hIBLB9wDR OQZ1TSNEjMk0buWOtaoXZ4fy6ntNwKa14B0tmoUX2Cg3fftsfQU6fAFUzCOJqymrLXXI TPDlxMLUwL1+fYRKxgYMuoInssjEdW1LJj3JQcQmcYhRl4ohbyzoULKfZgsIOPLXqH9Q +2pGhEUXEQD+mvGPxUFFWKZki8eaCjATsy5d80mSG2wq0Uh3Fgde1ANQO0Ls+78Ucy68 Ruww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=esY9Fo+mTFaNHsky8gYT9I2Vgb9OlmdOWP4kESY2sIE=; b=eJ0lm34qs4+uqpkitpcdoRdXplRLGP5qXaobaxzQbZ3ypBI/4PMGhKkpU7hxA9K8cZ fQq3WgxURrsyNLuZ0Smn3YDA3dEe5Rc9dQS/A+uZOHkdzg1LsGP11ik1RtD5EX5xgWb8 1ysWjZCmea6IYkC8/W3/ajvrLeNZDQa4nvAclXUm5508gOuJwE3jSBOK+6vSDK46eJut Eztozk5YYua0NB4ZhFLWI+Dhm7RFgdDhwQsDad/oFiPxyXAROFXlz0E0bOPk/ibesvwy ByU9YrWo5C5fpkACdGpnHfetk3rO6UZJJg/iNvlwEPkkWSZkp9wa1ddLkGpj/ogZUqoM 4Iug== X-Gm-Message-State: AOAM533/eI32Os0AN+RpU4MUnzd4TNMZaF37hMdmF8R1hxw7XqE35bIf FfUg0/YbHmbL7x6icjYiEizoryzvimcJ7A== X-Google-Smtp-Source: ABdhPJyMS2vz3XNFdLQiSHwExup3UsYsheq9WeZeOMfOi7hkEpP1LwzlRmlAbyLjaMFWoeJSyok8yA== X-Received: by 2002:a05:622a:92:: with SMTP id o18mr45314092qtw.570.1638849734459; Mon, 06 Dec 2021 20:02:14 -0800 (PST) Received: from wsfd-netdev15.ntdv.lab.eng.bos.redhat.com (nat-pool-bos-t.redhat.com. [66.187.233.206]) by smtp.gmail.com with ESMTPSA id 14sm8526393qtx.84.2021.12.06.20.02.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Dec 2021 20:02:14 -0800 (PST) From: Xin Long To: network dev Cc: Eric Dumazet , davem@davemloft.net, kuba@kernel.org, Marcelo Ricardo Leitner , Davide Caratti , Paolo Abeni Subject: [PATCH net-next 4/5] net: track in6_dev refcnt with obj_cnt Date: Mon, 6 Dec 2021 23:02:07 -0500 Message-Id: <47a018589c90c00026bef584ce4fa9356cdd973f.1638849511.git.lucien.xin@gmail.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Two types are added into obj_cnt to count in6_dev_hold/get and in6_dev_put, and all it does is put obj_cnt_track_by_dev() into these two functions. Here is an example to track the refcnt of a in6_dev which is attached on a netdev named dummy0: # sysctl -w obj_cnt.control="clear" # clear the old result # sysctl -w obj_cnt.type=0x30 # enable in6_dev_hold/put track # sysctl -w obj_cnt.name=dummy0 # count in6_dev_hold/put(in6_dev) # sysctl -w obj_cnt.nr_entries=4 # save 4 frames' call trace # ip link add dummy0 type dummy # ip link set dummy0 up # ip addr add 2020::1/64 dev dummy0 # ip link set dummy0 down # ip link del dummy0 # sysctl -w obj_cnt.control="scan" # print the new result # dmesg OBJ_CNT: obj_cnt_dump: obj: ffff8a1e17906000, type: in6_dev_put, cnt: 1,: ipv6_mc_down+0x11e/0x1a0 addrconf_ifdown+0x53c/0x670 addrconf_notify+0xb8/0x940 raw_notifier_call_chain+0x41/0x50 OBJ_CNT: obj_cnt_dump: obj: ffff8a1e17906000, type: in6_dev_put, cnt: 1,: ma_put+0x4f/0xb0 ipv6_mc_destroy_dev+0x150/0x180 addrconf_ifdown+0x478/0x670 addrconf_notify+0xb8/0x940 ... OBJ_CNT: obj_cnt_dump: obj: ffff8a1e17906000, type: in6_dev_hold, cnt: 2,: fib6_nh_init+0x6b4/0x8f0 ip6_route_info_create+0x4f2/0x670 ip6_route_add+0x18/0x90 addrconf_prefix_route.isra.50+0x100/0x150 OBJ_CNT: obj_cnt_dump: obj: ffff8a1e17906000, type: in6_dev_hold, cnt: 2,: fib6_nh_init+0x6b4/0x8f0 ip6_route_info_create+0x4f2/0x670 addrconf_f6i_alloc+0xe3/0x130 ipv6_add_addr+0x16a/0x740 ... Signed-off-by: Xin Long --- include/linux/obj_cnt.h | 2 ++ include/net/addrconf.h | 7 ++++++- lib/obj_cnt.c | 4 +++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/include/linux/obj_cnt.h b/include/linux/obj_cnt.h index ae4c12beb876..f014b2e613d9 100644 --- a/include/linux/obj_cnt.h +++ b/include/linux/obj_cnt.h @@ -7,6 +7,8 @@ enum { OBJ_CNT_DEV_PUT, OBJ_CNT_DST_HOLD, OBJ_CNT_DST_PUT, + OBJ_CNT_IN6_DEV_HOLD, + OBJ_CNT_IN6_DEV_PUT, OBJ_CNT_TYPE_MAX }; diff --git a/include/net/addrconf.h b/include/net/addrconf.h index 78ea3e332688..370a96b57dbd 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -357,8 +357,10 @@ static inline struct inet6_dev *in6_dev_get(const struct net_device *dev) rcu_read_lock(); idev = rcu_dereference(dev->ip6_ptr); - if (idev) + if (idev) { + obj_cnt_track_by_dev(idev, idev->dev, OBJ_CNT_IN6_DEV_HOLD); refcount_inc(&idev->refcnt); + } rcu_read_unlock(); return idev; } @@ -374,6 +376,7 @@ void in6_dev_finish_destroy(struct inet6_dev *idev); static inline void in6_dev_put(struct inet6_dev *idev) { + obj_cnt_track_by_dev(idev, idev->dev, OBJ_CNT_IN6_DEV_PUT); if (refcount_dec_and_test(&idev->refcnt)) in6_dev_finish_destroy(idev); } @@ -390,11 +393,13 @@ static inline void in6_dev_put_clear(struct inet6_dev **pidev) static inline void __in6_dev_put(struct inet6_dev *idev) { + obj_cnt_track_by_dev(idev, idev->dev, OBJ_CNT_IN6_DEV_PUT); refcount_dec(&idev->refcnt); } static inline void in6_dev_hold(struct inet6_dev *idev) { + obj_cnt_track_by_dev(idev, idev->dev, OBJ_CNT_IN6_DEV_HOLD); refcount_inc(&idev->refcnt); } diff --git a/lib/obj_cnt.c b/lib/obj_cnt.c index 648adc135080..8756efc005ed 100644 --- a/lib/obj_cnt.c +++ b/lib/obj_cnt.c @@ -18,7 +18,9 @@ static char *obj_cnt_str[OBJ_CNT_TYPE_MAX] = { "dev_hold", "dev_put", "dst_hold", - "dst_put" + "dst_put", + "in6_dev_hold", + "in6_dev_put" }; struct obj_cnt { From patchwork Tue Dec 7 04:02:08 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Xin Long X-Patchwork-Id: 12661017 X-Patchwork-Delegate: kuba@kernel.org 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 vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 85C2EC433EF for ; Tue, 7 Dec 2021 04:02:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234695AbhLGEFt (ORCPT ); Mon, 6 Dec 2021 23:05:49 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:39632 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234689AbhLGEFq (ORCPT ); Mon, 6 Dec 2021 23:05:46 -0500 Received: from mail-qt1-x831.google.com (mail-qt1-x831.google.com [IPv6:2607:f8b0:4864:20::831]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7B990C061A83 for ; Mon, 6 Dec 2021 20:02:16 -0800 (PST) Received: by mail-qt1-x831.google.com with SMTP id m25so13057747qtq.13 for ; Mon, 06 Dec 2021 20:02:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=KKIA9qDj8FQn55+aSvd8YOlaLj0ctyi5Ud6rJva2cPo=; b=omCi8t53spfqpIA6MrSYwRhm7ziHeeokGLK6byYkxqVvzkonGA4qlwg6d96ioyo0D+ 7W7LSo1Y90tpu91lladJLkXakH3HzQAIYkHjOzcOwcIY5boMOn66kYdR7vQaE/zPgmLT owZO9cVngbxbeqz1IinUecn7nSwO6bf7F6QLMQn3Pg/nR9d1UmaA60ByQqvUlYngkK2T IoeAtych2vtvEng1IwNjAPz82iPQdQ/yo8I0JVKIZDEABRqwyE/rUt6K88xQ5AgJhzTo lHjQH+6jolhlG1jykSWs1UMy2k55Es1xdpWevZaDHtq5rTEB9p4FFyL+sg5LSV/Z4boJ pzJg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=KKIA9qDj8FQn55+aSvd8YOlaLj0ctyi5Ud6rJva2cPo=; b=QrKx1Au1mJ3Vh6Kpy9wZ5xd0gmh2OH9Gl0QMqKooLch6Z6OAeRyPcAtANJRV55mFc7 W3x/I6bpS53mRTooxhObcPcphV57P7N8dwudAaubwZjBOIV+g7fcHWE/ScXiHaZeUb13 HYWHk/tgYHP+MNvcVbOOl9O51kOVc/aAuhLiEy0hobef+f4KBNYqt6F7hyAjtlmCUzuR TCeUN3EBZ4yu+K9IDb0qghVIK2/YzN0v2aB5vHyUaweyqBRAwBFRXDbwpTZcabGxNIjD N70hkxoPAgd2qWq3jwVKnFWYq2t4lp0PzBtP6SnKvuPlxguASVaZkjooPm2aCTeFvqFG QzvQ== X-Gm-Message-State: AOAM530UWpD3KqSiDJxxGwAzVgMypD0PSIFFYfogveQOkXEylBtHbcTx b6OJZyV2oU8f/fzASCME9JBgNU36gJYtsA== X-Google-Smtp-Source: ABdhPJz5ZSL/KG2mBV5yAklPTEqtwqvjRo4CCLuKSueZ0ZobFDSRHeWv2NipKpyuPTMp89tWHabQ1A== X-Received: by 2002:ac8:5e13:: with SMTP id h19mr44926589qtx.413.1638849735470; Mon, 06 Dec 2021 20:02:15 -0800 (PST) Received: from wsfd-netdev15.ntdv.lab.eng.bos.redhat.com (nat-pool-bos-t.redhat.com. [66.187.233.206]) by smtp.gmail.com with ESMTPSA id 14sm8526393qtx.84.2021.12.06.20.02.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 06 Dec 2021 20:02:14 -0800 (PST) From: Xin Long To: network dev Cc: Eric Dumazet , davem@davemloft.net, kuba@kernel.org, Marcelo Ricardo Leitner , Davide Caratti , Paolo Abeni Subject: [PATCH net-next 5/5] net: track xfrm_state refcnt with obj_cnt Date: Mon, 6 Dec 2021 23:02:08 -0500 Message-Id: <4f368b30a1dd6434a7cbe473c6b8d5a50565e3ad.1638849511.git.lucien.xin@gmail.com> X-Mailer: git-send-email 2.27.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org X-Patchwork-Delegate: kuba@kernel.org Two types are added into obj_cnt to count xfrm_state_hold and xfrm_state_put*, and all it does is put obj_cnt_track_by_index() into these two functions. Here is a example to track the refcnt of a xfrm_state whose spi is 0x100: # sysctl -w obj_cnt.control="clear" # clear the old result # sysctl -w obj_cnt.type=0xc0 # enable xfrm_state_hold/put track # sysctl -w obj_cnt.index=0x100 # count xfrm_state_hold/put(state) # sysctl -w obj_cnt.nr_entries=4 # save 4 frames' call trace # ip link add dummy0 type dummy # ip link set dummy0 up # ip addr add 1.1.1.1/24 dev dummy0 # ip xfrm state add src 1.1.1.1 dst 1.1.1.2 spi 0x100 proto esp enc aes \ 0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f \ mode tunnel sel src 1.1.1.1 dst 1.1.1.2 # ip xfrm policy add dir out src 1.1.1.1 dst 1.1.1.2 tmpl src 1.1.1.1 \ dst 1.1.1.2 proto esp mode tunnel # ping 1.1.1.2 -c 1 # ip link set dummy0 down # ip link del dummy0 # sysctl -w obj_cnt.control="scan" # print the new result # dmesg OBJ_CNT: obj_cnt_dump: obj: ffff8ca629cb0f00, type: xfrm_state_hold, cnt: 1,: xfrm_add_sa+0x476/0x5f0 xfrm_user_rcv_msg+0x13c/0x250 netlink_rcv_skb+0x50/0x100 xfrm_netlink_rcv+0x30/0x40 OBJ_CNT: obj_cnt_dump: obj: ffff8ca629cb0f00, type: xfrm_state_put, cnt: 2,: xfrm4_dst_destroy+0x110/0x130 dst_destroy+0x37/0xe0 rcu_do_batch+0x164/0x4b0 rcu_core+0x249/0x350 OBJ_CNT: obj_cnt_dump: obj: ffff8ca629cb0f00, type: xfrm_state_put, cnt: 1,: xfrm_add_sa+0x497/0x5f0 xfrm_user_rcv_msg+0x13c/0x250 netlink_rcv_skb+0x50/0x100 xfrm_netlink_rcv+0x30/0x40 Signed-off-by: Xin Long --- include/linux/obj_cnt.h | 2 ++ include/net/xfrm.h | 11 +++++++++++ lib/obj_cnt.c | 4 +++- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/include/linux/obj_cnt.h b/include/linux/obj_cnt.h index f014b2e613d9..42611aa321c7 100644 --- a/include/linux/obj_cnt.h +++ b/include/linux/obj_cnt.h @@ -9,6 +9,8 @@ enum { OBJ_CNT_DST_PUT, OBJ_CNT_IN6_DEV_HOLD, OBJ_CNT_IN6_DEV_PUT, + OBJ_CNT_XFRM_STATE_HOLD, + OBJ_CNT_XFRM_STATE_PUT, OBJ_CNT_TYPE_MAX }; diff --git a/include/net/xfrm.h b/include/net/xfrm.h index 2308210793a0..543840fba068 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -772,25 +772,36 @@ static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols) void __xfrm_state_destroy(struct xfrm_state *, bool); +static inline void obj_cnt_track_by_index(void *obj, int index, int type) +{ +#ifdef CONFIG_OBJ_CNT + obj_cnt_track(type, index, NULL, obj); +#endif +} + static inline void __xfrm_state_put(struct xfrm_state *x) { + obj_cnt_track_by_index(x, ntohl(x->id.spi), OBJ_CNT_XFRM_STATE_PUT); refcount_dec(&x->refcnt); } static inline void xfrm_state_put(struct xfrm_state *x) { + obj_cnt_track_by_index(x, ntohl(x->id.spi), OBJ_CNT_XFRM_STATE_PUT); if (refcount_dec_and_test(&x->refcnt)) __xfrm_state_destroy(x, false); } static inline void xfrm_state_put_sync(struct xfrm_state *x) { + obj_cnt_track_by_index(x, ntohl(x->id.spi), OBJ_CNT_XFRM_STATE_PUT); if (refcount_dec_and_test(&x->refcnt)) __xfrm_state_destroy(x, true); } static inline void xfrm_state_hold(struct xfrm_state *x) { + obj_cnt_track_by_index(x, ntohl(x->id.spi), OBJ_CNT_XFRM_STATE_HOLD); refcount_inc(&x->refcnt); } diff --git a/lib/obj_cnt.c b/lib/obj_cnt.c index 8756efc005ed..f054455abe8d 100644 --- a/lib/obj_cnt.c +++ b/lib/obj_cnt.c @@ -20,7 +20,9 @@ static char *obj_cnt_str[OBJ_CNT_TYPE_MAX] = { "dst_hold", "dst_put", "in6_dev_hold", - "in6_dev_put" + "in6_dev_put", + "xfrm_state_hold", + "xfrm_state_put" }; struct obj_cnt {