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; }; struct allocinfo_counter { @@ -39,13 +41,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) 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_file *m, void __user *arg) static bool matches_filter(struct codetag *ct, struct allocinfo_filter *filter) { + struct alloc_tag *tag; + struct alloc_tag_counters counters; + if (!ct || !filter || !filter->mask) return true; @@ -214,6 +217,18 @@ 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) || + (filter->mask & ALLOCINFO_FILTER_MASK_MAX_SIZE)) { + tag = ct_to_alloc_tag(ct); + counters = 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; } -- 2.54.0.545.g6539524ca2-goog