diff --git a/include/linux/mm.h b/include/linux/mm.h index 39e75cf1dec6..183f816bcde2 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1646,27 +1646,27 @@ static inline unsigned long get_mm_counter(struct mm_struct *mm, int member) return (unsigned long)val; } -void mm_trace_rss_stat(int member, long count); +void mm_trace_rss_stat(struct mm_struct *mm, int member, long count); static inline void add_mm_counter(struct mm_struct *mm, int member, long value) { long count = atomic_long_add_return(value, &mm->rss_stat.count[member]); - mm_trace_rss_stat(member, count); + mm_trace_rss_stat(mm, member, count); } static inline void inc_mm_counter(struct mm_struct *mm, int member) { long count = atomic_long_inc_return(&mm->rss_stat.count[member]); - mm_trace_rss_stat(member, count); + mm_trace_rss_stat(mm, member, count); } static inline void dec_mm_counter(struct mm_struct *mm, int member) { long count = atomic_long_dec_return(&mm->rss_stat.count[member]); - mm_trace_rss_stat(member, count); + mm_trace_rss_stat(mm, member, count); } /* Optimized variant when page is already known not to be PageAnon */ diff --git a/include/linux/string.h b/include/linux/string.h index f58e1ef76572..3c32b2f6670a 100644 --- a/include/linux/string.h +++ b/include/linux/string.h @@ -205,6 +205,8 @@ int bprintf(u32 *bin_buf, size_t size, const char *fmt, ...) __printf(3, 4); extern ssize_t memory_read_from_buffer(void *to, size_t count, loff_t *ppos, const void *from, size_t available); +int ptr_to_hashval(const void *ptr, unsigned long *hashval_out); + /** * strstarts - does @str start with @prefix? * @str: string to examine diff --git a/include/trace/events/kmem.h b/include/trace/events/kmem.h index 8b88e04fafbf..ec8f586f10c1 100644 --- a/include/trace/events/kmem.h +++ b/include/trace/events/kmem.h @@ -315,24 +315,50 @@ TRACE_EVENT(mm_page_alloc_extfrag, __entry->change_ownership) ); +/* + * Required for uniquely and securely identifying mm in rss_stat tracepoint. + */ +#ifndef __PTR_TO_HASHVAL +static unsigned int __maybe_unused mm_ptr_to_hash(const void *ptr) +{ + int ret; + unsigned long hashval; + + ret = ptr_to_hashval(ptr, &hashval); + if (ret) + return 0; + + /* The hashed value is only 32-bit */ + return (unsigned int)hashval; +} +#define __PTR_TO_HASHVAL +#endif + TRACE_EVENT(rss_stat, - TP_PROTO(int member, + TP_PROTO(struct mm_struct *mm, + int member, long count), - TP_ARGS(member, count), + TP_ARGS(mm, member, count), TP_STRUCT__entry( + __field(unsigned int, mm_id) + __field(unsigned int, curr) __field(int, member) __field(long, size) ), TP_fast_assign( + __entry->mm_id = mm_ptr_to_hash(mm); + __entry->curr = !!(current->mm == mm); __entry->member = member; __entry->size = (count << PAGE_SHIFT); ), - TP_printk("member=%d size=%ldB", + TP_printk("mm_id=%u curr=%d member=%d size=%ldB", + __entry->mm_id, + __entry->curr, __entry->member, __entry->size) ); diff --git a/lib/vsprintf.c b/lib/vsprintf.c index 812e59e13fe6..b71f713a7665 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -1708,23 +1708,12 @@ static int __init initialize_ptr_random(void) } early_initcall(initialize_ptr_random); -/* Maps a pointer to a 32 bit unique identifier. */ -static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec) +int ptr_to_hashval(const void *ptr, unsigned long *hashval_out) { - const char *str = sizeof(ptr) == 8 ? "(____ptrval____)" : "(ptrval)"; unsigned long hashval; - /* When debugging early boot use non-cryptographically secure hash. */ - if (unlikely(debug_boot_weak_hash)) { - hashval = hash_long((unsigned long)ptr, 32); - return pointer_string(buf, end, (const void *)hashval, spec); - } - - if (static_branch_unlikely(¬_filled_random_ptr_key)) { - spec.field_width = 2 * sizeof(ptr); - /* string length must be less than default_width */ - return string(buf, end, str, spec); - } + if (static_branch_unlikely(¬_filled_random_ptr_key)) + return -EAGAIN; #ifdef CONFIG_64BIT hashval = (unsigned long)siphash_1u64((u64)ptr, &ptr_key); @@ -1736,6 +1725,30 @@ static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec) #else hashval = (unsigned long)siphash_1u32((u32)ptr, &ptr_key); #endif + *hashval_out = hashval; + return 0; +} + +/* Maps a pointer to a 32 bit unique identifier. */ +static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec) +{ + const char *str = sizeof(ptr) == 8 ? "(____ptrval____)" : "(ptrval)"; + unsigned long hashval; + int ret; + + /* When debugging early boot use non-cryptographically secure hash. */ + if (unlikely(debug_boot_weak_hash)) { + hashval = hash_long((unsigned long)ptr, 32); + return pointer_string(buf, end, (const void *)hashval, spec); + } + + ret = ptr_to_hashval(ptr, &hashval); + if (ret) { + spec.field_width = 2 * sizeof(ptr); + /* string length must be less than default_width */ + return string(buf, end, str, spec); + } + return pointer_string(buf, end, (const void *)hashval, spec); } diff --git a/mm/memory.c b/mm/memory.c index 6491d7a31112..059ea3abf8a8 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -140,9 +140,9 @@ static int __init init_zero_pfn(void) } core_initcall(init_zero_pfn); -void mm_trace_rss_stat(int member, long count) +void mm_trace_rss_stat(struct mm_struct *mm, int member, long count) { - trace_rss_stat(member, count); + trace_rss_stat(mm, member, count); } #if defined(SPLIT_RSS_COUNTING)