From patchwork Tue Aug 15 12:52:46 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jinjiang Tu X-Patchwork-Id: 13353756 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 78749C04A6A for ; Tue, 15 Aug 2023 11:58:01 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 2A70A8D0009; Tue, 15 Aug 2023 07:58:00 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 27E6C8D0001; Tue, 15 Aug 2023 07:58:00 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 06B858D0009; Tue, 15 Aug 2023 07:57:59 -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 D50BE8D0001 for ; Tue, 15 Aug 2023 07:57:59 -0400 (EDT) Received: from smtpin08.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay03.hostedemail.com (Postfix) with ESMTP id 9A370A0801 for ; Tue, 15 Aug 2023 11:57:59 +0000 (UTC) X-FDA: 81126190278.08.A51EE60 Received: from szxga01-in.huawei.com (szxga01-in.huawei.com [45.249.212.187]) by imf01.hostedemail.com (Postfix) with ESMTP id 2278A40007 for ; Tue, 15 Aug 2023 11:57:56 +0000 (UTC) Authentication-Results: imf01.hostedemail.com; dkim=none; dmarc=pass (policy=quarantine) header.from=huawei.com; spf=pass (imf01.hostedemail.com: domain of tujinjiang@huawei.com designates 45.249.212.187 as permitted sender) smtp.mailfrom=tujinjiang@huawei.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1692100677; 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:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=vbbcIfUTDqboMEX0sE2+NtB1fLzGastILWeXfwoFBJ8=; b=xY68n+5Hn3pAjU3DojDd4NwQGui5hvnPlzl2nH8WGPpbytngBaFMHQa3PO0yaGqHkGaspv sgRZRbN9BDrBuuU3ni9XIgUFV6ugotEb0x0GR1nXEZSFal4AfBEW9PJSKzCYbYjvd7/AZn tuxDuBqxibe0iCoD50qq4IpK6jQq1Lo= ARC-Authentication-Results: i=1; imf01.hostedemail.com; dkim=none; dmarc=pass (policy=quarantine) header.from=huawei.com; spf=pass (imf01.hostedemail.com: domain of tujinjiang@huawei.com designates 45.249.212.187 as permitted sender) smtp.mailfrom=tujinjiang@huawei.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1692100677; a=rsa-sha256; cv=none; b=Wdq5Hp45D3/TC7t5sQR+z0ZjgpUK5nNUP31DY/Zq1377FdyRSsuiowTCeBZ3s06pc3AyIg vMitgfQDTqbc4wRDl8s2jZilkmtggFd79FujDt/+SDNdGux0tbHoNOIEWk6UkYdHY+rbIS cR2iAN0iSASTTz1g4LEbVFHRLuxwz+g= Received: from dggpeml500011.china.huawei.com (unknown [172.30.72.53]) by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4RQ8nN2VPNztRvk; Tue, 15 Aug 2023 19:54:16 +0800 (CST) Received: from huawei.com (10.175.113.32) by dggpeml500011.china.huawei.com (7.185.36.84) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.31; Tue, 15 Aug 2023 19:57:51 +0800 From: Jinjiang Tu To: , , , , CC: Subject: [PATCH 1/6] mm/page_owner: support identifying pages allocated by modules Date: Tue, 15 Aug 2023 20:52:46 +0800 Message-ID: <20230815125251.2865852-2-tujinjiang@huawei.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230815125251.2865852-1-tujinjiang@huawei.com> References: <20230815125251.2865852-1-tujinjiang@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.175.113.32] X-ClientProxiedBy: dggems705-chm.china.huawei.com (10.3.19.182) To dggpeml500011.china.huawei.com (7.185.36.84) X-CFilter-Loop: Reflected X-Rspam-User: X-Rspamd-Server: rspam12 X-Rspamd-Queue-Id: 2278A40007 X-Stat-Signature: nno4qed8ekttka53xtm9pgduiycetacc X-HE-Tag: 1692100676-548078 X-HE-Meta: U2FsdGVkX18DiLLMzmdDMCmOBXMBzEyoKXi/cYZAGT5TtMCBoqfN7PAcX9HT/hthdzo6DVI46E5/ngv/xZpNALpKCpAohNDoSw5t/Gm7rTEDGy0XT6CYzn1+IB/MuOCuBgCGFr1nBLXDRXMLrM0xd6ltL3qm4cQJeAvxV4z/kHVN9ukeoeIOlr1PSI8bJje4q2hIKQ9/nK1IIsCyUjV8YLQffuLpP5+v3ymCCjJIIA6uJpeNCk6vI8RbZ0oTVPnnaSfndXwYQxPpM4kmlnvHaHKPS8AVhCAQV8cTvVEMiQPSePeD5BxAa7HSBrBHwvcQA01Ha9NP85J2UhUmU/GRFnqws62QP6nK+MZ3SSxbOfI08h+YoxUhPx6MVKjbSHQWkNc364ut134LiJUjjDm6LGLqiR/2c1+P1fYwg+ToSoJCo5uCoOKu0PPch+MgQpFXguzqnQ9Hme7aQXvWPwV7WVm6TmikZTTH6s0WE6j7sVPoho721bfcKnKPtOk0mWZQFr5fuxQfq2jITt+YOOGKAXuxcnG/TcsQtB+3Fb+eUBr+Z/k/7slER2scsx3FC0Dz9Y2QHRjIBglNmy5ayKzKgusZ1/NoZ7ksuupzm1OHYGSHQgXmMHeuJ9JZVjNto5Himhl6B4jJf16tkWz5I/A6yXpbcLTglWQhstELHg8z7kLlKGyXpsqJ5h0c/LdrSmPCuR+ppun7HK47TrDLa/1L67VYyHxGj4E/KKCPBCgTx0u6AgbenReNuuVH/igBlwkMDzXTFH+SDnzMfyiiEM+/ZjzQBjuwhZqJ+GJJKE6TBOW0LTwPwPK/euBdLD9aTPHIqzajzBXCeuQk3ojkrZuAaOsnpg3kjwQhbD3Y/Svv/uwrfIwyWJjrDQRzcgF8+sRKFT+gw28Dq7R8LtDXQ39z2uj+YlkvK9/TdT18ohbUj5Ux/FtglpY7dylwd3SLFEYiXdqQnDpxbU1fISIobsj HgGM97x+ FrTRA5L970zrYFJJXZ9L4a3wad3Jo52+QNACYrICIRBdWGvwTHybmxyeXw9H+4rnqoqbfY6hCWn9z31Ebg1VLsMbz8utJ6EEjFmG00nVek1/MHV3NUWWFSUmUzSlV3HdLKUDMxCx9SX00ki4xka7i09r2FNhb9J2I/MMLJwyPULwN7jk3M3Q3J99706ZwUz0I4Gxj 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: Identify if the pages are allocated by modules according to stackstrace. By traversing the stacktrace and querying if the address of each entry is located in a module, we gets the module who allocated/freed the page. If several modules are found in stacktrace, we choose the one that is closet to the allocation/free function. We record the module name in struct page_owner and print it when a user reads from page_owner interface. Signed-off-by: Jinjiang Tu --- mm/page_owner.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) diff --git a/mm/page_owner.c b/mm/page_owner.c index c93baef0148f..ef8fe1857d42 100644 --- a/mm/page_owner.c +++ b/mm/page_owner.c @@ -12,6 +12,7 @@ #include #include #include +#include #include "internal.h" @@ -32,6 +33,9 @@ struct page_owner { char comm[TASK_COMM_LEN]; pid_t pid; pid_t tgid; +#ifdef CONFIG_MODULES + char module_name[MODULE_NAME_LEN]; +#endif }; static bool page_owner_enabled __initdata; @@ -134,6 +138,78 @@ static noinline depot_stack_handle_t save_stack(gfp_t flags) return handle; } +#ifdef CONFIG_MODULES +static char *find_module_name(depot_stack_handle_t handle) +{ + int i; + struct module *mod = NULL; + unsigned long *entries; + unsigned int nr_entries; + + nr_entries = stack_depot_fetch(handle, &entries); + for (i = 0; i < nr_entries; i++) { + if (core_kernel_text(entries[i])) + continue; + + preempt_disable(); + mod = __module_address(entries[i]); + preempt_enable(); + + if (!mod) + continue; + + return mod->name; + } + + return NULL; +} + +static void set_module_name(struct page_owner *page_owner, char *mod_name) +{ + if (mod_name) + strscpy(page_owner->module_name, mod_name, MODULE_NAME_LEN); + else + memset(page_owner->module_name, 0, MODULE_NAME_LEN); +} + +static int module_name_snprint(struct page_owner *page_owner, + char *kbuf, size_t size) +{ + if (strlen(page_owner->module_name) != 0) + return scnprintf(kbuf, size, "Page allocated by module %s\n", + page_owner->module_name); + + return 0; +} + +static inline void copy_module_name(struct page_owner *old_page_owner, + struct page_owner *new_page_owner) +{ + set_module_name(new_page_owner, old_page_owner->module_name); +} +#else +static inline char *find_module_name(depot_stack_handle_t handle) +{ + return NULL; +} + +static inline void set_module_name(struct page_owner *page_owner, + char *mod_name) +{ +} + +static inline int module_name_snprint(struct page_owner *page_owner, + char *kbuf, size_t size) +{ + return 0; +} + +static inline void copy_module_name(struct page_owner *old_page_owner, + struct page_owner *new_page_owner) +{ +} +#endif + void __reset_page_owner(struct page *page, unsigned short order) { int i; @@ -141,17 +217,20 @@ void __reset_page_owner(struct page *page, unsigned short order) depot_stack_handle_t handle; struct page_owner *page_owner; u64 free_ts_nsec = local_clock(); + char *mod_name; page_ext = page_ext_get(page); if (unlikely(!page_ext)) return; handle = save_stack(GFP_NOWAIT | __GFP_NOWARN); + mod_name = find_module_name(handle); for (i = 0; i < (1 << order); i++) { __clear_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags); page_owner = get_page_owner(page_ext); page_owner->free_handle = handle; page_owner->free_ts_nsec = free_ts_nsec; + set_module_name(page_owner, mod_name); page_ext = page_ext_next(page_ext); } page_ext_put(page_ext); @@ -164,6 +243,9 @@ static inline void __set_page_owner_handle(struct page_ext *page_ext, struct page_owner *page_owner; int i; u64 ts_nsec = local_clock(); + char *mod_name; + + mod_name = find_module_name(handle); for (i = 0; i < (1 << order); i++) { page_owner = get_page_owner(page_ext); @@ -176,6 +258,7 @@ static inline void __set_page_owner_handle(struct page_ext *page_ext, page_owner->ts_nsec = ts_nsec; strscpy(page_owner->comm, current->comm, sizeof(page_owner->comm)); + set_module_name(page_owner, mod_name); __set_bit(PAGE_EXT_OWNER, &page_ext->flags); __set_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags); @@ -256,6 +339,7 @@ void __folio_copy_owner(struct folio *newfolio, struct folio *old) new_page_owner->ts_nsec = old_page_owner->ts_nsec; new_page_owner->free_ts_nsec = old_page_owner->ts_nsec; strcpy(new_page_owner->comm, old_page_owner->comm); + copy_module_name(new_page_owner, old_page_owner); /* * We don't clear the bit on the old folio as it's going to be freed @@ -425,6 +509,8 @@ print_page_owner(char __user *buf, size_t count, unsigned long pfn, migratetype_names[pageblock_mt], &page->flags); + ret += module_name_snprint(page_owner, kbuf + ret, count - ret); + ret += stack_depot_snprint(handle, kbuf + ret, count - ret, 0); if (ret >= count) goto err;