xref: /linux-6.15/kernel/trace/trace_seq.c (revision dba39448)
1 /*
2  * trace_seq.c
3  *
4  * Copyright (C) 2008-2014 Red Hat Inc, Steven Rostedt <[email protected]>
5  *
6  * The trace_seq is a handy tool that allows you to pass a descriptor around
7  * to a buffer that other functions can write to. It is similar to the
8  * seq_file functionality but has some differences.
9  *
10  * To use it, the trace_seq must be initialized with trace_seq_init().
11  * This will set up the counters within the descriptor. You can call
12  * trace_seq_init() more than once to reset the trace_seq to start
13  * from scratch.
14  *
15  * The buffer size is currently PAGE_SIZE, although it may become dynamic
16  * in the future.
17  *
18  * A write to the buffer will either succed or fail. That is, unlike
19  * sprintf() there will not be a partial write (well it may write into
20  * the buffer but it wont update the pointers). This allows users to
21  * try to write something into the trace_seq buffer and if it fails
22  * they can flush it and try again.
23  *
24  */
25 #include <linux/uaccess.h>
26 #include <linux/seq_file.h>
27 #include <linux/trace_seq.h>
28 
29 /* How much buffer is left on the trace_seq? */
30 #define TRACE_SEQ_BUF_LEFT(s) ((PAGE_SIZE - 1) - (s)->len)
31 
32 /* How much buffer is written? */
33 #define TRACE_SEQ_BUF_USED(s) min((s)->len, (unsigned int)(PAGE_SIZE - 1))
34 
35 /**
36  * trace_print_seq - move the contents of trace_seq into a seq_file
37  * @m: the seq_file descriptor that is the destination
38  * @s: the trace_seq descriptor that is the source.
39  *
40  * Returns 0 on success and non zero on error. If it succeeds to
41  * write to the seq_file it will reset the trace_seq, otherwise
42  * it does not modify the trace_seq to let the caller try again.
43  */
44 int trace_print_seq(struct seq_file *m, struct trace_seq *s)
45 {
46 	unsigned int len = TRACE_SEQ_BUF_USED(s);
47 	int ret;
48 
49 	ret = seq_write(m, s->buffer, len);
50 
51 	/*
52 	 * Only reset this buffer if we successfully wrote to the
53 	 * seq_file buffer. This lets the caller try again or
54 	 * do something else with the contents.
55 	 */
56 	if (!ret)
57 		trace_seq_init(s);
58 
59 	return ret;
60 }
61 
62 /**
63  * trace_seq_printf - sequence printing of trace information
64  * @s: trace sequence descriptor
65  * @fmt: printf format string
66  *
67  * The tracer may use either sequence operations or its own
68  * copy to user routines. To simplify formating of a trace
69  * trace_seq_printf() is used to store strings into a special
70  * buffer (@s). Then the output may be either used by
71  * the sequencer or pulled into another buffer.
72  */
73 void trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
74 {
75 	unsigned int len = TRACE_SEQ_BUF_LEFT(s);
76 	va_list ap;
77 	int ret;
78 
79 	if (s->full || !len)
80 		return;
81 
82 	va_start(ap, fmt);
83 	ret = vsnprintf(s->buffer + s->len, len, fmt, ap);
84 	va_end(ap);
85 
86 	/* If we can't write it all, don't bother writing anything */
87 	if (ret >= len) {
88 		s->full = 1;
89 		return;
90 	}
91 
92 	s->len += ret;
93 }
94 EXPORT_SYMBOL_GPL(trace_seq_printf);
95 
96 /**
97  * trace_seq_bitmask - write a bitmask array in its ASCII representation
98  * @s:		trace sequence descriptor
99  * @maskp:	points to an array of unsigned longs that represent a bitmask
100  * @nmaskbits:	The number of bits that are valid in @maskp
101  *
102  * Writes a ASCII representation of a bitmask string into @s.
103  */
104 void trace_seq_bitmask(struct trace_seq *s, const unsigned long *maskp,
105 		      int nmaskbits)
106 {
107 	unsigned int len = TRACE_SEQ_BUF_LEFT(s);
108 	int ret;
109 
110 	if (s->full || !len)
111 		return;
112 
113 	ret = bitmap_scnprintf(s->buffer + s->len, len, maskp, nmaskbits);
114 	s->len += ret;
115 }
116 EXPORT_SYMBOL_GPL(trace_seq_bitmask);
117 
118 /**
119  * trace_seq_vprintf - sequence printing of trace information
120  * @s: trace sequence descriptor
121  * @fmt: printf format string
122  *
123  * The tracer may use either sequence operations or its own
124  * copy to user routines. To simplify formating of a trace
125  * trace_seq_printf is used to store strings into a special
126  * buffer (@s). Then the output may be either used by
127  * the sequencer or pulled into another buffer.
128  */
129 void trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
130 {
131 	unsigned int len = TRACE_SEQ_BUF_LEFT(s);
132 	int ret;
133 
134 	if (s->full || !len)
135 		return;
136 
137 	ret = vsnprintf(s->buffer + s->len, len, fmt, args);
138 
139 	/* If we can't write it all, don't bother writing anything */
140 	if (ret >= len) {
141 		s->full = 1;
142 		return;
143 	}
144 
145 	s->len += ret;
146 }
147 EXPORT_SYMBOL_GPL(trace_seq_vprintf);
148 
149 /**
150  * trace_seq_bprintf - Write the printf string from binary arguments
151  * @s: trace sequence descriptor
152  * @fmt: The format string for the @binary arguments
153  * @binary: The binary arguments for @fmt.
154  *
155  * When recording in a fast path, a printf may be recorded with just
156  * saving the format and the arguments as they were passed to the
157  * function, instead of wasting cycles converting the arguments into
158  * ASCII characters. Instead, the arguments are saved in a 32 bit
159  * word array that is defined by the format string constraints.
160  *
161  * This function will take the format and the binary array and finish
162  * the conversion into the ASCII string within the buffer.
163  */
164 void trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary)
165 {
166 	unsigned int len = TRACE_SEQ_BUF_LEFT(s);
167 	int ret;
168 
169 	if (s->full || !len)
170 		return;
171 
172 	ret = bstr_printf(s->buffer + s->len, len, fmt, binary);
173 
174 	/* If we can't write it all, don't bother writing anything */
175 	if (ret >= len) {
176 		s->full = 1;
177 		return;
178 	}
179 
180 	s->len += ret;
181 }
182 EXPORT_SYMBOL_GPL(trace_seq_bprintf);
183 
184 /**
185  * trace_seq_puts - trace sequence printing of simple string
186  * @s: trace sequence descriptor
187  * @str: simple string to record
188  *
189  * The tracer may use either the sequence operations or its own
190  * copy to user routines. This function records a simple string
191  * into a special buffer (@s) for later retrieval by a sequencer
192  * or other mechanism.
193  */
194 void trace_seq_puts(struct trace_seq *s, const char *str)
195 {
196 	unsigned int len = strlen(str);
197 
198 	if (s->full)
199 		return;
200 
201 	if (len > TRACE_SEQ_BUF_LEFT(s)) {
202 		s->full = 1;
203 		return;
204 	}
205 
206 	memcpy(s->buffer + s->len, str, len);
207 	s->len += len;
208 }
209 EXPORT_SYMBOL_GPL(trace_seq_puts);
210 
211 /**
212  * trace_seq_putc - trace sequence printing of simple character
213  * @s: trace sequence descriptor
214  * @c: simple character to record
215  *
216  * The tracer may use either the sequence operations or its own
217  * copy to user routines. This function records a simple charater
218  * into a special buffer (@s) for later retrieval by a sequencer
219  * or other mechanism.
220  */
221 void trace_seq_putc(struct trace_seq *s, unsigned char c)
222 {
223 	if (s->full)
224 		return;
225 
226 	if (TRACE_SEQ_BUF_LEFT(s) < 1) {
227 		s->full = 1;
228 		return;
229 	}
230 
231 	s->buffer[s->len++] = c;
232 }
233 EXPORT_SYMBOL_GPL(trace_seq_putc);
234 
235 /**
236  * trace_seq_putmem - write raw data into the trace_seq buffer
237  * @s: trace sequence descriptor
238  * @mem: The raw memory to copy into the buffer
239  * @len: The length of the raw memory to copy (in bytes)
240  *
241  * There may be cases where raw memory needs to be written into the
242  * buffer and a strcpy() would not work. Using this function allows
243  * for such cases.
244  */
245 void trace_seq_putmem(struct trace_seq *s, const void *mem, unsigned int len)
246 {
247 	if (s->full)
248 		return;
249 
250 	if (len > TRACE_SEQ_BUF_LEFT(s)) {
251 		s->full = 1;
252 		return;
253 	}
254 
255 	memcpy(s->buffer + s->len, mem, len);
256 	s->len += len;
257 }
258 EXPORT_SYMBOL_GPL(trace_seq_putmem);
259 
260 #define MAX_MEMHEX_BYTES	8U
261 #define HEX_CHARS		(MAX_MEMHEX_BYTES*2 + 1)
262 
263 /**
264  * trace_seq_putmem_hex - write raw memory into the buffer in ASCII hex
265  * @s: trace sequence descriptor
266  * @mem: The raw memory to write its hex ASCII representation of
267  * @len: The length of the raw memory to copy (in bytes)
268  *
269  * This is similar to trace_seq_putmem() except instead of just copying the
270  * raw memory into the buffer it writes its ASCII representation of it
271  * in hex characters.
272  */
273 void trace_seq_putmem_hex(struct trace_seq *s, const void *mem,
274 			 unsigned int len)
275 {
276 	unsigned char hex[HEX_CHARS];
277 	const unsigned char *data = mem;
278 	unsigned int start_len;
279 	int i, j;
280 
281 	if (s->full)
282 		return;
283 
284 	while (len) {
285 		start_len = min(len, HEX_CHARS - 1);
286 #ifdef __BIG_ENDIAN
287 		for (i = 0, j = 0; i < start_len; i++) {
288 #else
289 		for (i = start_len-1, j = 0; i >= 0; i--) {
290 #endif
291 			hex[j++] = hex_asc_hi(data[i]);
292 			hex[j++] = hex_asc_lo(data[i]);
293 		}
294 		if (WARN_ON_ONCE(j == 0 || j/2 > len))
295 			break;
296 
297 		/* j increments twice per loop */
298 		len -= j / 2;
299 		hex[j++] = ' ';
300 
301 		trace_seq_putmem(s, hex, j);
302 	}
303 }
304 EXPORT_SYMBOL_GPL(trace_seq_putmem_hex);
305 
306 /**
307  * trace_seq_path - copy a path into the sequence buffer
308  * @s: trace sequence descriptor
309  * @path: path to write into the sequence buffer.
310  *
311  * Write a path name into the sequence buffer.
312  *
313  * Returns 1 if we successfully written all the contents to
314  *   the buffer.
315  * Returns 0 if we the length to write is bigger than the
316  *   reserved buffer space. In this case, nothing gets written.
317  */
318 int trace_seq_path(struct trace_seq *s, const struct path *path)
319 {
320 	unsigned char *p;
321 
322 	if (s->full)
323 		return 0;
324 
325 	if (TRACE_SEQ_BUF_LEFT(s) < 1) {
326 		s->full = 1;
327 		return 0;
328 	}
329 
330 	p = d_path(path, s->buffer + s->len, PAGE_SIZE - s->len);
331 	if (!IS_ERR(p)) {
332 		p = mangle_path(s->buffer + s->len, p, "\n");
333 		if (p) {
334 			s->len = p - s->buffer;
335 			return 1;
336 		}
337 	} else {
338 		s->buffer[s->len++] = '?';
339 		return 1;
340 	}
341 
342 	s->full = 1;
343 	return 0;
344 }
345 EXPORT_SYMBOL_GPL(trace_seq_path);
346 
347 /**
348  * trace_seq_to_user - copy the squence buffer to user space
349  * @s: trace sequence descriptor
350  * @ubuf: The userspace memory location to copy to
351  * @cnt: The amount to copy
352  *
353  * Copies the sequence buffer into the userspace memory pointed to
354  * by @ubuf. It starts from the last read position (@s->readpos)
355  * and writes up to @cnt characters or till it reaches the end of
356  * the content in the buffer (@s->len), which ever comes first.
357  *
358  * On success, it returns a positive number of the number of bytes
359  * it copied.
360  *
361  * On failure it returns -EBUSY if all of the content in the
362  * sequence has been already read, which includes nothing in the
363  * sequenc (@s->len == @s->readpos).
364  *
365  * Returns -EFAULT if the copy to userspace fails.
366  */
367 int trace_seq_to_user(struct trace_seq *s, char __user *ubuf, int cnt)
368 {
369 	int len;
370 	int ret;
371 
372 	if (!cnt)
373 		return 0;
374 
375 	if (s->len <= s->readpos)
376 		return -EBUSY;
377 
378 	len = s->len - s->readpos;
379 	if (cnt > len)
380 		cnt = len;
381 	ret = copy_to_user(ubuf, s->buffer + s->readpos, cnt);
382 	if (ret == cnt)
383 		return -EFAULT;
384 
385 	cnt -= ret;
386 
387 	s->readpos += cnt;
388 	return cnt;
389 }
390 EXPORT_SYMBOL_GPL(trace_seq_to_user);
391