Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

ref_tracker: have callers pass output function to pr_ostream()

In a later patch, we'll be adding a 3rd mechanism for outputting
ref_tracker info via seq_file. Instead of a conditional, have the caller
set a pointer to an output function in struct ostream. As part of this,
the log prefix must be explicitly passed in, as it's too late for the
pr_fmt macro.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Link: https://patch.msgid.link/20250618-reftrack-dbgfs-v15-3-24fc37ead144@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Jeff Layton and committed by
Jakub Kicinski
49c94af0 e209f919

+39 -15
+2
include/linux/ref_tracker.h
··· 6 6 #include <linux/spinlock.h> 7 7 #include <linux/stackdepot.h> 8 8 9 + #define __ostream_printf __printf(2, 3) 10 + 9 11 struct ref_tracker; 10 12 11 13 struct ref_tracker_dir {
+37 -15
lib/ref_tracker.c
··· 63 63 } 64 64 65 65 struct ostream { 66 + void __ostream_printf (*func)(struct ostream *stream, char *fmt, ...); 67 + char *prefix; 66 68 char *buf; 67 69 int size, used; 68 70 }; 71 + 72 + static void __ostream_printf pr_ostream_log(struct ostream *stream, char *fmt, ...) 73 + { 74 + va_list args; 75 + 76 + va_start(args, fmt); 77 + vprintk(fmt, args); 78 + va_end(args); 79 + } 80 + 81 + static void __ostream_printf pr_ostream_buf(struct ostream *stream, char *fmt, ...) 82 + { 83 + int ret, len = stream->size - stream->used; 84 + va_list args; 85 + 86 + va_start(args, fmt); 87 + ret = vsnprintf(stream->buf + stream->used, len, fmt, args); 88 + va_end(args); 89 + if (ret > 0) 90 + stream->used += min(ret, len); 91 + } 69 92 70 93 #define pr_ostream(stream, fmt, args...) \ 71 94 ({ \ 72 95 struct ostream *_s = (stream); \ 73 96 \ 74 - if (!_s->buf) { \ 75 - pr_err(fmt, ##args); \ 76 - } else { \ 77 - int ret, len = _s->size - _s->used; \ 78 - ret = snprintf(_s->buf + _s->used, len, pr_fmt(fmt), ##args); \ 79 - _s->used += min(ret, len); \ 80 - } \ 97 + _s->func(_s, fmt, ##args); \ 81 98 }) 82 99 83 100 static void ··· 113 96 114 97 stats = ref_tracker_get_stats(dir, display_limit); 115 98 if (IS_ERR(stats)) { 116 - pr_ostream(s, "%s@%p: couldn't get stats, error %pe\n", 117 - dir->name, dir, stats); 99 + pr_ostream(s, "%s%s@%p: couldn't get stats, error %pe\n", 100 + s->prefix, dir->name, dir, stats); 118 101 return; 119 102 } 120 103 ··· 124 107 stack = stats->stacks[i].stack_handle; 125 108 if (sbuf && !stack_depot_snprint(stack, sbuf, STACK_BUF_SIZE, 4)) 126 109 sbuf[0] = 0; 127 - pr_ostream(s, "%s@%p has %d/%d users at\n%s\n", dir->name, dir, 128 - stats->stacks[i].count, stats->total, sbuf); 110 + pr_ostream(s, "%s%s@%p has %d/%d users at\n%s\n", s->prefix, 111 + dir->name, dir, stats->stacks[i].count, 112 + stats->total, sbuf); 129 113 skipped -= stats->stacks[i].count; 130 114 } 131 115 132 116 if (skipped) 133 - pr_ostream(s, "%s@%p skipped reports about %d/%d users.\n", 134 - dir->name, dir, skipped, stats->total); 117 + pr_ostream(s, "%s%s@%p skipped reports about %d/%d users.\n", 118 + s->prefix, dir->name, dir, skipped, stats->total); 135 119 136 120 kfree(sbuf); 137 121 ··· 142 124 void ref_tracker_dir_print_locked(struct ref_tracker_dir *dir, 143 125 unsigned int display_limit) 144 126 { 145 - struct ostream os = {}; 127 + struct ostream os = { .func = pr_ostream_log, 128 + .prefix = "ref_tracker: " }; 146 129 147 130 __ref_tracker_dir_pr_ostream(dir, display_limit, &os); 148 131 } ··· 162 143 163 144 int ref_tracker_dir_snprint(struct ref_tracker_dir *dir, char *buf, size_t size) 164 145 { 165 - struct ostream os = { .buf = buf, .size = size }; 146 + struct ostream os = { .func = pr_ostream_buf, 147 + .prefix = "ref_tracker: ", 148 + .buf = buf, 149 + .size = size }; 166 150 unsigned long flags; 167 151 168 152 spin_lock_irqsave(&dir->lock, flags);