xref: /linux-6.15/kernel/trace/trace_seq.c (revision 36aabfff)
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 HEX_CHARS		(MAX_MEMHEX_BYTES*2 + 1)
295 
296 /**
297  * trace_seq_putmem_hex - write raw memory into the buffer in ASCII hex
298  * @s: trace sequence descriptor
299  * @mem: The raw memory to write its hex ASCII representation of
300  * @len: The length of the raw memory to copy (in bytes)
301  *
302  * This is similar to trace_seq_putmem() except instead of just copying the
303  * raw memory into the buffer it writes its ASCII representation of it
304  * in hex characters.
305  *
306  * Returns how much it wrote to the buffer.
307  */
308 int trace_seq_putmem_hex(struct trace_seq *s, const void *mem,
309 			 unsigned int len)
310 {
311 	unsigned char hex[HEX_CHARS];
312 	const unsigned char *data = mem;
313 	int i, j;
314 
315 	if (s->full)
316 		return 0;
317 
318 #ifdef __BIG_ENDIAN
319 	for (i = 0, j = 0; i < len; i++) {
320 #else
321 	for (i = len-1, j = 0; i >= 0; i--) {
322 #endif
323 		hex[j++] = hex_asc_hi(data[i]);
324 		hex[j++] = hex_asc_lo(data[i]);
325 	}
326 	hex[j++] = ' ';
327 
328 	return trace_seq_putmem(s, hex, j);
329 }
330 EXPORT_SYMBOL_GPL(trace_seq_putmem_hex);
331 
332 /**
333  * trace_seq_reserve - reserve space on the sequence buffer
334  * @s: trace sequence descriptor
335  * @len: The amount to reserver.
336  *
337  * If for some reason there is a need to save some space on the
338  * buffer to fill in later, this function is used for that purpose.
339  * The given length will be reserved and the pointer to that
340  * location on the buffer is returned, unless there is not enough
341  * buffer left to hold the given length then NULL is returned.
342  */
343 void *trace_seq_reserve(struct trace_seq *s, unsigned int len)
344 {
345 	void *ret;
346 
347 	if (s->full)
348 		return NULL;
349 
350 	if (len > TRACE_SEQ_BUF_LEFT(s)) {
351 		s->full = 1;
352 		return NULL;
353 	}
354 
355 	ret = s->buffer + s->len;
356 	s->len += len;
357 
358 	return ret;
359 }
360 EXPORT_SYMBOL_GPL(trace_seq_reserve);
361 
362 /**
363  * trace_seq_path - copy a path into the sequence buffer
364  * @s: trace sequence descriptor
365  * @path: path to write into the sequence buffer.
366  *
367  * Write a path name into the sequence buffer.
368  *
369  * Returns 1 if we successfully written all the contents to
370  *   the buffer.
371  * Returns 0 if we the length to write is bigger than the
372  *   reserved buffer space. In this case, nothing gets written.
373  */
374 int trace_seq_path(struct trace_seq *s, const struct path *path)
375 {
376 	unsigned char *p;
377 
378 	if (s->full)
379 		return 0;
380 
381 	if (TRACE_SEQ_BUF_LEFT(s) < 1) {
382 		s->full = 1;
383 		return 0;
384 	}
385 
386 	p = d_path(path, s->buffer + s->len, PAGE_SIZE - s->len);
387 	if (!IS_ERR(p)) {
388 		p = mangle_path(s->buffer + s->len, p, "\n");
389 		if (p) {
390 			s->len = p - s->buffer;
391 			return 1;
392 		}
393 	} else {
394 		s->buffer[s->len++] = '?';
395 		return 1;
396 	}
397 
398 	s->full = 1;
399 	return 0;
400 }
401 EXPORT_SYMBOL_GPL(trace_seq_path);
402 
403 /**
404  * trace_seq_to_user - copy the squence buffer to user space
405  * @s: trace sequence descriptor
406  * @ubuf: The userspace memory location to copy to
407  * @cnt: The amount to copy
408  *
409  * Copies the sequence buffer into the userspace memory pointed to
410  * by @ubuf. It starts from the last read position (@s->readpos)
411  * and writes up to @cnt characters or till it reaches the end of
412  * the content in the buffer (@s->len), which ever comes first.
413  *
414  * On success, it returns a positive number of the number of bytes
415  * it copied.
416  *
417  * On failure it returns -EBUSY if all of the content in the
418  * sequence has been already read, which includes nothing in the
419  * sequenc (@s->len == @s->readpos).
420  *
421  * Returns -EFAULT if the copy to userspace fails.
422  */
423 int trace_seq_to_user(struct trace_seq *s, char __user *ubuf, int cnt)
424 {
425 	int len;
426 	int ret;
427 
428 	if (!cnt)
429 		return 0;
430 
431 	if (s->len <= s->readpos)
432 		return -EBUSY;
433 
434 	len = s->len - s->readpos;
435 	if (cnt > len)
436 		cnt = len;
437 	ret = copy_to_user(ubuf, s->buffer + s->readpos, cnt);
438 	if (ret == cnt)
439 		return -EFAULT;
440 
441 	cnt -= ret;
442 
443 	s->readpos += cnt;
444 	return cnt;
445 }
446 EXPORT_SYMBOL_GPL(trace_seq_to_user);
447