From patchwork Tue Aug 15 12:52:48 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jinjiang Tu X-Patchwork-Id: 13353759 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 AEBE7C0015E for ; Tue, 15 Aug 2023 11:58:06 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id ABD0C8D000B; Tue, 15 Aug 2023 07:58:00 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id A6CFD8D0008; 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 941798D000C; Tue, 15 Aug 2023 07:58:00 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0013.hostedemail.com [216.40.44.13]) by kanga.kvack.org (Postfix) with ESMTP id 839BE8D000B for ; Tue, 15 Aug 2023 07:58:00 -0400 (EDT) Received: from smtpin29.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay01.hostedemail.com (Postfix) with ESMTP id 54F671C9CB6 for ; Tue, 15 Aug 2023 11:58:00 +0000 (UTC) X-FDA: 81126190320.29.886871B Received: from szxga01-in.huawei.com (szxga01-in.huawei.com [45.249.212.187]) by imf12.hostedemail.com (Postfix) with ESMTP id 321104000A for ; Tue, 15 Aug 2023 11:57:56 +0000 (UTC) Authentication-Results: imf12.hostedemail.com; dkim=none; spf=pass (imf12.hostedemail.com: domain of tujinjiang@huawei.com designates 45.249.212.187 as permitted sender) smtp.mailfrom=tujinjiang@huawei.com; dmarc=pass (policy=quarantine) header.from=huawei.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1692100678; a=rsa-sha256; cv=none; b=nYwFwWACr+E/rGPm8eX1K2AaplP4dslsCxKlDZfPEUiWR0b6QeWv3ExZVx8vkvgUGscEGg FFd2BWh3dclDwL8D6oO3Z+7VdZUDA52p+hxJBXOJp9esOE0cl9PI7Ch2zfiFXavEfWLFkp XrnUmYG6AHWS4pdFJSY6VEFx0NZLgjM= ARC-Authentication-Results: i=1; imf12.hostedemail.com; dkim=none; spf=pass (imf12.hostedemail.com: domain of tujinjiang@huawei.com designates 45.249.212.187 as permitted sender) smtp.mailfrom=tujinjiang@huawei.com; dmarc=pass (policy=quarantine) header.from=huawei.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1692100678; 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=AmqJMJDCupGWzT3gJ/B0Aeo1P7ty/LJ9a5q1IP9DHUQ=; b=m41oe01C5Y0oqiHKjLauNEHV8Uv84qNPAIZHcwqJnOYtkH9KWen7xY1EQgFhPPTCTQVYoD 84IicIlCEtakVV3EsRRuzuHf3VXQERz/KAxWMeCUJu2AUk6vh6oOmpvxC8uG/aepEqxvtl Iupq4CQtK49vc5R/5EKuG9+mXeQ1zbg= Received: from dggpeml500011.china.huawei.com (unknown [172.30.72.53]) by szxga01-in.huawei.com (SkyGuard) with ESMTP id 4RQ8r10p1SzrSBP; Tue, 15 Aug 2023 19:56:33 +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:52 +0800 From: Jinjiang Tu To: , , , , CC: Subject: [PATCH 3/6] tools/vm/page_owner_sort: support for selecting by module name Date: Tue, 15 Aug 2023 20:52:48 +0800 Message-ID: <20230815125251.2865852-4-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: rspam06 X-Rspamd-Queue-Id: 321104000A X-Stat-Signature: sge1w95ck8jtgs498yfj91y1rxrrhrh9 X-HE-Tag: 1692100676-826273 X-HE-Meta: U2FsdGVkX19/T8vqjbD/4rTeuhhvC/5KHIumZeDyoGQ+i4bXu31J3N8VxR24x1Ffiw8cyOuj7PFs64QWdraIHA4dLgOH/UFGiqERW57sez/oqW0VI4VvHQ7/0tZzo7KkNk/MBcNc8o7RUg7bmt+UvMr3GHP4j2e2VKoGLGTQGwxSawiLDS0+SLny+tlxBTUyt2wjiIlAhpl0miyI3lmKfS9fhoDzbOELVJayls+JEwCcRG1WhJAjev1e1p6NSuo5oPCurdlIm0JESFLT7DX7KHKra9U4gV4OodCvzu7GB84H/BujyYR9nMEE2jvdfGQJOC44rZ38WGFBc+SPDLhvXIMsUOTcM2406czxHWjo2ISdlXYbwxWC27xqkI9j8k1VFLj7kaKZqAGeLoykHNIk6CNUKCYoB3y7oVkEogq/7i0prCTUgiW8/XtdAB5UwsB0/PJkJFfEjXZHFXibn1w3vkDldT244ws7kQnB61/yiRPB7C6Iwi3r5C/F3Dqcf1OLNK/88q1smLhmRE+7Sq6pgH4MyZ+tppLpkDfsTZ7+la0qxUP6T6CqfmaLeUKXfFhYD7Tj8o2q1VtOa7munzN/WyNcpkc2poLTdaQZCf6D/+1G5oZ1HUHLx2bFxcTJtpJ3AQvDSSIPa7uubJLc04QmFV/UfFrTZUfshtgB5VvpQEBoYUm6lVoNACtcG+zF9sL55BtNREo4orrVMCJh/rL5It9ORcnEWEvbp8LZGD5UzLayRsIwwbQ8Rj0/PlwyYoBka9oqbQImn+EpUCexl0nQqdbtZjy0kyVGv9O5mQ7awmRHN3SJEOawzNaBuYIOy/sPut6ayqK137qH2uhFucOCFpFJ+6LfwX/Oxwcjdb0KDtI+ZqXCLOGLXnpZEvijC+nw1OGN0Lf9hqaUhHhOk/k3RyjPzQ5PgoGIX/Z7p8bEdxZn+Cm2mgXmU808ki2J0kyldgO/fduxXcXiGUA3zwr CtmkwJnq LD2Bi1CMejCengsbBdoFCmC+wHe4JrWSkhGHDi5LKDhu3ArPudnXifjM0RvFg+7c0Jlo4f7na22N/2Y8kzLRQpW5rJkhdfrmoFEIK+pykNywvloy/eJG2sOsUNb1O9Vmq2NbpyVwIRrDeqtX4K7ZypPkrB9r0V1Xf5rfcy2KMoIhlmzr4HdHHVQd2yqMzS8koohmG 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 -M and --module options to support selecting modules. -M option allows to filtering all the items except the ones allcating by modules. --module option allows to only select one or more modules. For example, --module=mod1,mod2 will only select items allocating by mod1 or mod2. Signed-off-by: Jinjiang Tu --- tools/mm/page_owner_sort.c | 84 +++++++++++++++++++++++++++++++++----- 1 file changed, 73 insertions(+), 11 deletions(-) diff --git a/tools/mm/page_owner_sort.c b/tools/mm/page_owner_sort.c index 99798894b879..6fd689199789 100644 --- a/tools/mm/page_owner_sort.c +++ b/tools/mm/page_owner_sort.c @@ -27,6 +27,7 @@ #define true 1 #define false 0 #define TASK_COMM_LEN 16 +#define MODULE_NAME_LEN (64 - sizeof(unsigned long)) struct block_list { char *txt; @@ -40,12 +41,14 @@ struct block_list { pid_t pid; pid_t tgid; int allocator; + char *module; }; enum FILTER_BIT { FILTER_UNRELEASE = 1<<1, FILTER_PID = 1<<2, FILTER_TGID = 1<<3, - FILTER_COMM = 1<<4 + FILTER_COMM = 1<<4, + FILTER_MODULE = 1<<5 }; enum CULL_BIT { CULL_UNRELEASE = 1<<1, @@ -74,9 +77,11 @@ struct filter_condition { pid_t *pids; pid_t *tgids; char **comms; + char **modules; int pids_size; int tgids_size; int comms_size; + int modules_size; }; struct sort_condition { int (**cmps)(const void *, const void *); @@ -91,6 +96,7 @@ static regex_t tgid_pattern; static regex_t comm_pattern; static regex_t ts_nsec_pattern; static regex_t free_ts_nsec_pattern; +static regex_t module_pattern; static struct block_list *list; static int list_size; static int max_size; @@ -100,10 +106,12 @@ static bool debug_on; static void set_single_cmp(int (*cmp)(const void *, const void *), int sign); -int read_block(char *buf, char *ext_buf, int buf_size, FILE *fin) +int read_block(char *buf, char *ext_buf, char *mod_buf, int buf_size, FILE *fin) { char *curr = buf, *const buf_end = buf + buf_size; + char *mod_string = "Page allocated by module"; + mod_buf[0] = '\0'; while (buf_end - curr > 1 && fgets(curr, buf_end - curr, fin)) { if (*curr == '\n') { /* empty line */ return curr - buf; @@ -112,6 +120,10 @@ int read_block(char *buf, char *ext_buf, int buf_size, FILE *fin) strcpy(ext_buf, curr); continue; } + if (!strncmp(curr, mod_string, strlen(mod_string))) { + strcpy(mod_buf, curr); + continue; + } curr += strlen(curr); } @@ -401,6 +413,16 @@ static char *get_comm(char *buf) return comm_str; } +static char *get_module(char *buf) +{ + char *mod = malloc(MODULE_NAME_LEN); + + memset(mod, 0, MODULE_NAME_LEN); + search_pattern(&module_pattern, mod, buf); + + return mod; +} + static int get_arg_type(const char *arg) { if (!strcmp(arg, "pid") || !strcmp(arg, "p")) @@ -469,7 +491,24 @@ static bool match_str_list(const char *str, char **list, int list_size) return false; } -static bool is_need(char *buf) +static bool is_module_filtered(char *mod_buf) +{ + char *mod = get_module(mod_buf); + int ret = true; + + if (!strlen(mod)) + goto out; + + if (fc.modules_size == 0 || + match_str_list(mod, fc.modules, fc.modules_size)) + ret = false; + +out: + free(mod); + return ret; +} + +static bool is_need(char *buf, char *mod_buf) { __u64 ts_nsec, free_ts_nsec; @@ -484,6 +523,9 @@ static bool is_need(char *buf) !match_num_list(get_tgid(buf), fc.tgids, fc.tgids_size)) return false; + if (filter & FILTER_MODULE && is_module_filtered(mod_buf)) + return false; + char *comm = get_comm(buf); if ((filter & FILTER_COMM) && @@ -495,7 +537,7 @@ static bool is_need(char *buf) return true; } -static bool add_list(char *buf, int len, char *ext_buf) +static bool add_list(char *buf, int len, char *ext_buf, char *mod_buf) { if (list_size != 0 && len == list[list_size-1].len && @@ -508,7 +550,7 @@ static bool add_list(char *buf, int len, char *ext_buf) fprintf(stderr, "max_size too small??\n"); return false; } - if (!is_need(buf)) + if (!is_need(buf, mod_buf)) return true; list[list_size].pid = get_pid(buf); list[list_size].tgid = get_tgid(buf); @@ -530,6 +572,7 @@ static bool add_list(char *buf, int len, char *ext_buf) list[list_size].ts_nsec = get_ts_nsec(buf); list[list_size].free_ts_nsec = get_free_ts_nsec(buf); list[list_size].allocator = get_allocator(buf, ext_buf); + list[list_size].module = get_module(mod_buf); list_size++; if (list_size % 1000 == 0) { printf("loaded %d\r", list_size); @@ -681,19 +724,21 @@ static void usage(void) "-a\t\tSort by memory allocate time.\n" "-r\t\tSort by memory release time.\n" "-f\t\tFilter out the information of blocks whose memory has been released.\n" + "-M\t\tFilter out the information of blocks whose memory isn't allocated by modules.\n" "-d\t\tPrint debug information.\n" "--pid \tSelect by pid. This selects the information of blocks whose process ID numbers appear in .\n" "--tgid \tSelect by tgid. This selects the information of blocks whose Thread Group ID numbers appear in .\n" "--name \n\t\tSelect by command name. This selects the information of blocks whose command name appears in .\n" "--cull \tCull by user-defined rules. is a single argument in the form of a comma-separated list with some common fields predefined\n" "--sort \tSpecify sort order as: [+|-]key[,[+|-]key[,...]]\n" + "--module \tSelect by module. This selects the information of blocks whose memory is allocated by modules appear in .\n" ); } int main(int argc, char **argv) { FILE *fin, *fout; - char *buf, *ext_buf; + char *buf, *ext_buf, *mod_buf; int i, count; struct stat st; int opt; @@ -703,10 +748,11 @@ int main(int argc, char **argv) { "name", required_argument, NULL, 3 }, { "cull", required_argument, NULL, 4 }, { "sort", required_argument, NULL, 5 }, + { "module", required_argument, NULL, 6 }, { 0, 0, 0, 0}, }; - while ((opt = getopt_long(argc, argv, "adfmnprstP", longopts, NULL)) != -1) + while ((opt = getopt_long(argc, argv, "adfmnprstPM", longopts, NULL)) != -1) switch (opt) { case 'a': set_single_cmp(compare_ts, SORT_ASC); @@ -738,6 +784,11 @@ int main(int argc, char **argv) case 'n': set_single_cmp(compare_comm, SORT_ASC); break; + case 'M': + filter = filter | FILTER_MODULE; + fc.modules_size = 0; + fc.modules = NULL; + break; case 1: filter = filter | FILTER_PID; fc.pids = parse_nums_list(optarg, &fc.pids_size); @@ -774,6 +825,10 @@ int main(int argc, char **argv) exit(1); } break; + case 6: + filter = filter | FILTER_MODULE; + fc.modules = explode(',', optarg, &fc.modules_size); + break; default: usage(); exit(1); @@ -804,6 +859,8 @@ int main(int argc, char **argv) goto out_ts; if (!check_regcomp(&free_ts_nsec_pattern, "free_ts\\s*([0-9]*)\\s*ns")) goto out_free_ts; + if (!check_regcomp(&module_pattern, "Page allocated by module (.*)")) + goto out_module; fstat(fileno(fin), &st); max_size = st.st_size / 100; /* hack ... */ @@ -811,17 +868,18 @@ int main(int argc, char **argv) list = malloc(max_size * sizeof(*list)); buf = malloc(BUF_SIZE); ext_buf = malloc(BUF_SIZE); - if (!list || !buf || !ext_buf) { + mod_buf = malloc(BUF_SIZE); + if (!list || !buf || !ext_buf || !mod_buf) { fprintf(stderr, "Out of memory\n"); goto out_free; } for ( ; ; ) { - int buf_len = read_block(buf, ext_buf, BUF_SIZE, fin); + int buf_len = read_block(buf, ext_buf, mod_buf, BUF_SIZE, fin); if (buf_len < 0) break; - if (!add_list(buf, buf_len, ext_buf)) + if (!add_list(buf, buf_len, ext_buf, mod_buf)) goto out_free; } @@ -848,8 +906,10 @@ int main(int argc, char **argv) for (i = 0; i < count; i++) { if (cull == 0) { fprintf(fout, "%d times, %d pages, ", list[i].num, list[i].page_num); + if (strlen(list[i].module) != 0) + fprintf(fout, "allocated by module %s, ", list[i].module); print_allocator(fout, list[i].allocator); - fprintf(fout, ":\n%s\n", list[i].txt); + fprintf(fout, " :\n%s\n", list[i].txt); } else { fprintf(fout, "%d times, %d pages", @@ -880,6 +940,8 @@ int main(int argc, char **argv) free(buf); if (list) free(list); +out_module: + regfree(&module_pattern); out_free_ts: regfree(&free_ts_nsec_pattern); out_ts: