diff --git a/include/linux/mm.h b/include/linux/mm.h index 8b3660e82890..aed84145c1b1 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -1628,27 +1628,28 @@ static inline unsigned long get_mm_counter(struct mm_struct *mm, int member) return (unsigned long)val; } -void mm_trace_rss_stat(struct mm_struct *mm, int member, long count); +void mm_trace_rss_stat(struct mm_struct *mm, int member, long count, + long value); 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(mm, member, count); + mm_trace_rss_stat(mm, member, count, value); } 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(mm, member, count); + mm_trace_rss_stat(mm, member, count, 1); } 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(mm, member, count); + mm_trace_rss_stat(mm, member, count, -1); } /* Optimized variant when page is already known not to be PageAnon */ diff --git a/mm/memory.c b/mm/memory.c index ece007d30a00..542f0d8af661 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -154,9 +154,21 @@ static int __init init_zero_pfn(void) } core_initcall(init_zero_pfn); -void mm_trace_rss_stat(struct mm_struct *mm, int member, long count) +/* + * Only trace rss_stat when there is a 512kb cross over. + * Smaller changes may be lost unless every small change is + * crossing into or returning to a 512kb boundary. + */ +#define TRACE_MM_COUNTER_THRESHOLD 128 + +void mm_trace_rss_stat(struct mm_struct *mm, int member, long count, + long value) { - trace_rss_stat(mm, member, count); + long thresh_mask = ~(TRACE_MM_COUNTER_THRESHOLD - 1); + + /* Threshold roll-over, trace it */ + if ((count & thresh_mask) != ((count - value) & thresh_mask)) + trace_rss_stat(mm, member, count); } EXPORT_SYMBOL_GPL(mm_trace_rss_stat);