From: Abhishek Bapat <abhishekbapat@google.com>
To: Suren Baghdasaryan <surenb@google.com>,
Andrew Morton <akpm@linux-foundation.org>,
Kent Overstreet <kent.overstreet@linux.dev>,
Hao Ge <hao.ge@linux.dev>
Cc: Shuah Khan <skhan@linuxfoundation.org>,
Jonathan Corbet <corbet@lwn.net>,
linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-mm@kvack.org, Sourav Panda <souravpanda@google.com>,
Abhishek Bapat <abhishekbapat@google.com>
Subject: [PATCH v4 3/6] alloc_tag: add size-based filtering to ioctl
Date: Wed, 10 Jun 2026 00:12:56 +0000 [thread overview]
Message-ID: <4e2a75c69fe350358e1fef3e4e25435f6a3d4e77.1781042698.git.abhishekbapat@google.com> (raw)
In-Reply-To: <cover.1781042698.git.abhishekbapat@google.com>
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 <abhishekbapat@google.com>
---
include/uapi/linux/alloc_tag.h | 8 ++++-
lib/alloc_tag.c | 63 ++++++++++++++++++++++++++++------
2 files changed, 59 insertions(+), 12 deletions(-)
diff --git a/include/uapi/linux/alloc_tag.h b/include/uapi/linux/alloc_tag.h
index 3b11877955b9..7f5acbb44c14 100644
--- a/include/uapi/linux/alloc_tag.h
+++ b/include/uapi/linux/alloc_tag.h
@@ -45,13 +45,17 @@ enum {
ALLOCINFO_FILTER_FUNCTION,
ALLOCINFO_FILTER_FILENAME,
ALLOCINFO_FILTER_LINENO,
- __ALLOCINFO_FILTER_LAST = ALLOCINFO_FILTER_LINENO
+ ALLOCINFO_FILTER_MIN_SIZE,
+ ALLOCINFO_FILTER_MAX_SIZE,
+ __ALLOCINFO_FILTER_LAST = ALLOCINFO_FILTER_MAX_SIZE
};
#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)
#define ALLOCINFO_FILTER_MASKS \
((1 << (__ALLOCINFO_FILTER_LAST + 1)) - 1)
@@ -59,6 +63,8 @@ enum {
struct allocinfo_filter {
__u64 mask; /* bitmask of the filter fields used */
struct allocinfo_tag fields;
+ __u64 min_size;
+ __u64 max_size;
};
struct allocinfo_get_at {
diff --git a/lib/alloc_tag.c b/lib/alloc_tag.c
index 378fcd63b6c9..a936cf18611a 100644
--- a/lib/alloc_tag.c
+++ b/lib/alloc_tag.c
@@ -191,15 +191,26 @@ static int allocinfo_cmp_str(const char *str, const char *template)
return strncmp(allocinfo_str(str), template, ALLOCINFO_STR_SIZE);
}
+/* Fetch the per-CPU counters */
+static inline struct alloc_tag_counters allocinfo_prefetch_counters(struct codetag *ct)
+{
+ return alloc_tag_read(ct_to_alloc_tag(ct));
+}
+
/*
* Populates the UAPI allocinfo_tag_data structure with active runtime
* profiling counters extracted from the given kernel codetag.
*/
static void allocinfo_to_params(struct codetag *ct,
- struct allocinfo_tag_data *data)
+ struct allocinfo_tag_data *data,
+ struct alloc_tag_counters *counters)
{
- struct alloc_tag *tag = ct_to_alloc_tag(ct);
- struct alloc_tag_counters counter = alloc_tag_read(tag);
+ struct alloc_tag_counters local_counters;
+
+ if (!counters) {
+ local_counters = allocinfo_prefetch_counters(ct);
+ counters = &local_counters;
+ }
if (ct->modname)
allocinfo_copy_str(data->tag.modname, ct->modname);
@@ -208,9 +219,9 @@ static void allocinfo_to_params(struct codetag *ct,
allocinfo_copy_str(data->tag.function, ct->function);
allocinfo_copy_str(data->tag.filename, ct->filename);
data->tag.lineno = ct->lineno;
- data->counter.bytes = counter.bytes;
- data->counter.calls = counter.calls;
- data->counter.accurate = !alloc_tag_is_inaccurate(tag);
+ data->counter.bytes = counters->bytes;
+ data->counter.calls = counters->calls;
+ data->counter.accurate = !alloc_tag_is_inaccurate(ct_to_alloc_tag(ct));
}
/*
@@ -234,7 +245,9 @@ static int allocinfo_ioctl_get_content_id(struct seq_file *m, void __user *arg)
* Verifies whether a given codetag satisfies the active filtering criteria by
* matching its characteristics against the specified filter.
*/
-static bool matches_filter(struct codetag *ct, struct allocinfo_filter *filter)
+static bool matches_filter(struct codetag *ct, struct allocinfo_filter *filter,
+ struct alloc_tag_counters *counters,
+ bool *fetched_counters)
{
if (!filter || !filter->mask)
return true;
@@ -261,6 +274,19 @@ static bool matches_filter(struct codetag *ct, struct allocinfo_filter *filter)
ct->lineno != filter->fields.lineno)
return false;
+ if (filter->mask & (ALLOCINFO_FILTER_MASK_MIN_SIZE | ALLOCINFO_FILTER_MASK_MAX_SIZE)) {
+ if (!*fetched_counters) {
+ *counters = allocinfo_prefetch_counters(ct);
+ *fetched_counters = true;
+ }
+ if ((filter->mask & ALLOCINFO_FILTER_MASK_MIN_SIZE) &&
+ counters->bytes < filter->min_size)
+ return false;
+ if ((filter->mask & ALLOCINFO_FILTER_MASK_MAX_SIZE) &&
+ counters->bytes > filter->max_size)
+ return false;
+ }
+
return true;
}
@@ -274,6 +300,8 @@ static int allocinfo_ioctl_get_at(struct seq_file *m, void __user *arg)
struct codetag *ct;
struct allocinfo_get_at params = {0};
__u64 skip_count;
+ struct alloc_tag_counters counters;
+ bool fetched_counters;
if (copy_from_user(¶ms, arg, sizeof(params)))
return -EFAULT;
@@ -281,6 +309,11 @@ static int allocinfo_ioctl_get_at(struct seq_file *m, void __user *arg)
if (params.filter.mask & ~ALLOCINFO_FILTER_MASKS)
return -EINVAL;
+ if ((params.filter.mask & ALLOCINFO_FILTER_MASK_MIN_SIZE) &&
+ (params.filter.mask & ALLOCINFO_FILTER_MASK_MAX_SIZE) &&
+ params.filter.min_size > params.filter.max_size)
+ return -EINVAL;
+
priv = m->private;
mutex_lock(&priv->ioctl_lock);
@@ -304,7 +337,8 @@ static int allocinfo_ioctl_get_at(struct seq_file *m, void __user *arg)
ct = codetag_next_ct(&priv->ioctl_iter);
while (ct) {
- if (matches_filter(ct, &priv->filter)) {
+ fetched_counters = false;
+ if (matches_filter(ct, &priv->filter, &counters, &fetched_counters)) {
if (skip_count == 0)
break;
skip_count--;
@@ -313,7 +347,7 @@ static int allocinfo_ioctl_get_at(struct seq_file *m, void __user *arg)
}
if (ct) {
- allocinfo_to_params(ct, ¶ms.data);
+ allocinfo_to_params(ct, ¶ms.data, fetched_counters ? &counters : NULL);
priv->positioned = true;
}
@@ -339,6 +373,8 @@ static int allocinfo_ioctl_get_next(struct seq_file *m, void __user *arg)
struct codetag *ct;
struct allocinfo_tag_data params;
int ret = 0;
+ struct alloc_tag_counters counters;
+ bool fetched_counters;
memset(¶ms, 0, sizeof(params));
priv = m->private;
@@ -352,10 +388,15 @@ static int allocinfo_ioctl_get_next(struct seq_file *m, void __user *arg)
}
ct = codetag_next_ct(&priv->ioctl_iter);
- while (ct && !matches_filter(ct, &priv->filter))
+ while (ct) {
+ fetched_counters = false;
+ if (matches_filter(ct, &priv->filter, &counters, &fetched_counters))
+ break;
ct = codetag_next_ct(&priv->ioctl_iter);
+ }
+
if (ct)
- allocinfo_to_params(ct, ¶ms);
+ allocinfo_to_params(ct, ¶ms, fetched_counters ? &counters : NULL);
if (!ct) {
priv->positioned = false;
--
2.54.0.1099.g489fc7bff1-goog
next prev parent reply other threads:[~2026-06-10 0:13 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-10 0:12 [PATCH v4 0/6] alloc_tag: introduce IOCTL-based filtering for MAP Abhishek Bapat
2026-06-10 0:12 ` [PATCH v4 1/6] alloc_tag: add ioctl to /proc/allocinfo Abhishek Bapat
2026-06-10 1:28 ` Hao Ge
2026-06-10 11:23 ` Usama Arif
2026-06-10 0:12 ` [PATCH v4 2/6] alloc_tag: add ioctl filters " Abhishek Bapat
2026-06-10 1:45 ` Hao Ge
2026-06-10 0:12 ` Abhishek Bapat [this message]
2026-06-10 1:49 ` [PATCH v4 3/6] alloc_tag: add size-based filtering to ioctl Hao Ge
2026-06-10 0:12 ` [PATCH v4 4/6] alloc_tag: add accuracy based " Abhishek Bapat
2026-06-10 1:52 ` Hao Ge
2026-06-10 0:12 ` [PATCH v4 5/6] kselftest: alloc_tag: add kselftest for ioctl interface Abhishek Bapat
2026-06-10 3:17 ` Hao Ge
2026-06-10 0:12 ` [PATCH v4 6/6] kselftest: alloc_tag: extend the allocinfo ioctl kselftest Abhishek Bapat
2026-06-10 9:33 ` Hao Ge
2026-06-12 0:23 ` Abhishek Bapat
2026-06-10 19:42 ` kernel test robot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4e2a75c69fe350358e1fef3e4e25435f6a3d4e77.1781042698.git.abhishekbapat@google.com \
--to=abhishekbapat@google.com \
--cc=akpm@linux-foundation.org \
--cc=corbet@lwn.net \
--cc=hao.ge@linux.dev \
--cc=kent.overstreet@linux.dev \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=skhan@linuxfoundation.org \
--cc=souravpanda@google.com \
--cc=surenb@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®