xref: /linux-6.15/kernel/trace/trace_seq.c (revision 6d2289f3)
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  * Returns 1 if we successfully written all the contents to
74  *   the buffer.
75   * Returns 0 if we the length to write is bigger than the
76  *   reserved buffer space. In this case, nothing gets written.
77  */
78 int trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
79 {
80 	unsigned int len = TRACE_SEQ_BUF_LEFT(s);
81 	va_list ap;
82 	int ret;
83 
84 	if (s->full || !len)
85 		return 0;
86 
87 	va_start(ap, fmt);
88 	ret = vsnprintf(s->buffer + s->len, len, fmt, ap);
89 	va_end(ap);
90 
91 	/* If we can't write it all, don't bother writing anything */
92 	if (ret >= len) {
93 		s->full = 1;
94 		return 0;
95 	}
96 
97 	s->len += ret;
98 
99 	return 1;
100 }
101 EXPORT_SYMBOL_GPL(trace_seq_printf);
102 
103 /**
104  * trace_seq_bitmask - write a bitmask array in its ASCII representation
105  * @s:		trace sequence descriptor
106  * @maskp:	points to an array of unsigned longs that represent a bitmask
107  * @nmaskbits:	The number of bits that are valid in @maskp
108  *
109  * Writes a ASCII representation of a bitmask string into @s.
110  *
111  * Returns 1 if we successfully written all the contents to
112  *   the buffer.
113  * Returns 0 if we the length to write is bigger than the
114  *   reserved buffer space. In this case, nothing gets written.
115  */
116 int trace_seq_bitmask(struct trace_seq *s, const unsigned long *maskp,
117 		      int nmaskbits)
118 {
119 	unsigned int len = TRACE_SEQ_BUF_LEFT(s);
120 	int ret;
121 
122 	if (s->full || !len)
123 		return 0;
124 
125 	ret = bitmap_scnprintf(s->buffer, len, maskp, nmaskbits);
126 	s->len += ret;
127 
128 	return 1;
129 }
130 EXPORT_SYMBOL_GPL(trace_seq_bitmask);
131 
132 /**
133  * trace_seq_vprintf - sequence printing of trace information
134  * @s: trace sequence descriptor
135  * @fmt: printf format string
136  *
137  * The tracer may use either sequence operations or its own
138  * copy to user routines. To simplify formating of a trace
139  * trace_seq_printf is used to store strings into a special
140  * buffer (@s). Then the output may be either used by
141  * the sequencer or pulled into another buffer.
142  *
143  * Returns how much it wrote to the buffer.
144  */
145 int trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
146 {
147 	unsigned int len = TRACE_SEQ_BUF_LEFT(s);
148 	int ret;
149 
150 	if (s->full || !len)
151 		return 0;
152 
153 	ret = vsnprintf(s->buffer + s->len, len, fmt, args);
154 
155 	/* If we can't write it all, don't bother writing anything */
156 	if (ret >= len) {
157 		s->full = 1;
158 		return 0;
159 	}
160 
161 	s->len += ret;
162 
163 	return len;
164 }
165 EXPORT_SYMBOL_GPL(trace_seq_vprintf);
166 
167 /**
168  * trace_seq_bprintf - Write the printf string from binary arguments
169  * @s: trace sequence descriptor
170  * @fmt: The format string for the @binary arguments
171  * @binary: The binary arguments for @fmt.
172  *
173  * When recording in a fast path, a printf may be recorded with just
174  * saving the format and the arguments as they were passed to the
175  * function, instead of wasting cycles converting the arguments into
176  * ASCII characters. Instead, the arguments are saved in a 32 bit
177  * word array that is defined by the format string constraints.
178  *
179  * This function will take the format and the binary array and finish
180  * the conversion into the ASCII string within the buffer.
181  *
182  * Returns how much it wrote to the buffer.
183  */
184 int trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary)
185 {
186 	unsigned int len = TRACE_SEQ_BUF_LEFT(s);
187 	int ret;
188 
189 	if (s->full || !len)
190 		return 0;
191 
192 	ret = bstr_printf(s->buffer + s->len, len, fmt, binary);
193 
194 	/* If we can't write it all, don't bother writing anything */
195 	if (ret >= len) {
196 		s->full = 1;
197 		return 0;
198 	}
199 
200 	s->len += ret;
201 
202 	return len;
203 }
204 EXPORT_SYMBOL_GPL(trace_seq_bprintf);
205 
206 /**
207  * trace_seq_puts - trace sequence printing of simple string
208  * @s: trace sequence descriptor
209  * @str: simple string to record
210  *
211  * The tracer may use either the sequence operations or its own
212  * copy to user routines. This function records a simple string
213  * into a special buffer (@s) for later retrieval by a sequencer
214  * or other mechanism.
215  *
216  * Returns how much it wrote to the buffer.
217  */
218 int trace_seq_puts(struct trace_seq *s, const char *str)
219 {
220 	unsigned int len = strlen(str);
221 
222 	if (s->full)
223 		return 0;
224 
225 	if (len > TRACE_SEQ_BUF_LEFT(s)) {
226 		s->full = 1;
227 		return 0;
228 	}
229 
230 	memcpy(s->buffer + s->len, str, len);
231 	s->len += len;
232 
233 	return len;
234 }
235 EXPORT_SYMBOL_GPL(trace_seq_puts);
236 
237 /**
238  * trace_seq_putc - trace sequence printing of simple character
239  * @s: trace sequence descriptor
240  * @c: simple character to record
241  *
242  * The tracer may use either the sequence operations or its own
243  * copy to user routines. This function records a simple charater
244  * into a special buffer (@s) for later retrieval by a sequencer
245  * or other mechanism.
246  *
247  * Returns how much it wrote to the buffer.
248  */
249 int trace_seq_putc(struct trace_seq *s, unsigned char c)
250 {
251 	if (s->full)
252 		return 0;
253 
254 	if (TRACE_SEQ_BUF_LEFT(s) < 1) {
255 		s->full = 1;
256 		return 0;
257 	}
258 
259 	s->buffer[s->len++] = c;
260 
261 	return 1;
262 }
263 EXPORT_SYMBOL_GPL(trace_seq_putc);
264 
265 /**
266  * trace_seq_putmem - write raw data into the trace_seq buffer
267  * @s: trace sequence descriptor
268  * @mem: The raw memory to copy into the buffer
269  * @len: The length of the raw memory to copy (in bytes)
270  *
271  * There may be cases where raw memory needs to be written into the
272  * buffer and a strcpy() would not work. Using this function allows
273  * for such cases.
274  *
275  * Returns how much it wrote to the buffer.
276  */
277 int trace_seq_putmem(struct trace_seq *s, const void *mem, unsigned int len)
278 {
279 	if (s->full)
280 		return 0;
281 
282 	if (len > TRACE_SEQ_BUF_LEFT(s)) {
283 		s->full = 1;
284 		return 0;
285 	}
286 
287 	memcpy(s->buffer + s->len, mem, len);
288 	s->len += len;
289 
290 	return len;
291 }
292 EXPORT_SYMBOL_GPL(trace_seq_putmem);
293 
294 #define MAX_MEMHEX_BYTES	8U
295 #define HEX_CHARS		(MAX_MEMHEX_BYTES*2 + 1)
296 
297 /**
298  * trace_seq_putmem_hex - write raw memory into the buffer in ASCII hex
299  * @s: trace sequence descriptor
300  * @mem: The raw memory to write its hex ASCII representation of
301  * @len: The length of the raw memory to copy (in bytes)
302  *
303  * This is similar to trace_seq_putmem() except instead of just copying the
304  * raw memory into the buffer it writes its ASCII representation of it
305  * in hex characters.
306  *
307  * Returns how much it wrote to the buffer.
308  */
309 int trace_seq_putmem_hex(struct trace_seq *s, const void *mem,
310 			 unsigned int len)
311 {
312 	unsigned char hex[HEX_CHARS];
313 	const unsigned char *data = mem;
314 	unsigned int start_len;
315 	int i, j;
316 	int cnt = 0;
317 
318 	if (s->full)
319 		return 0;
320 
321 	while (len) {
322 		start_len = min(len, HEX_CHARS - 1);
323 #ifdef __BIG_ENDIAN
324 		for (i = 0, j = 0; i < start_len; i++) {
325 #else
326 		for (i = start_len-1, j = 0; i >= 0; i--) {
327 #endif
328 			hex[j++] = hex_asc_hi(data[i]);
329 			hex[j++] = hex_asc_lo(data[i]);
330 		}
331 		if (WARN_ON_ONCE(j == 0 || j/2 > len))
332 			break;
333 
334 		/* j increments twice per loop */
335 		len -= j / 2;
336 		hex[j++] = ' ';
337 
338 		cnt += trace_seq_putmem(s, hex, j);
339 	}
340 	return cnt;
341 }
342 EXPORT_SYMBOL_GPL(trace_seq_putmem_hex);
343 
344 /**
345  * trace_seq_reserve - reserve space on the sequence buffer
346  * @s: trace sequence descriptor
347  * @len: The amount to reserver.
348  *
349  * If for some reason there is a need to save some space on the
350  * buffer to fill in later, this function is used for that purpose.
351  * The given length will be reserved and the pointer to that
352  * location on the buffer is returned, unless there is not enough
353  * buffer left to hold the given length then NULL is returned.
354  */
355 void *trace_seq_reserve(struct trace_seq *s, unsigned int len)
356 {
357 	void *ret;
358 
359 	if (s->full)
360 		return NULL;
361 
362 	if (len > TRACE_SEQ_BUF_LEFT(s)) {
363 		s->full = 1;
364 		return NULL;
365 	}
366 
367 	ret = s->buffer + s->len;
368 	s->len += len;
369 
370 	return ret;
371 }
372 EXPORT_SYMBOL_GPL(trace_seq_reserve);
373 
374 /**
375  * trace_seq_path - copy a path into the sequence buffer
376  * @s: trace sequence descriptor
377  * @path: path to write into the sequence buffer.
378  *
379  * Write a path name into the sequence buffer.
380  *
381  * Returns 1 if we successfully written all the contents to
382  *   the buffer.
383  * Returns 0 if we the length to write is bigger than the
384  *   reserved buffer space. In this case, nothing gets written.
385  */
386 int trace_seq_path(struct trace_seq *s, const struct path *path)
387 {
388 	unsigned char *p;
389 
390 	if (s->full)
391 		return 0;
392 
393 	if (TRACE_SEQ_BUF_LEFT(s) < 1) {
394 		s->full = 1;
395 		return 0;
396 	}
397 
398 	p = d_path(path, s->buffer + s->len, PAGE_SIZE - s->len);
399 	if (!IS_ERR(p)) {
400 		p = mangle_path(s->buffer + s->len, p, "\n");
401 		if (p) {
402 			s->len = p - s->buffer;
403 			return 1;
404 		}
405 	} else {
406 		s->buffer[s->len++] = '?';
407 		return 1;
408 	}
409 
410 	s->full = 1;
411 	return 0;
412 }
413 EXPORT_SYMBOL_GPL(trace_seq_path);
414 
415 /**
416  * trace_seq_to_user - copy the squence buffer to user space
417  * @s: trace sequence descriptor
418  * @ubuf: The userspace memory location to copy to
419  * @cnt: The amount to copy
420  *
421  * Copies the sequence buffer into the userspace memory pointed to
422  * by @ubuf. It starts from the last read position (@s->readpos)
423  * and writes up to @cnt characters or till it reaches the end of
424  * the content in the buffer (@s->len), which ever comes first.
425  *
426  * On success, it returns a positive number of the number of bytes
427  * it copied.
428  *
429  * On failure it returns -EBUSY if all of the content in the
430  * sequence has been already read, which includes nothing in the
431  * sequenc (@s->len == @s->readpos).
432  *
433  * Returns -EFAULT if the copy to userspace fails.
434  */
435 int trace_seq_to_user(struct trace_seq *s, char __user *ubuf, int cnt)
436 {
437 	int len;
438 	int ret;
439 
440 	if (!cnt)
441 		return 0;
442 
443 	if (s->len <= s->readpos)
444 		return -EBUSY;
445 
446 	len = s->len - s->readpos;
447 	if (cnt > len)
448 		cnt = len;
449 	ret = copy_to_user(ubuf, s->buffer + s->readpos, cnt);
450 	if (ret == cnt)
451 		return -EFAULT;
452 
453 	cnt -= ret;
454 
455 	s->readpos += cnt;
456 	return cnt;
457 }
458 EXPORT_SYMBOL_GPL(trace_seq_to_user);
459