From nobody Sun Jun 14 01:44:49 2026 Received: from mail-dl1-f74.google.com (mail-dl1-f74.google.com [74.125.82.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3F6CA3E0C54 for ; Mon, 4 May 2026 23:36:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.74 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777937792; cv=none; b=NgvDh0dNwItzGOQJbPbyXHWiU2xYsMvdbHV/r3jYsIWlt4NadE+E/AOg1r8nSHOZv+A6GHOVwbx3a86yUPvVQCQrpyH2bra5xmPsAQ1bSkejx2nV6MX1Fqn0w+fPnS6L5v9k9lsidQQigTwtS6M4vZaIAYJ3CMZrTdbY2rpnzeM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777937792; c=relaxed/simple; bh=3HXFTPdUGxCgKQnh38fX9E/zA9KKgcm7/WL3CKknbFY=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=GnZX5AmupZlU/96ZgiB9WOP4mSgv5Uf0TXyGP7JkvOBFcMb/e3eo7L/ysyGLLywOO9lUH6q+D89n9OwJIrrdf4E40I01YP47HGq7Ee4a9JxY6T+Lt0c99ICoLwfUKf+ZnZHAzmvDdwSIPRY2rGce3flz//j/Y4UMucUSuQ3BB4U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--abhishekbapat.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=AxLBcJgp; arc=none smtp.client-ip=74.125.82.74 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--abhishekbapat.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="AxLBcJgp" Received: by mail-dl1-f74.google.com with SMTP id a92af1059eb24-130a468d5cdso539392c88.0 for ; Mon, 04 May 2026 16:36:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1777937790; x=1778542590; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=08AQr2uL2/ZNq+SW+24c1u9Obl8u2hOTuInIp2FYA2Y=; b=AxLBcJgpQOJjp5YPAM2FqTAvxSHYjYlVWx19zkQgVueR+XMXAvHXsgprcFrJNsYESB rXnOcQq4A2XfXl6pEoCjQ6wnWAAAVufUm4PCa0S0GqXBX6npP8yrLVfh8haW3FJsoD/h xHTeMNK7FNA1Q83Io4NwVTEDrLP7H2I5rSUsRzyu6dXzIwMQC2all93rmXclNoyKKEKO sbTTQVf7dmA4a8MVn9ghPxquqETRNUfc0Sx1BQeaN92RM8r/YrCgKAIoPdZARmsmFbF3 ItBHYSPeiUjLlRKISs8LQPWvzDUN6OlCbTzPRW6gaOPPfDmaMsJgpb1O7QLFKIyfq+y0 Md/g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777937790; x=1778542590; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=08AQr2uL2/ZNq+SW+24c1u9Obl8u2hOTuInIp2FYA2Y=; b=bY8JjY0bmBf12WOLpq0KXGc9JzmrNtVffanp7mWnuVxuOpN8jT5haMnq/M9UvtU3CV 9ERLwGk9GDlhJ7wcZ2rjbGFDb2fqauPd+ePLzkBvRyTe836Eu5a+7BAaspcWRSOFV0lu XN0ihXUauqxD1Qo5uf0lqi49wWJLJzbjbzXHGik5isYlVjz5q6JtZCR8puNikxlI09J6 frU65YygsQdS4GpE+27Dxj4lP3JWX7jU124amMzzkpS+BNoqx++oDN33ZnYMpZaIQXyg poPY7yLOy+tPcKWG6STbxBm7vMVPrYxF3kesamTxlJ+GQICF73kjsz4e7ukcKZD/v11t cIiQ== X-Forwarded-Encrypted: i=1; AFNElJ/YPdbB9B2HXev9SJkuPcvqQWRGy5EjLVqCAm7QqME6uU9VUwhySlAazSpXKkG5cE0yquWspiENtNYzLvo=@vger.kernel.org X-Gm-Message-State: AOJu0YwwYrzP42e5H2J/Io1Ypk1iU5GB0vlnaLCQZsqldpjd2Ff8mpqi 2x7RKRrteQt2/MhlvV3FCkOCWGY8gcwjk7QYomsEQHwHBH5tJHsi2cM3D/bBlvchrGSDecJCCxE YN1SAcea63xJ6V8k7nnhjJDOrSW339GY0rw== X-Received: from dybbs42.prod.google.com ([2002:a05:7300:a22a:b0:2ee:2c3a:8aaf]) (user=abhishekbapat job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7022:43:b0:12c:2e07:3fd with SMTP id a92af1059eb24-130b1c6d589mr516965c88.32.1777937790210; Mon, 04 May 2026 16:36:30 -0700 (PDT) Date: Mon, 4 May 2026 23:36:19 +0000 In-Reply-To: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog Message-ID: Subject: [PATCH 1/6] alloc_tag: add ioctl to /proc/allocinfo From: Abhishek Bapat To: Suren Baghdasaryan , Andrew Morton , Kent Overstreet Cc: Shuah Khan , Jonathan Corbet , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, Sourav Panda , Abhishek Bapat Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: Suren Baghdasaryan Add the following ioctl commands for /proc/allocinfo file: ALLOCINFO_IOC_CONTENT_ID - gets content identifier which can be used to check whether the file content has changed specifically due to module load/unload. Every time a module is loaded / unloaded, the returned value will be different. By comparing the identifier value at the beginning and at the end of the content retrieval operation, users can validate retrieved information for consistency. ALLOCINFO_IOC_GET_AT - gets the record at the specified position. This is the position of a record in /proc/allocinfo. ALLOCINFO_IOC_GET_NEXT - gets the record next to the last retrieved one. If no records were previously retrieved, returns the first record. Signed-off-by: Suren Baghdasaryan Signed-off-by: Abhishek Bapat --- .../userspace-api/ioctl/ioctl-number.rst | 2 + include/linux/codetag.h | 1 + include/uapi/linux/alloc_tag.h | 54 ++++++ lib/alloc_tag.c | 178 +++++++++++++++++- lib/codetag.c | 11 ++ 5 files changed, 244 insertions(+), 2 deletions(-) create mode 100644 include/uapi/linux/alloc_tag.h diff --git a/Documentation/userspace-api/ioctl/ioctl-number.rst b/Documenta= tion/userspace-api/ioctl/ioctl-number.rst index 331223761fff..84f6808a8578 100644 --- a/Documentation/userspace-api/ioctl/ioctl-number.rst +++ b/Documentation/userspace-api/ioctl/ioctl-number.rst @@ -349,6 +349,8 @@ Code Seq# Include File = Comments 0xA5 20-2F linux/surface_aggregator/dtx.h Mic= rosoft Surface DTX driver +0xA6 00-0F uapi/linux/alloc_tag.h Mem= ory allocation profiling + 0xAA 00-3F linux/uapi/linux/userfaultfd.h 0xAB 00-1F linux/nbd.h 0xAC 00-1F linux/raw.h diff --git a/include/linux/codetag.h b/include/linux/codetag.h index 8ea2a5f7c98a..2bcd4e7c809e 100644 --- a/include/linux/codetag.h +++ b/include/linux/codetag.h @@ -76,6 +76,7 @@ struct codetag_iterator { =20 void codetag_lock_module_list(struct codetag_type *cttype, bool lock); bool codetag_trylock_module_list(struct codetag_type *cttype); +unsigned long codetag_get_content_id(struct codetag_type *cttype); struct codetag_iterator codetag_get_ct_iter(struct codetag_type *cttype); struct codetag *codetag_next_ct(struct codetag_iterator *iter); =20 diff --git a/include/uapi/linux/alloc_tag.h b/include/uapi/linux/alloc_tag.h new file mode 100644 index 000000000000..e9a5b55fcc7a --- /dev/null +++ b/include/uapi/linux/alloc_tag.h @@ -0,0 +1,54 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * include/linux/alloc_tag.h + */ + +#ifndef _UAPI_ALLOC_TAG_H +#define _UAPI_ALLOC_TAG_H + +#include + +#define ALLOCINFO_STR_SIZE 64 + +struct allocinfo_content_id { + __u64 id; +}; + +struct allocinfo_tag { + /* Longer names are trimmed */ + char modname[ALLOCINFO_STR_SIZE]; + char function[ALLOCINFO_STR_SIZE]; + char filename[ALLOCINFO_STR_SIZE]; + __u64 lineno; +}; + +struct allocinfo_counter { + __u64 bytes; + __u64 calls; + __u8 accurate; + __u8 pad[7]; /* Add alignment to not break the 32-bit compatible interfac= e */ +}; + +struct allocinfo_tag_data { + struct allocinfo_tag tag; + struct allocinfo_counter counter; +}; + +struct allocinfo_get_at { + __u64 pos; /* input */ + struct allocinfo_tag_data data; +}; + +#define _ALLOCINFO_IOC_CONTENT_ID 0 +#define _ALLOCINFO_IOC_GET_AT 1 +#define _ALLOCINFO_IOC_GET_NEXT 2 + +#define ALLOCINFO_IOC_BASE 0xA6 +#define ALLOCINFO_IOC_CONTENT_ID _IOR(ALLOCINFO_IOC_BASE, _ALLOCINFO_IOC_C= ONTENT_ID, \ + struct allocinfo_content_id) +#define ALLOCINFO_IOC_GET_AT _IOWR(ALLOCINFO_IOC_BASE, _ALLOCINFO_IOC_GET= _AT, \ + struct allocinfo_get_at) +#define ALLOCINFO_IOC_GET_NEXT _IOR(ALLOCINFO_IOC_BASE, _ALLOCINFO_IOC_GE= T_NEXT, \ + struct allocinfo_tag_data) + +#endif /* _UAPI_ALLOC_TAG_H */ diff --git a/lib/alloc_tag.c b/lib/alloc_tag.c index ed1bdcf1f8ab..5c24d2f954d4 100644 --- a/lib/alloc_tag.c +++ b/lib/alloc_tag.c @@ -14,6 +14,7 @@ #include #include #include +#include =20 #define ALLOCINFO_FILE_NAME "allocinfo" #define MODULE_ALLOC_TAG_VMAP_SIZE (100000UL * sizeof(struct alloc_tag)) @@ -46,6 +47,9 @@ int alloc_tag_ref_offs; struct allocinfo_private { struct codetag_iterator iter; bool print_header; + /* ioctl uses a separate iterator not to interfere with reads */ + struct codetag_iterator ioctl_iter; + bool positioned; /* seq_open_private() sets to 0 */ }; =20 static void *allocinfo_start(struct seq_file *m, loff_t *pos) @@ -125,6 +129,177 @@ static const struct seq_operations allocinfo_seq_op = =3D { .show =3D allocinfo_show, }; =20 +static int allocinfo_open(struct inode *inode, struct file *file) +{ + return seq_open_private(file, &allocinfo_seq_op, + sizeof(struct allocinfo_private)); +} + +static int allocinfo_release(struct inode *inode, struct file *file) +{ + return seq_release_private(inode, file); +} + +static const char *allocinfo_str(const char *str) +{ + size_t len =3D strlen(str); + + /* Keep an extra space for the trailing NULL. */ + if (len >=3D ALLOCINFO_STR_SIZE) + str +=3D (len - ALLOCINFO_STR_SIZE) + 1; + return str; +} + +/* Copy a string and trim from the beginning if it's too long */ +static void allocinfo_copy_str(char *dest, const char *src) +{ + strscpy(dest, allocinfo_str(src), ALLOCINFO_STR_SIZE); +} + +static void allocinfo_to_params(struct codetag *ct, + struct allocinfo_tag_data *data) +{ + struct alloc_tag *tag =3D ct_to_alloc_tag(ct); + struct alloc_tag_counters counter =3D alloc_tag_read(tag); + + if (ct->modname) + allocinfo_copy_str(data->tag.modname, ct->modname); + else + data->tag.modname[0] =3D '\0'; + allocinfo_copy_str(data->tag.function, ct->function); + allocinfo_copy_str(data->tag.filename, ct->filename); + data->tag.lineno =3D ct->lineno; + data->counter.bytes =3D counter.bytes; + data->counter.calls =3D counter.calls; + data->counter.accurate =3D !alloc_tag_is_inaccurate(tag); +} + +static int allocinfo_ioctl_get_content_id(struct seq_file *m, void __user = *arg) +{ + struct allocinfo_content_id params; + + codetag_lock_module_list(alloc_tag_cttype, true); + params.id =3D codetag_get_content_id(alloc_tag_cttype); + codetag_lock_module_list(alloc_tag_cttype, false); + if (copy_to_user(arg, ¶ms, sizeof(params))) + return -EFAULT; + + return 0; +} + +static int allocinfo_ioctl_get_at(struct seq_file *m, void __user *arg) +{ + struct allocinfo_private *priv; + struct codetag *ct; + __u64 pos; + struct allocinfo_get_at params =3D {0}; + + if (copy_from_user(¶ms, arg, sizeof(params))) + return -EFAULT; + + priv =3D (struct allocinfo_private *)m->private; + pos =3D params.pos; + + codetag_lock_module_list(alloc_tag_cttype, true); + + /* Find the codetag */ + priv->ioctl_iter =3D codetag_get_ct_iter(alloc_tag_cttype); + ct =3D codetag_next_ct(&priv->ioctl_iter); + while (ct && pos--) + ct =3D codetag_next_ct(&priv->ioctl_iter); + if (ct) { + allocinfo_to_params(ct, ¶ms.data); + priv->positioned =3D true; + } + + codetag_lock_module_list(alloc_tag_cttype, false); + + if (!ct) + return -ENOENT; + + if (copy_to_user(arg, ¶ms, sizeof(params))) + return -EFAULT; + + return 0; +} + +static int allocinfo_ioctl_get_next(struct seq_file *m, void __user *arg) +{ + struct allocinfo_private *priv; + struct codetag *ct; + struct allocinfo_tag_data params =3D {0}; + int ret =3D 0; + + priv =3D (struct allocinfo_private *)m->private; + + codetag_lock_module_list(alloc_tag_cttype, true); + + if (!priv->positioned) { + priv->ioctl_iter =3D codetag_get_ct_iter(alloc_tag_cttype); + priv->positioned =3D true; + } + + ct =3D codetag_next_ct(&priv->ioctl_iter); + if (ct) + allocinfo_to_params(ct, ¶ms); + + if (!ct) { + priv->positioned =3D false; + ret =3D -ENOENT; + } + codetag_lock_module_list(alloc_tag_cttype, false); + + if (ret =3D=3D 0) { + if (copy_to_user(arg, ¶ms, sizeof(params))) + return -EFAULT; + } + return ret; +} + +static long allocinfo_ioctl(struct file *file, unsigned int cmd, + unsigned long __arg) +{ + void __user *arg =3D (void __user *)__arg; + int ret; + + switch (cmd) { + case ALLOCINFO_IOC_CONTENT_ID: + ret =3D allocinfo_ioctl_get_content_id(file->private_data, arg); + break; + case ALLOCINFO_IOC_GET_AT: + ret =3D allocinfo_ioctl_get_at(file->private_data, arg); + break; + case ALLOCINFO_IOC_GET_NEXT: + ret =3D allocinfo_ioctl_get_next(file->private_data, arg); + break; + default: + ret =3D -ENOIOCTLCMD; + break; + } + + return ret; +} + +#ifdef CONFIG_COMPAT +static long allocinfo_compat_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + return allocinfo_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); +} +#endif + +static const struct proc_ops allocinfo_proc_ops =3D { + .proc_open =3D allocinfo_open, + .proc_read_iter =3D seq_read_iter, + .proc_lseek =3D seq_lseek, + .proc_release =3D allocinfo_release, + .proc_ioctl =3D allocinfo_ioctl, +#ifdef CONFIG_COMPAT + .proc_compat_ioctl =3D allocinfo_compat_ioctl, +#endif + +}; + size_t alloc_tag_top_users(struct codetag_bytes *tags, size_t count, bool = can_sleep) { struct codetag_iterator iter; @@ -946,8 +1121,7 @@ static int __init alloc_tag_init(void) return 0; } =20 - if (!proc_create_seq_private(ALLOCINFO_FILE_NAME, 0400, NULL, &allocinfo_= seq_op, - sizeof(struct allocinfo_private), NULL)) { + if (!proc_create(ALLOCINFO_FILE_NAME, 0400, NULL, &allocinfo_proc_ops)) { pr_err("Failed to create %s file\n", ALLOCINFO_FILE_NAME); shutdown_mem_profiling(false); return -ENOMEM; diff --git a/lib/codetag.c b/lib/codetag.c index 304667897ad4..93aa30991563 100644 --- a/lib/codetag.c +++ b/lib/codetag.c @@ -48,6 +48,17 @@ bool codetag_trylock_module_list(struct codetag_type *ct= type) return down_read_trylock(&cttype->mod_lock) !=3D 0; } =20 +unsigned long codetag_get_content_id(struct codetag_type *cttype) +{ + lockdep_assert_held(&cttype->mod_lock); + + /* + * next_mod_seq is updated on every load, so can be used to identify + * content changes. + */ + return cttype->next_mod_seq; +} + struct codetag_iterator codetag_get_ct_iter(struct codetag_type *cttype) { struct codetag_iterator iter =3D { --=20 2.54.0.545.g6539524ca2-goog From nobody Sun Jun 14 01:44:49 2026 Received: from mail-dy1-f201.google.com (mail-dy1-f201.google.com [74.125.82.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EDA752264A9 for ; Mon, 4 May 2026 23:36:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777937795; cv=none; b=qUWweyJiTwkCfwp5J0QF49yAKLezRYsPvs/F2EtDzIqSsKXs7PbPwBEi7drh+6krcbpU2fV5mfY3pMUTew4CL1DE7SYKcPdEdFVx6s9HtzDh6bK6zx0B+zVNU5DxwWiScpmnBOhh+daNpkB3dAfhRS8DkBKrUkIsfKS+tQrEV1I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777937795; c=relaxed/simple; bh=O5GFVRYXtZjXkiZL0LDRQ6w4GTBctnx+XTp600SssqU=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=CnhbxymSYZPRlPJNc2HibGZpzJ8wCAHZZKhj2oGSt7OkowrTY7BrsC976F0Tn7oATEANVfD3OO3mtgkNiLwwmSONSWoXM3X9AcxpgTDfo93oRwTui8nQuTL4wgTVAzU42QWnXbjxEXOzSfDbErb3M3H7ekYSKO65L9u/KHw1Z3g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--abhishekbapat.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=VKC+v2fO; arc=none smtp.client-ip=74.125.82.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--abhishekbapat.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="VKC+v2fO" Received: by mail-dy1-f201.google.com with SMTP id 5a478bee46e88-2c0f6593ef5so6682969eec.1 for ; Mon, 04 May 2026 16:36:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1777937793; x=1778542593; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=P8In7SqV1CDaELSYurDVfz0X7xi71y9ocBNy94kYNvE=; b=VKC+v2fOEw4FqQ1siRB9N8EEcikOQQzarTkwrhzGxiedMEAqCgkD1uqlp/kk3hG08H oIFg6X3qv+4ciAkqHihUzVU1yn837bpBLoHQPLTf/BEdQfeAJNjkJZmszy/ryIEkubqh OlTSQNk1uwKRZSqtyyvIimmh8UKl/vmn53b8X0v1KKe1daHZe4jt/foDGQsi9GGw3vRX pKe+B9CEgDOob34WGQqQPJaNREENS/OhhX3eU7WHDQvBhPEVJO5y0jtCeNSiqIzAQizu s4XWMA1FHxf39+IHpt1ATRl6tvYT5dAtXqnRQvezaH8G0O2UpO9xN4AzaHUifuNrrcmB 6R6w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777937793; x=1778542593; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=P8In7SqV1CDaELSYurDVfz0X7xi71y9ocBNy94kYNvE=; b=i/4Z7AbOv3MtQbdw9sI9Qn4JwHAoQsHyLSiaVooruiT9cjj3WPkA4vCKCXtv1KePPa C8CHbEfw4lPQLbVexzP9G7rqdmryOyBE4C265K/AMcDZfyejw70yu8DW+Nbw6wSCV90U 9ZE3FLjBScCrfsse4BZ3Qcnl9/AcbNFARttigBoInyo0s3JLRc8zmWbCrudWdq5tkJ0k osUTNALu8EDJIrAoqjtXOSpvSN0vR5wIZgZpQHAi93OT/8Glj1y4U9IcjmB+noKjWaiM NYvRIyqVyjI0y8IYfVLDYg+s8aUXO3VPoY8gNOldPRIbSz99V7qGuc93BS0HyjWIr2wn hztA== X-Forwarded-Encrypted: i=1; AFNElJ/87eh4zyy3T1knPALSsaer4sakPuxjKHqGkcFvHrZh8cbegqEFda2KtZm8TiiUUPeRXX/saTryeBATJ+k=@vger.kernel.org X-Gm-Message-State: AOJu0YxJerWoxQoWwPVZWSZMIPEWuus2E2mdS8L5e3vkK56vT7FVqH/7 EbNYpvkjiJ7H97cgzVtKItM99TFfZj8q3DmfkX70khhDP2oX7qlx/bQwLcgDi0qsjTv5b439gEG GXEeOqwNthDviJpn+9KO1s0RTXzXMXXZHaA== X-Received: from dybmk34.prod.google.com ([2002:a05:7301:ea2:b0:2ed:a84e:18d3]) (user=abhishekbapat job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7300:7fa0:b0:2ea:e93a:ff9b with SMTP id 5a478bee46e88-2f408519825mr409335eec.13.1777937792756; Mon, 04 May 2026 16:36:32 -0700 (PDT) Date: Mon, 4 May 2026 23:36:20 +0000 In-Reply-To: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog Message-ID: <2d1cbd93b987198d9569ff54b7fee4ae6aad5ff6.1777936301.git.abhishekbapat@google.com> Subject: [PATCH 2/6] alloc_tag: add ioctl filters to /proc/allocinfo From: Abhishek Bapat To: Suren Baghdasaryan , Andrew Morton , Kent Overstreet Cc: Shuah Khan , Jonathan Corbet , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, Sourav Panda , Abhishek Bapat Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extend the capability of the IOCTL mechanism to filter allocations based on tag's module name, function name, file name and line number. Signed-off-by: Abhishek Bapat --- include/uapi/linux/alloc_tag.h | 26 +++++++++++++++- lib/alloc_tag.c | 55 ++++++++++++++++++++++++++++++++-- 2 files changed, 77 insertions(+), 4 deletions(-) diff --git a/include/uapi/linux/alloc_tag.h b/include/uapi/linux/alloc_tag.h index e9a5b55fcc7a..0cc9db5298c6 100644 --- a/include/uapi/linux/alloc_tag.h +++ b/include/uapi/linux/alloc_tag.h @@ -34,8 +34,32 @@ struct allocinfo_tag_data { struct allocinfo_counter counter; }; =20 +enum { + ALLOCINFO_FILTER_MODNAME, + ALLOCINFO_FILTER_FUNCTION, + ALLOCINFO_FILTER_FILENAME, + ALLOCINFO_FILTER_LINENO, + __ALLOCINFO_FILTER_LAST =3D ALLOCINFO_FILTER_LINENO +}; + +#define ALLOCINFO_FILTER_MASK_MODNAME (1 << ALLOCINFO_FILTER_MODNAME) +#define ALLOCINFO_FILTER_MASK_FUNCTION (1 << ALLOCINFO_FILTER_FUNCTION) +#define ALLOCINFO_FILTER_MASK_FILENAME (1 << ALLOCINFO_FILTER_FILENAME) +#define ALLOCINFO_FILTER_MASK_LINENO (1 << ALLOCINFO_FILTER_LINENO) + +#define ALLOCINFO_FILTER_MASKS \ + ((1 << (__ALLOCINFO_FILTER_LAST + 1)) - 1) + +struct allocinfo_filter { + __u64 mask; /* bitmask of the filter fields used */ + struct allocinfo_tag fields; +}; + struct allocinfo_get_at { - __u64 pos; /* input */ + /* inputs */ + __u64 pos; + struct allocinfo_filter filter; + /* output */ struct allocinfo_tag_data data; }; =20 diff --git a/lib/alloc_tag.c b/lib/alloc_tag.c index 5c24d2f954d4..7ff936e15e97 100644 --- a/lib/alloc_tag.c +++ b/lib/alloc_tag.c @@ -47,6 +47,7 @@ int alloc_tag_ref_offs; struct allocinfo_private { struct codetag_iterator iter; bool print_header; + struct allocinfo_filter filter; /* ioctl uses a separate iterator not to interfere with reads */ struct codetag_iterator ioctl_iter; bool positioned; /* seq_open_private() sets to 0 */ @@ -156,6 +157,11 @@ static void allocinfo_copy_str(char *dest, const char = *src) strscpy(dest, allocinfo_str(src), ALLOCINFO_STR_SIZE); } =20 +static int allocinfo_cmp_str(const char *str, const char *template) +{ + return strncmp(allocinfo_str(str), template, ALLOCINFO_STR_SIZE); +} + static void allocinfo_to_params(struct codetag *ct, struct allocinfo_tag_data *data) { @@ -187,26 +193,67 @@ static int allocinfo_ioctl_get_content_id(struct seq_= file *m, void __user *arg) return 0; } =20 +static bool matches_filter(struct codetag *ct, struct allocinfo_filter *fi= lter) +{ + if (!ct || !filter || !filter->mask) + return true; + + if ((filter->mask & ALLOCINFO_FILTER_MASK_MODNAME) && + ct->modname && (allocinfo_cmp_str(ct->modname, filter->fields.modname= ))) + return false; + + if ((filter->mask & ALLOCINFO_FILTER_MASK_FUNCTION) && + ct->function && (allocinfo_cmp_str(ct->function, filter->fields.funct= ion))) + return false; + + if ((filter->mask & ALLOCINFO_FILTER_MASK_FILENAME) && + ct->filename && (allocinfo_cmp_str(ct->filename, filter->fields.filen= ame))) + return false; + + if ((filter->mask & ALLOCINFO_FILTER_MASK_LINENO) && + ct->lineno !=3D filter->fields.lineno) + return false; + + return true; +} + static int allocinfo_ioctl_get_at(struct seq_file *m, void __user *arg) { struct allocinfo_private *priv; struct codetag *ct; - __u64 pos; struct allocinfo_get_at params =3D {0}; + __u64 skip_count; =20 if (copy_from_user(¶ms, arg, sizeof(params))) return -EFAULT; =20 + if (params.filter.mask & ~ALLOCINFO_FILTER_MASKS) + return -EINVAL; + priv =3D (struct allocinfo_private *)m->private; - pos =3D params.pos; + + skip_count =3D params.pos; =20 codetag_lock_module_list(alloc_tag_cttype, true); =20 + if (params.filter.mask) + priv->filter =3D params.filter; + else + priv->filter.mask =3D 0; + /* Find the codetag */ priv->ioctl_iter =3D codetag_get_ct_iter(alloc_tag_cttype); ct =3D codetag_next_ct(&priv->ioctl_iter); - while (ct && pos--) + + while (ct) { + if (matches_filter(ct, &priv->filter)) { + if (skip_count =3D=3D 0) + break; + skip_count--; + } ct =3D codetag_next_ct(&priv->ioctl_iter); + } + if (ct) { allocinfo_to_params(ct, ¶ms.data); priv->positioned =3D true; @@ -240,6 +287,8 @@ static int allocinfo_ioctl_get_next(struct seq_file *m,= void __user *arg) } =20 ct =3D codetag_next_ct(&priv->ioctl_iter); + while (ct && !matches_filter(ct, &priv->filter)) + ct =3D codetag_next_ct(&priv->ioctl_iter); if (ct) allocinfo_to_params(ct, ¶ms); =20 --=20 2.54.0.545.g6539524ca2-goog From nobody Sun Jun 14 01:44:49 2026 Received: from mail-dy1-f201.google.com (mail-dy1-f201.google.com [74.125.82.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4979B3DD533 for ; Mon, 4 May 2026 23:36:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777937797; cv=none; b=r3u62nGrqYj0hFMZpKOw9FlSDF1U8z4ZVypcWA6XrKl9ZBn6JuGsizt9CaG/z4IpWGq0R84Hw5ibQsRGNXy6eAXlhwB1R/lojLRPyD0gCp3IdUPnIrgjYNl8b8XBeEvOsCtldD5gaFTNZ/9dmtS9x7GuIxyCKq8+Gp3LyBaZWYM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777937797; c=relaxed/simple; bh=2tj/mjQmlaxHamp83p2PwwrXMefMcBjdUBuZAQhz9X8=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=fMgnrn3EODo8eAxKOIG7oFZsPtIRUsU6TUKWjzDQG75lT0+x3VjeLDwMWFGvMJHeYUsVs602ngrT7RYE7CjFFvNp1FwV2Rw8oi4YISjBbpgOHEoaqsbaf69w5EhQPglNyOggK+yMLlyRRMeML9EpRcd9ajB97j5pfhIs32w5NpQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--abhishekbapat.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=uEtltYgt; arc=none smtp.client-ip=74.125.82.201 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--abhishekbapat.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="uEtltYgt" Received: by mail-dy1-f201.google.com with SMTP id 5a478bee46e88-2ef62078ee7so2462626eec.0 for ; Mon, 04 May 2026 16:36:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1777937795; x=1778542595; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=a6S6DlMMQcGikJO+VWHR/PLbk/eNEQ6Kb3xIzqUHnnk=; b=uEtltYgtg+fS+sAJ8K0odxPHx5u/xlwoDTBtEopWN2I9ytrpEO427q/Xydu0+TEj5N AcVKUIAi4RPV1XVv8gWzYxlnN86a1gRnT9Ola+pxF2WeyCzq5Ms1/241VSa3nbP4c2hP cVKkRyeWwuCB4s9riNgxFSJKDzssBmKJ1pd7bT1PweeBBFRPIcUkqAhSBu/q4d4mJ2Os mbGvxiwoAf7ItZjidQYKNzJ4wlR3VYnncJfOH1MP2LpN3vah9R0h/gv7Mr3Y2rr57yhA s7AHPA8ViB470oQaUUbW/DkM35wqr0a1Ydsd0320qxld+DlCPJjUBae8o4IkxzHcfe0+ aMog== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777937795; x=1778542595; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=a6S6DlMMQcGikJO+VWHR/PLbk/eNEQ6Kb3xIzqUHnnk=; b=BitK/nQP3viVSE0f0Z7C6lVmItNJEWjfMIJG0YnMzKmgEznsmeUWZ/37nc+ZLNfgah +dKznO3qZfJe3C6a20qHfikWRcY+lzxGiqwflBuGQj4ib2ZXTNrMjx2pIp8cAv98KruI 3y/rV4hRp+A/clW0wdkZmJddjp55lRr2dAsLbICmZQ+V8tpicAFlA2gj66eY1llsDnGS 2/ly+2ZfA4tU6jmYIO4PV5tPKpydUIl6hktc6LwlQ9dZLSsBuXu6SpkEb7brcEFDfhnI zNEJemtf5ndZnKNb3QjE5W2iqL9omXpj3t4XAAtMCWVSF3sIKQojj9TfUbEOic6Rbdbi wp2A== X-Forwarded-Encrypted: i=1; AFNElJ/2Xb+Y1B/Pjex9KHZc0XQ/yU6S6U0ce3eDffH8N0Ak3gvcKxlW1YJGoYKO84U2FXOBXRQGV6hgTy+uC58=@vger.kernel.org X-Gm-Message-State: AOJu0Yxj7QtA/wDt0iq9lzMkxEVTNZLSyhQKl4BvVIGXwe0neWq+M7hD BdO/Qxv5FkT4c0PN4ATioDkYDrdvUv9P/mVdURf4W9LUvbKSituy/Dh2yQYfA7htODngk8fSgoQ s05K4YR9yOC5h9I4RLzsW0a4EAYP1dPBx/Q== X-Received: from dycoh3.prod.google.com ([2002:a05:7301:da03:b0:2f2:3f95:c586]) (user=abhishekbapat job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7300:5709:b0:2ed:e14:7f5c with SMTP id 5a478bee46e88-2f40a190047mr396805eec.32.1777937795111; Mon, 04 May 2026 16:36:35 -0700 (PDT) Date: Mon, 4 May 2026 23:36:21 +0000 In-Reply-To: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog Message-ID: <06b4fc2457fb4b75eb1ef18320a8722ddb5a850f.1777936301.git.abhishekbapat@google.com> Subject: [PATCH 3/6] alloc_tag: add size-based filtering to ioctl From: Abhishek Bapat To: Suren Baghdasaryan , Andrew Morton , Kent Overstreet Cc: Shuah Khan , Jonathan Corbet , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, Sourav Panda , Abhishek Bapat Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extend the allocinfo filtering mechanism to allow users to filter tags based on the total number of bytes allocated [min_size, max_size]. The size range is inclusive. Filtering by size involves retrieving allocinfo per-CPU counters, which is an expensive operation. Hence, the performance of size-based filtering will be worse than other filters. Signed-off-by: Abhishek Bapat --- include/uapi/linux/alloc_tag.h | 8 +++++++- lib/alloc_tag.c | 15 +++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/alloc_tag.h b/include/uapi/linux/alloc_tag.h index 0cc9db5298c6..229068efd24c 100644 --- a/include/uapi/linux/alloc_tag.h +++ b/include/uapi/linux/alloc_tag.h @@ -20,6 +20,8 @@ struct allocinfo_tag { char function[ALLOCINFO_STR_SIZE]; char filename[ALLOCINFO_STR_SIZE]; __u64 lineno; + __u64 min_size; + __u64 max_size; }; =20 struct allocinfo_counter { @@ -39,13 +41,17 @@ enum { ALLOCINFO_FILTER_FUNCTION, ALLOCINFO_FILTER_FILENAME, ALLOCINFO_FILTER_LINENO, - __ALLOCINFO_FILTER_LAST =3D ALLOCINFO_FILTER_LINENO + ALLOCINFO_FILTER_MIN_SIZE, + ALLOCINFO_FILTER_MAX_SIZE, + __ALLOCINFO_FILTER_LAST =3D ALLOCINFO_FILTER_MAX_SIZE }; =20 #define ALLOCINFO_FILTER_MASK_MODNAME (1 << ALLOCINFO_FILTER_MODNAME) #define ALLOCINFO_FILTER_MASK_FUNCTION (1 << ALLOCINFO_FILTER_FUNCTION) #define ALLOCINFO_FILTER_MASK_FILENAME (1 << ALLOCINFO_FILTER_FILENAME) #define ALLOCINFO_FILTER_MASK_LINENO (1 << ALLOCINFO_FILTER_LINENO) +#define ALLOCINFO_FILTER_MASK_MIN_SIZE (1 << ALLOCINFO_FILTER_MIN_SIZE) +#define ALLOCINFO_FILTER_MASK_MAX_SIZE (1 << ALLOCINFO_FILTER_MAX_SIZE) =20 #define ALLOCINFO_FILTER_MASKS \ ((1 << (__ALLOCINFO_FILTER_LAST + 1)) - 1) diff --git a/lib/alloc_tag.c b/lib/alloc_tag.c index 7ff936e15e97..98a27c302928 100644 --- a/lib/alloc_tag.c +++ b/lib/alloc_tag.c @@ -195,6 +195,9 @@ static int allocinfo_ioctl_get_content_id(struct seq_fi= le *m, void __user *arg) =20 static bool matches_filter(struct codetag *ct, struct allocinfo_filter *fi= lter) { + struct alloc_tag *tag; + struct alloc_tag_counters counters; + if (!ct || !filter || !filter->mask) return true; =20 @@ -214,6 +217,18 @@ static bool matches_filter(struct codetag *ct, struct = allocinfo_filter *filter) ct->lineno !=3D filter->fields.lineno) return false; =20 + if ((filter->mask & ALLOCINFO_FILTER_MASK_MIN_SIZE) || + (filter->mask & ALLOCINFO_FILTER_MASK_MAX_SIZE)) { + tag =3D ct_to_alloc_tag(ct); + counters =3D alloc_tag_read(tag); + if ((filter->mask & ALLOCINFO_FILTER_MASK_MIN_SIZE) && + counters.bytes < filter->fields.min_size) + return false; + if ((filter->mask & ALLOCINFO_FILTER_MASK_MAX_SIZE) && + counters.bytes > filter->fields.max_size) + return false; + } + return true; } =20 --=20 2.54.0.545.g6539524ca2-goog From nobody Sun Jun 14 01:44:49 2026 Received: from mail-dy1-f202.google.com (mail-dy1-f202.google.com [74.125.82.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A6AC83E6381 for ; Mon, 4 May 2026 23:36:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777937803; cv=none; b=ADzFxNPfgHCLt6L9++aJ7rEJQT/zTU27HpZyeJAc9qWe3xlKjUhapM4tQoSbXz1jHLUNWd/eztOyaZYyCO99eHu0UBtPR2IG0VITkjZHqaETkUfeHMiiQaHWEsT+nBFNvtJO9GdX3MHSU2poyf6rmy5Qz2qoYF6gpBQ56k6eA4M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777937803; c=relaxed/simple; bh=51JYkKcoObz7U76H6J2lOAG7KYNGj04Z1Oio5sQiOrU=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=MGXmKT/s0MLTi6lBs7FjvjKAez3nnSKkYt6mTZfcyejR38K9rZwiEbT/JihWGrVSvJ7HiBZww+JGSKaKNCyRqiipH/qCe8rLeMofKrA34cES/Q2UsoINyTG2/SjWXPorNfe8Ieb/3dvzRACcpQM8jZUh93ljLx1tik3Pl5QtsQ4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--abhishekbapat.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=AEQsM+q4; arc=none smtp.client-ip=74.125.82.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--abhishekbapat.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="AEQsM+q4" Received: by mail-dy1-f202.google.com with SMTP id 5a478bee46e88-2eebb099efbso8254182eec.0 for ; Mon, 04 May 2026 16:36:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1777937798; x=1778542598; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=vwKDNFxCHplCHNXs9frgTkD+bqZx+jlVLXfcJGvps6s=; b=AEQsM+q4cmutv44ucAjZX6g4c5L/PmpPXzUh0Ddqs1/Mav0Ar7UF1y11nKAe2QDYaW tMQW03grecKTFhhrvUvuATUriBbIlUByNp9hpm5BUd2aaX+b4U1gcD4MXDGrFFXlQnQ+ VxvLTm3iGzEAH0Kj+Nrn5xfljEyvWDhdjtr9OrWEyvOc4YBycKGVvgOWufeV0qnRq3fR gpypXAJKNt1vXcejElyzItzSPR1PuorFE4c4erd3HgF8BRGyyaA2dmjF5AeeaH0Co3/y Au2KC01XRUrkudXVL16YaGikRSssHpmi17OLYs5b+pNDeV4luq87cVWXBJDa2mZCGvEt COhA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777937798; x=1778542598; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=vwKDNFxCHplCHNXs9frgTkD+bqZx+jlVLXfcJGvps6s=; b=GmFIOKvRWhgandq1trcNFG8IF7xKfWSKdcpqNiDzhZxJ+dJ3iPs9Vfdvv+GVLcRKGV crbiNaTYnzJqhuhs48kazN3R2gUBFywuuNTDfWPj6aiBV6lP7X69qMNnTnPbqO5ixGlH Xuac31ckm/px7LT8V/3LhuCMRd0kCkGXfLylTXBTheOZcI+GlVPJKJXAW2BhfXF/UZKR v/rRxl0KUgY7lbOcJBtCTuMl/iW25zaIYDoOq2wRG0/nb49AbPSgre4e6zy6RE8mdkIn WBlV6zy5me8C2ftsEsWqemp4G4dT4lwfFwRU2pyciMG+40uGm4HbDnM/KoIiimhmyCOU lzPA== X-Forwarded-Encrypted: i=1; AFNElJ8yOAGcYhJ4lKvM85y9g2fpiHe4lyp4brkyM6j/RVOa/E9jhT+T+m/ZShwrDKJWnB6ud19m/RDJmY2Ck50=@vger.kernel.org X-Gm-Message-State: AOJu0YwDlxO6WtCJXAa49sC2J4DQTfQOQoc08UDZ/FU5AEkbrdcExE48 8mVQvAuJx1CjSksjTup0eKzk2JjEUkWACpZkZgPa43CkAs+LtoBR/wcAxQGwlljPRJz2NmQnJZ1 uOOeVhKQi7kc57vqbAU2iJlwdMtWwD9XqlQ== X-Received: from dyctt4.prod.google.com ([2002:a05:693c:3e44:b0:2f1:5dbf:fd4e]) (user=abhishekbapat job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7300:fe0b:b0:2e0:4edd:64e4 with SMTP id 5a478bee46e88-2efba178867mr6138179eec.26.1777937797656; Mon, 04 May 2026 16:36:37 -0700 (PDT) Date: Mon, 4 May 2026 23:36:22 +0000 In-Reply-To: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog Message-ID: <3d6ba4a1b49489b8138a4736704fccb9ed00bef3.1777936301.git.abhishekbapat@google.com> Subject: [PATCH 4/6] alloc_tag: add accuracy based filtering to ioctl From: Abhishek Bapat To: Suren Baghdasaryan , Andrew Morton , Kent Overstreet Cc: Shuah Khan , Jonathan Corbet , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, Sourav Panda , Abhishek Bapat Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Extend the allocinfo filtering mechanism to allow users to filter tags based on their accuracy. Signed-off-by: Abhishek Bapat --- include/uapi/linux/alloc_tag.h | 3 +++ lib/alloc_tag.c | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/include/uapi/linux/alloc_tag.h b/include/uapi/linux/alloc_tag.h index 229068efd24c..99dfe951b185 100644 --- a/include/uapi/linux/alloc_tag.h +++ b/include/uapi/linux/alloc_tag.h @@ -20,6 +20,7 @@ struct allocinfo_tag { char function[ALLOCINFO_STR_SIZE]; char filename[ALLOCINFO_STR_SIZE]; __u64 lineno; + __u64 inaccurate; __u64 min_size; __u64 max_size; }; @@ -41,6 +42,7 @@ enum { ALLOCINFO_FILTER_FUNCTION, ALLOCINFO_FILTER_FILENAME, ALLOCINFO_FILTER_LINENO, + ALLOCINFO_FILTER_INACCURATE, ALLOCINFO_FILTER_MIN_SIZE, ALLOCINFO_FILTER_MAX_SIZE, __ALLOCINFO_FILTER_LAST =3D ALLOCINFO_FILTER_MAX_SIZE @@ -50,6 +52,7 @@ enum { #define ALLOCINFO_FILTER_MASK_FUNCTION (1 << ALLOCINFO_FILTER_FUNCTION) #define ALLOCINFO_FILTER_MASK_FILENAME (1 << ALLOCINFO_FILTER_FILENAME) #define ALLOCINFO_FILTER_MASK_LINENO (1 << ALLOCINFO_FILTER_LINENO) +#define ALLOCINFO_FILTER_MASK_INACCURATE (1 << ALLOCINFO_FILTER_INACCURATE) #define ALLOCINFO_FILTER_MASK_MIN_SIZE (1 << ALLOCINFO_FILTER_MIN_SIZE) #define ALLOCINFO_FILTER_MASK_MAX_SIZE (1 << ALLOCINFO_FILTER_MAX_SIZE) =20 diff --git a/lib/alloc_tag.c b/lib/alloc_tag.c index 98a27c302928..576ecb3c5b6c 100644 --- a/lib/alloc_tag.c +++ b/lib/alloc_tag.c @@ -197,6 +197,7 @@ static bool matches_filter(struct codetag *ct, struct a= llocinfo_filter *filter) { struct alloc_tag *tag; struct alloc_tag_counters counters; + bool inaccurate; =20 if (!ct || !filter || !filter->mask) return true; @@ -217,6 +218,12 @@ static bool matches_filter(struct codetag *ct, struct = allocinfo_filter *filter) ct->lineno !=3D filter->fields.lineno) return false; =20 + if (filter->mask & ALLOCINFO_FILTER_MASK_INACCURATE) { + inaccurate =3D !!(ct->flags & CODETAG_FLAG_INACCURATE); + if (inaccurate !=3D filter->fields.inaccurate) + return false; + } + if ((filter->mask & ALLOCINFO_FILTER_MASK_MIN_SIZE) || (filter->mask & ALLOCINFO_FILTER_MASK_MAX_SIZE)) { tag =3D ct_to_alloc_tag(ct); --=20 2.54.0.545.g6539524ca2-goog From nobody Sun Jun 14 01:44:49 2026 Received: from mail-dl1-f73.google.com (mail-dl1-f73.google.com [74.125.82.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 704373DD533 for ; Mon, 4 May 2026 23:36:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.73 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777937803; cv=none; b=WSqHPCiW7nSF8KfmvqeBrm4mp9bf44ifB1L3sA2cUeuTLd9cQUhGED87T20BLx0bVoiu7BE3K5Pu15WJiTsHszEES0xzFtPAjZV6xSBGMvKdgIkrp/VekEBtZN1DjqDTWFvciOPw8YMP5qq6kcAQm5LuZn4g/FsAKgSY40682PU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777937803; c=relaxed/simple; bh=t5zScYAHSzAE6u8f/w+ST1cF2Z8jzoAm1J120Ncer8w=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=ZMVWPNIxdAeHdTD/V6QxkcBUDmxzyY6NZ08ErjjLG2BpZfOrYUDug/h4a0dBGxKAJxiViJQQ6e/dOe5oTNdxJisftJfTnA+cD/OrqCZKLK3Xpmjf/BmAoANMA9mpHdUDda2d4bUfujJH1ISnMlkJw2N16mwYup6Xh2z2CuKNcoQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--abhishekbapat.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=bqj/+6tN; arc=none smtp.client-ip=74.125.82.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--abhishekbapat.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="bqj/+6tN" Received: by mail-dl1-f73.google.com with SMTP id a92af1059eb24-12dbf4f678eso25299614c88.0 for ; Mon, 04 May 2026 16:36:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1777937800; x=1778542600; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=clHgUoRKmFepHvgpWp4LqZgVIqiObGW8cZkna6OApEg=; b=bqj/+6tNT8rw9JRKZRvihHa5yvHBFj7NrtW5pzeiIo0iBA2Lvv8/yh1li/EeySXxZY IhkP17csTW3NHo37HP5FDuvtIAKGq4ASiBCmhh71s3f7vlxcpQoo3v4CFzcq19fWsFxJ vrUq7vQykIlhlwLLLqK7wGvxjb9lpBlshh+olWjlLpVZefEm8mGgbCd1kXyxNkn+H/fg MYuWpYQAWXh64AXI3qAauFl0f7Vdi8IFLfKnc2Sh443LjJ0EyTtMhFPdPRKGXViZ2ZEI QxaavFkyEttzVVcMrgjp48vM+51s+jpjuN/1cOgQmyPzeyqlTZ8ZnJsZiua8sGuohOfZ XDZw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777937800; x=1778542600; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=clHgUoRKmFepHvgpWp4LqZgVIqiObGW8cZkna6OApEg=; b=kzZQMuT6NaZk55vYyvKeHF/JoswZr+KVcWMzxq4gQ38MTzdkfBF82RK3uW+CafMDA0 49r8P9hj1F+6s79ExbqpCLPTdVfySLdkdAij7uC/pyMqx8Mm/tLPkANuqXaMDKwi+IxN eLmcmMZx43XaYPSpRCLfSW8AXxQWT875eDpxW2sAhJ9nHPFR4lhZmucMz5KACo/vBp2l TtlBWiMGpwbG9QoPrV/2HMtEymoglu/RJdJrqPRFN9B1jDUcjOtphqrhWGDPnod9QoSL h0uhKvfCpoDp6yJO9ALxN+v12ZLH3FQ0rxxyE2MJ2ahh9m7HJgK4iwVl0X8J/iLaGESU FexQ== X-Forwarded-Encrypted: i=1; AFNElJ/DUwMGjSxcF025jVTrNy0ivO44/24XxfyIGrq9FiupmTpPj9r2vMpvXvYFwqPsPf56iCpRFm4WOel0wS4=@vger.kernel.org X-Gm-Message-State: AOJu0Ywkkwqj6QtGBQNCHYJepP/eqgCqSkENwoNnOQ6ZkeEzqEuLccmV mWY/mg7WJSF/F1o6M4ruwMvJonbbt1GvH4wgBLKdJQz/2xTD/Ydj2eQ7n/WDV/FasTTp+azb0kP NK3sW8IZYVreJKmORuOVD6LC9Xmvjd1xf4w== X-Received: from dyau17.prod.google.com ([2002:a05:7300:6011:b0:2ed:fa8:caa3]) (user=abhishekbapat job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7022:78f:b0:128:dedf:f56d with SMTP id a92af1059eb24-12dfd81a853mr5607329c88.24.1777937800218; Mon, 04 May 2026 16:36:40 -0700 (PDT) Date: Mon, 4 May 2026 23:36:23 +0000 In-Reply-To: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog Message-ID: <6d8a2059a4625ef638062815d9586f7a083d02ec.1777936301.git.abhishekbapat@google.com> Subject: [PATCH 5/6] kselftest: alloc_tag: add kselftest for ioctl interface From: Abhishek Bapat To: Suren Baghdasaryan , Andrew Morton , Kent Overstreet Cc: Shuah Khan , Jonathan Corbet , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, Sourav Panda , Abhishek Bapat Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce a kselftest to verify the new IOCTL-based interface for /proc/allocinfo. The test covers: 1. Validation of the filename filter. 2. Validation of the function filter. The first test validates the functionality of the filename filter. Using "mm/memory.c" as the candidate filename filter, it retrieves filtered entries from both procfs and ioctl and matches the first VEC_MAX_ENTRIES entries. The second test validates the functionality of the function filter. It uses "dup_mm" as the candidate function as we do not expect this function name to change frequently and hence won't be needing to modify this test often. Note that both the tests match line no, function name and file name fields. Bytes allocated and calls are not matched as those values may change in the time when the data is being read from procfs and ioctl and hence can lead to false negatives. Signed-off-by: Abhishek Bapat --- tools/testing/selftests/alloc_tag/Makefile | 9 + .../alloc_tag/allocinfo_ioctl_test.c | 316 ++++++++++++++++++ 2 files changed, 325 insertions(+) create mode 100644 tools/testing/selftests/alloc_tag/Makefile create mode 100644 tools/testing/selftests/alloc_tag/allocinfo_ioctl_test.c diff --git a/tools/testing/selftests/alloc_tag/Makefile b/tools/testing/sel= ftests/alloc_tag/Makefile new file mode 100644 index 000000000000..f2b8fc022c3b --- /dev/null +++ b/tools/testing/selftests/alloc_tag/Makefile @@ -0,0 +1,9 @@ +# SPDX-License-Identifier: GPL-2.0 + +TEST_GEN_PROGS :=3D allocinfo_ioctl_test + +CFLAGS +=3D -Wall +CFLAGS +=3D -I../../../../usr/include + +include ../lib.mk + diff --git a/tools/testing/selftests/alloc_tag/allocinfo_ioctl_test.c b/too= ls/testing/selftests/alloc_tag/allocinfo_ioctl_test.c new file mode 100644 index 000000000000..543023ca3d27 --- /dev/null +++ b/tools/testing/selftests/alloc_tag/allocinfo_ioctl_test.c @@ -0,0 +1,316 @@ +// SPDX-License-Identifier: GPL-2.0-only + +/* kselftest for allocinfo ioctl + * allocinfo ioctl retrives allocinfo data through ioctl + * Copyright (C) 2026 Google, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../kselftest.h" + +#define MAX_LINE_LEN 512 +#define ALLOCINFO_PROC "/proc/allocinfo" + +enum ioctl_ret { + IOCTL_SUCCESS =3D 0, + IOCTL_FAILURE =3D 1, + IOCTL_INVALID_DATA =3D 2, +}; + +#define VEC_MAX_ENTRIES 32 + +struct allocinfo_tag_data_vec { + struct allocinfo_tag_data tag[VEC_MAX_ENTRIES]; + __u64 count; +}; + +static inline int __allocinfo_get_content_id(int dev_fd, struct allocinfo_= content_id *params) +{ + return ioctl(dev_fd, ALLOCINFO_IOC_CONTENT_ID, params); +} + +static inline int __allocinfo_get_at(int dev_fd, struct allocinfo_get_at *= params) +{ + return ioctl(dev_fd, ALLOCINFO_IOC_GET_AT, params); +} + +static inline int __allocinfo_get_next(int dev_fd, struct allocinfo_tag_da= ta *params) +{ + return ioctl(dev_fd, ALLOCINFO_IOC_GET_NEXT, params); +} + +static bool match_entry(const struct allocinfo_tag_data *procfs_entry, + const struct allocinfo_tag_data *tag_data, + bool match_bytes, bool match_calls, bool match_lineno, + bool match_function, bool match_filename) +{ + if (match_bytes && tag_data->counter.bytes !=3D procfs_entry->counter.byt= es) { + ksft_print_msg("size retrieved through ioctl does not match procfs\n"); + return false; + } + + if (match_calls && tag_data->counter.calls !=3D procfs_entry->counter.cal= ls) { + ksft_print_msg("call count retrieved through ioctl does not match procfs= \n"); + return false; + } + + if (match_lineno && tag_data->tag.lineno !=3D procfs_entry->tag.lineno) { + ksft_print_msg("lineno retrieved through ioctl does not match procfs\n"); + return false; + } + + if (match_function && + strncmp(tag_data->tag.function, procfs_entry->tag.function, ALLOCINFO= _STR_SIZE)) { + ksft_print_msg("function retrieved through ioctl does not match procfs\n= "); + return false; + } + + if (match_filename && + strncmp(tag_data->tag.filename, procfs_entry->tag.filename, ALLOCINFO= _STR_SIZE)) { + ksft_print_msg("filename retrieved through ioctl does not match procfs\n= "); + return false; + } + return true; +} + +static bool match_entries(const struct allocinfo_tag_data_vec *procfs_entr= ies, + const struct allocinfo_tag_data_vec *tags, + bool match_bytes, bool match_calls, bool match_lineno, + bool match_function, bool match_filename) +{ + __u64 i; + + if (procfs_entries->count !=3D tags->count) { + ksft_print_msg("Entry count mismatch. ioctl entries: %llu, proc entries:= %llu\n", + tags->count, procfs_entries->count); + return false; + } + for (i =3D 0; i < procfs_entries->count; i++) { + if (!match_entry(&procfs_entries->tag[i], &tags->tag[i], + match_bytes, match_calls, match_lineno, + match_function, match_filename)) { + ksft_print_msg("%lluth entry does not match.\n", i); + return false; + } + } + return true; +} + +static int get_filtered_procfs_entries(struct allocinfo_tag_data_vec *proc= fs_entries, + const struct allocinfo_filter *filter, int fd) +{ + FILE *fp =3D fdopen(fd, "r"); + char line[MAX_LINE_LEN]; + int matches, skip_lines =3D 2; + struct allocinfo_tag_data procfs_entry; + + if (!fp) { + ksft_print_msg("Failed to open " ALLOCINFO_PROC " for reading\n"); + return 1; + } + memset(procfs_entries, 0, sizeof(*procfs_entries)); + while (fgets(line, sizeof(line), fp) && procfs_entries->count < VEC_MAX_E= NTRIES) { + /*The first two procfs entries are for the header, so we skip them.*/ + if (skip_lines-- > 0) + continue; + + memset(&procfs_entry, 0, sizeof(procfs_entry)); + matches =3D sscanf(line, "%llu %llu %[^:]:%llu func:%s", + &procfs_entry.counter.bytes, + &procfs_entry.counter.calls, + procfs_entry.tag.filename, + &procfs_entry.tag.lineno, + procfs_entry.tag.function); + + if (matches !=3D 5) + continue; + + if (filter->mask & ALLOCINFO_FILTER_MASK_FILENAME) { + if (strncmp(procfs_entry.tag.filename, + filter->fields.filename, ALLOCINFO_STR_SIZE)) + continue; + } + if (filter->mask & ALLOCINFO_FILTER_MASK_FUNCTION) { + if (strncmp(procfs_entry.tag.function, + filter->fields.function, ALLOCINFO_STR_SIZE)) + continue; + } + if (filter->mask & ALLOCINFO_FILTER_MASK_LINENO) { + if (procfs_entry.tag.lineno !=3D filter->fields.lineno) + continue; + } + if (filter->mask & ALLOCINFO_FILTER_MASK_MIN_SIZE) { + if (procfs_entry.counter.bytes < filter->fields.min_size) + continue; + } + if (filter->mask & ALLOCINFO_FILTER_MASK_MAX_SIZE) { + if (procfs_entry.counter.bytes > filter->fields.max_size) + continue; + } + + memcpy(&procfs_entries->tag[procfs_entries->count++], &procfs_entry, + sizeof(procfs_entry)); + } + return 0; +} + +static enum ioctl_ret get_filtered_ioctl_entries(struct allocinfo_tag_data= _vec *tags, + const struct allocinfo_filter *filter, int fd, + __u64 start_pos) +{ + struct allocinfo_content_id start_cont_id, end_cont_id; + struct allocinfo_get_at get_at_params; + const int max_retries =3D 10; + int retry_count =3D 0; + int status; + + /* + * __allocinfo_get_content_id may return different values if a kernel mod= ule was loaded + * between the two calls. If that happens, the data gathered cannot be co= nsidered consistent + * and hence needs to be fetched again to avoid flakiness. + */ + do { + if (__allocinfo_get_content_id(fd, &start_cont_id)) { + ksft_print_msg("allocinfo_get_content_id failed\n"); + return IOCTL_FAILURE; + } + + memset(tags, 0, sizeof(*tags)); + memset(&get_at_params, 0, sizeof(get_at_params)); + memcpy(&get_at_params.filter, filter, sizeof(*filter)); + get_at_params.pos =3D start_pos; + if (__allocinfo_get_at(fd, &get_at_params)) { + ksft_print_msg("allocinfo_get_at failed\n"); + return IOCTL_FAILURE; + } + memcpy(&tags->tag[tags->count++], &get_at_params.data, sizeof(get_at_par= ams.data)); + + while (tags->count < VEC_MAX_ENTRIES && + __allocinfo_get_next(fd, &tags->tag[tags->count]) =3D=3D 0) + tags->count++; + + if (__allocinfo_get_content_id(fd, &end_cont_id)) { + ksft_print_msg("allocinfo_get_content_id failed\n"); + return IOCTL_FAILURE; + } + + if (start_cont_id.id =3D=3D end_cont_id.id) { + status =3D IOCTL_SUCCESS; + } else { + ksft_print_msg("allocinfo_get_content_id mismatch, retrying...\n"); + status =3D IOCTL_INVALID_DATA; + } + } while (status =3D=3D IOCTL_INVALID_DATA && retry_count++ < max_retries); + + return status; +} + +static int run_filter_test(const struct allocinfo_filter *filter) +{ + int fd; + struct allocinfo_tag_data_vec *tags =3D malloc(sizeof(*tags)); + struct allocinfo_tag_data_vec *procfs_entries =3D malloc(sizeof(*procfs_e= ntries)); + int ioctl_status; + int ret =3D KSFT_PASS; + + if (!tags || !procfs_entries) { + ksft_print_msg("Memory allocation failed.\n"); + ret =3D KSFT_FAIL; + goto freemem; + } + + fd =3D open(ALLOCINFO_PROC, O_RDONLY); + if (fd < 0) { + ksft_exit_skip("Failed to open " ALLOCINFO_PROC ": %s\n", strerror(errno= )); + ret =3D KSFT_FAIL; + goto freemem; + } + + if (get_filtered_procfs_entries(procfs_entries, filter, fd)) { + ksft_print_msg("Error retrieving entries from " ALLOCINFO_PROC "\n"); + ret =3D KSFT_FAIL; + goto exit; + } + + if (procfs_entries->count =3D=3D 0) { + ksft_print_msg("No entries found in " ALLOCINFO_PROC ", skipping test\n"= ); + ret =3D KSFT_SKIP; + goto exit; + } + + ioctl_status =3D get_filtered_ioctl_entries(tags, filter, fd, 0); + if (ioctl_status =3D=3D IOCTL_INVALID_DATA) { + ksft_print_msg("Trouble retrieving valid IOCTL entries, skipping.\n"); + ret =3D KSFT_SKIP; + goto exit; + } + if (ioctl_status =3D=3D IOCTL_FAILURE) { + ksft_print_msg("Error retrieving IOCTL entries.\n"); + ret =3D KSFT_FAIL; + goto exit; + } + + if (!match_entries(procfs_entries, tags, false, false, true, true, true)) + ret =3D KSFT_FAIL; + +exit: + close(fd); +freemem: + free(tags); + free(procfs_entries); + return ret; +} + +static int test_filename_filter(void) +{ + struct allocinfo_filter filter; + const char *target_filename =3D "mm/memory.c"; + + memset(&filter, 0, sizeof(filter)); + filter.mask |=3D ALLOCINFO_FILTER_MASK_FILENAME; + strncpy(filter.fields.filename, target_filename, ALLOCINFO_STR_SIZE); + + return run_filter_test(&filter); +} + +static int test_function_filter(void) +{ + struct allocinfo_filter filter; + const char *target_function =3D "dup_mm"; + + memset(&filter, 0, sizeof(filter)); + filter.mask |=3D ALLOCINFO_FILTER_MASK_FUNCTION; + strncpy(filter.fields.function, target_function, ALLOCINFO_STR_SIZE); + + return run_filter_test(&filter); +} + +int main(int argc, char *argv[]) +{ + int ret; + + ksft_set_plan(2); + + ret =3D test_filename_filter(); + if (ret =3D=3D KSFT_SKIP) + ksft_test_result_skip("Skipping test_filename_filter\n"); + else + ksft_test_result(ret =3D=3D KSFT_PASS, "test_filename_filter\n"); + + ret =3D test_function_filter(); + if (ret =3D=3D KSFT_SKIP) + ksft_test_result_skip("Skipping test_function_filter\n"); + else + ksft_test_result(ret =3D=3D KSFT_PASS, "test_function_filter\n"); + + ksft_finished(); +} --=20 2.54.0.545.g6539524ca2-goog From nobody Sun Jun 14 01:44:49 2026 Received: from mail-dy1-f202.google.com (mail-dy1-f202.google.com [74.125.82.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 49F2C3E3C50 for ; Mon, 4 May 2026 23:36:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.82.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777937806; cv=none; b=sI4v2xXl8bp2KDs9FMDgC77Q1ajbWfsh9GgI1x8FYMrgeGXGlvSgsEeTCBswVVSTzVmdXh1RiErQdhjtcmk6ZxzL+dEVbOP8G36AOni8iNRVRxvZR1Yehmo2Q88LXy4lLxK27mkuaw1FPSNtT17Hz0mUgefjJfamVvm2nEJenyE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1777937806; c=relaxed/simple; bh=+Rk1ExFYE/5E0lN6OmyGkdUYjVIsSU316GsMwHwOZRI=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=pMQ7Mfh8hrFarrsU/0xwsPPLBwJN6yDXWS/aoahSMVcepUnvKgRhTX4gI68sYc+XfGGEXgqN07qXMW7Gsc/spRI4OSPzyByLynvbtqVbA5I2ISrFn5KgK3h9wuf1xDbR5ltF37Uw9CFIuyWu6oYJser9TDHrCdKe6HV7xdQgE+U= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--abhishekbapat.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=rvKAGHwh; arc=none smtp.client-ip=74.125.82.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--abhishekbapat.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="rvKAGHwh" Received: by mail-dy1-f202.google.com with SMTP id 5a478bee46e88-2bdf75bc88fso7369476eec.0 for ; Mon, 04 May 2026 16:36:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20251104; t=1777937803; x=1778542603; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=G+hEq3xcQpeNbVKkmlLzQ0aZOXZlDNVaIlQ1vlmIpXk=; b=rvKAGHwhTCHml8tiPMiOijz/n18bUuNPP7SyhS0YbsJ1luwhM0naGLbqZ34nxnUdBF ymKiEEV58UPVtF7osW02RL0ceMQAFCZ3liHU7YCyrMtMlHcHa5AMH8vNGPyaAM9FsRql XupzcD9bYfGv1qEoL0U+kLh3JRodM4rto5k0nvWKdkzfNYYYK6WRdNH6AM9+nBzpJ6Ar E8bzli8/8NovAmOIZgnKdq+lhVUi35/TjINk04ASljNIgV5u+qycWlXrToRgphIPltKt wAR5dUs9tHTKa3DGcL2KtUHTKOwd4WcwMo3lQhuMuEnIFsCNBiqeYv/vr04vhTo0jWr6 U2ZA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1777937803; x=1778542603; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=G+hEq3xcQpeNbVKkmlLzQ0aZOXZlDNVaIlQ1vlmIpXk=; b=JYDu5ALtlRIGHzd/Oi0kzIG0oq/ZX+RWPS4zEP77rcO8FHLUROEwUPvhJO9LNNkbNP OGe17/VtQFZqjKxdGU215NBWYc0L1gJeMOuJuIuYheOO+gSCqPCA/8A5vhvD0i8Ld1fh KVg22qcdnAf5WHQxqAY2OrXai4J8C+2w4tAGIQmeXuRKcq8W2nzOEZRhuU2NBHdd4oL6 rrLaVF+c9x1x6SqjHJP3eCeLMnry1JFjn+T/2gxU7HJYRicaLoe/MHkDQFFFuyyMceZd r3M8rp9PGkw5Q+zXoob1/FyjvxVsxvYRdaL/TMdOGPsRCxQUzH3ttR1OHcDOmB9M+mod zz4w== X-Forwarded-Encrypted: i=1; AFNElJ8JoN56OekHMOl8jTz5F+dAJx2gmLTmbFEPlXwJ2IYPVzuWVcbqTl1CMYbVS6IlVceq2YWX2hwi0Anw2i8=@vger.kernel.org X-Gm-Message-State: AOJu0YzNSFKmJFzsDHD/mpeD7x1ECISXKxZTt6mEV0hh9DLH3zUo/SZg hXU/9EPie6rl0Ff/ZOdhY5WOa+aJweBFlnwG/8nGo36ohziAkK59URNsQtpeCaoT2q/iL4g3r7B 6wXi0qnEJs3lhhDjUk/ap8xYxB0a4OCw+VQ== X-Received: from dyclh13.prod.google.com ([2002:a05:7301:6d0d:b0:2f3:f2a4:6ea3]) (user=abhishekbapat job=prod-delivery.src-stubby-dispatcher) by 2002:a05:7300:cd8e:b0:2d2:96e8:1bf5 with SMTP id 5a478bee46e88-2efb7bdc5bamr5234886eec.3.1777937802855; Mon, 04 May 2026 16:36:42 -0700 (PDT) Date: Mon, 4 May 2026 23:36:24 +0000 In-Reply-To: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: X-Mailer: git-send-email 2.54.0.545.g6539524ca2-goog Message-ID: <26468cbbff1760513043fd3589f9c106dfbbf5bc.1777936301.git.abhishekbapat@google.com> Subject: [PATCH 6/6] kselftest: alloc_tag: extend the allocinfo ioctl kselftest From: Abhishek Bapat To: Suren Baghdasaryan , Andrew Morton , Kent Overstreet Cc: Shuah Khan , Jonathan Corbet , linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org, linux-mm@kvack.org, Sourav Panda , Abhishek Bapat Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add the following 2 scenarios to the allocinfo ioctl kselftest: 1. Validate size based filtering 2. Validate lineno based filtering The first test uses "do_init_module" as the candidate function for the test. This is because the associated site will only allocate memory when a kernel module is loaded. The return value of get_content_id() changes every time modules are loaded or unloaded. Hence, as long as get_content_id() values at the start and the end of the test are the same, the memory allocated by the do_init_module call site should also remain the same. Consequently, the test can assume consistency between the value returned by the ioctl and the procfs resulting in less flakiness. Signed-off-by: Abhishek Bapat --- .../alloc_tag/allocinfo_ioctl_test.c | 194 +++++++++++++++++- 1 file changed, 193 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/alloc_tag/allocinfo_ioctl_test.c b/too= ls/testing/selftests/alloc_tag/allocinfo_ioctl_test.c index 543023ca3d27..573d84a3619a 100644 --- a/tools/testing/selftests/alloc_tag/allocinfo_ioctl_test.c +++ b/tools/testing/selftests/alloc_tag/allocinfo_ioctl_test.c @@ -294,11 +294,191 @@ static int test_function_filter(void) return run_filter_test(&filter); } =20 +static int test_size_filter(void) +{ + int fd; + struct allocinfo_tag_data_vec *tags =3D malloc(sizeof(*tags)); + struct allocinfo_tag_data_vec *procfs_entries =3D malloc(sizeof(*procfs_e= ntries)); + struct allocinfo_filter filter; + int ret =3D KSFT_PASS; + __u64 target_size, i; + bool found =3D false; + const char *target_function =3D "do_init_module"; + + if (!tags || !procfs_entries) { + ksft_print_msg("Memory allocation failed.\n"); + ret =3D KSFT_FAIL; + goto freemem; + } + + fd =3D open(ALLOCINFO_PROC, O_RDONLY); + if (fd < 0) { + ksft_exit_skip("Failed to open " ALLOCINFO_PROC ": %s\n", strerror(errno= )); + ret =3D KSFT_FAIL; + goto freemem; + } + + memset(&filter, 0, sizeof(filter)); + filter.mask |=3D ALLOCINFO_FILTER_MASK_FUNCTION; + strncpy(filter.fields.function, target_function, ALLOCINFO_STR_SIZE); + + if (get_filtered_procfs_entries(procfs_entries, &filter, fd)) { + ksft_print_msg("Error retrieving entries from " ALLOCINFO_PROC "\n"); + ret =3D KSFT_FAIL; + goto exit; + } + + if (procfs_entries->count =3D=3D 0) { + ksft_print_msg("Function %s not found in procfs\n", target_function); + ret =3D KSFT_SKIP; + goto exit; + } + + /* + * We depend on the result of procfs entries to create the ioctl_filter. = Hence we + * cannot recycle the run_filter_test function here. + */ + target_size =3D procfs_entries->tag[0].counter.bytes; + + memset(&filter, 0, sizeof(filter)); + filter.mask |=3D ALLOCINFO_FILTER_MASK_MIN_SIZE | ALLOCINFO_FILTER_MASK_M= AX_SIZE; + filter.fields.min_size =3D target_size; + filter.fields.max_size =3D target_size; + + __u64 pos =3D 0; + enum ioctl_ret ioctl_status; + + /* + * This loop is required because the first 32 entries fetched by the IOCT= L based on + * the size parameter might not contain the exact entry that was used fro= m procfs. + * If that happens, we must update pos and fetch again until we find the = exact entry. + */ + while (1) { + ioctl_status =3D get_filtered_ioctl_entries(tags, &filter, fd, pos); + if (ioctl_status =3D=3D IOCTL_INVALID_DATA) { + ksft_print_msg("Trouble retrieving valid IOCTL entries, skipping.\n"); + ret =3D KSFT_SKIP; + goto exit; + } + if (ioctl_status =3D=3D IOCTL_FAILURE) { + ksft_print_msg("Error retrieving IOCTL entries.\n"); + ret =3D KSFT_FAIL; + goto exit; + } + + for (i =3D 0; i < tags->count; i++) { + if (strcmp(tags->tag[i].tag.function, target_function) =3D=3D 0) { + found =3D true; + break; + } + } + + if (found) + break; + + if (tags->count < VEC_MAX_ENTRIES) + break; + + pos +=3D tags->count; + } + + if (!found) { + ksft_print_msg("Entry with function %s not found in IOCTL results\n", + target_function); + ret =3D KSFT_FAIL; + } + +exit: + close(fd); +freemem: + free(tags); + free(procfs_entries); + return ret; +} + +static int test_lineno_filter(void) +{ + int fd; + struct allocinfo_tag_data_vec *tags =3D malloc(sizeof(*tags)); + struct allocinfo_tag_data_vec *procfs_entries =3D malloc(sizeof(*procfs_e= ntries)); + struct allocinfo_filter filter; + enum ioctl_ret ioctl_status; + int ret =3D KSFT_PASS; + __u64 target_lineno, i; + + if (!tags || !procfs_entries) { + ksft_print_msg("Memory allocation failed.\n"); + ret =3D KSFT_FAIL; + goto freemem; + } + + fd =3D open(ALLOCINFO_PROC, O_RDONLY); + if (fd < 0) { + ksft_exit_skip("Failed to open " ALLOCINFO_PROC ": %s\n", strerror(errno= )); + ret =3D KSFT_FAIL; + goto freemem; + } + + memset(&filter, 0, sizeof(filter)); + + if (get_filtered_procfs_entries(procfs_entries, &filter, fd)) { + ksft_print_msg("Error retrieving entries from " ALLOCINFO_PROC "\n"); + ret =3D KSFT_FAIL; + goto exit; + } + if (procfs_entries->count =3D=3D 0) { + ksft_print_msg("Could not retrieve procfs entries\n"); + ret =3D KSFT_SKIP; + goto exit; + } + /* + * We depend on the result of procfs entries to create the ioctl_filter. = Hence we + * cannot recycle the run_filter_test function here. + */ + target_lineno =3D procfs_entries->tag[0].tag.lineno; + + filter.mask |=3D ALLOCINFO_FILTER_MASK_LINENO; + filter.fields.lineno =3D target_lineno; + + ioctl_status =3D get_filtered_ioctl_entries(tags, &filter, fd, 0); + if (ioctl_status =3D=3D IOCTL_INVALID_DATA) { + ksft_print_msg("Trouble retrieving valid IOCTL entries, skipping.\n"); + ret =3D KSFT_SKIP; + goto exit; + } + if (ioctl_status =3D=3D IOCTL_FAILURE) { + ksft_print_msg("Error retrieving IOCTL entries.\n"); + ret =3D KSFT_FAIL; + goto exit; + } + + if (tags->count =3D=3D 0) { + ksft_print_msg("IOCTL returned 0 matches for target lineno %llu.\n", tar= get_lineno); + ret =3D KSFT_FAIL; + goto exit; + } + for (i =3D 0; i < tags->count; i++) { + if (tags->tag[i].tag.lineno !=3D target_lineno) { + ksft_print_msg("IOCTL entry %llu has incorrect lineno %llu.\n", + i, tags->tag[i].tag.lineno); + ret =3D KSFT_FAIL; + goto exit; + } + } + +exit: + close(fd); +freemem: + free(tags); + free(procfs_entries); + return ret; +} + int main(int argc, char *argv[]) { int ret; =20 - ksft_set_plan(2); + ksft_set_plan(4); =20 ret =3D test_filename_filter(); if (ret =3D=3D KSFT_SKIP) @@ -312,5 +492,17 @@ int main(int argc, char *argv[]) else ksft_test_result(ret =3D=3D KSFT_PASS, "test_function_filter\n"); =20 + ret =3D test_size_filter(); + if (ret =3D=3D KSFT_SKIP) + ksft_test_result_skip("Skipping test_size_filter\n"); + else + ksft_test_result(ret =3D=3D KSFT_PASS, "test_size_filter\n"); + + ret =3D test_lineno_filter(); + if (ret =3D=3D KSFT_SKIP) + ksft_test_result_skip("Skipping test_lineno_filter\n"); + else + ksft_test_result(ret =3D=3D KSFT_PASS, "test_lineno_filter\n"); + ksft_finished(); } --=20 2.54.0.545.g6539524ca2-goog