xref: /openbmc/linux/kernel/trace/trace_seq.c (revision 275876e2)
1 /*
2  * trace_seq.c
3  *
4  * Copyright (C) 2008-2014 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
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_path - copy a path into the sequence buffer
346  * @s: trace sequence descriptor
347  * @path: path to write into the sequence buffer.
348  *
349  * Write a path name into the sequence buffer.
350  *
351  * Returns 1 if we successfully written all the contents to
352  *   the buffer.
353  * Returns 0 if we the length to write is bigger than the
354  *   reserved buffer space. In this case, nothing gets written.
355  */
356 int trace_seq_path(struct trace_seq *s, const struct path *path)
357 {
358 	unsigned char *p;
359 
360 	if (s->full)
361 		return 0;
362 
363 	if (TRACE_SEQ_BUF_LEFT(s) < 1) {
364 		s->full = 1;
365 		return 0;
366 	}
367 
368 	p = d_path(path, s->buffer + s->len, PAGE_SIZE - s->len);
369 	if (!IS_ERR(p)) {
370 		p = mangle_path(s->buffer + s->len, p, "\n");
371 		if (p) {
372 			s->len = p - s->buffer;
373 			return 1;
374 		}
375 	} else {
376 		s->buffer[s->len++] = '?';
377 		return 1;
378 	}
379 
380 	s->full = 1;
381 	return 0;
382 }
383 EXPORT_SYMBOL_GPL(trace_seq_path);
384 
385 /**
386  * trace_seq_to_user - copy the squence buffer to user space
387  * @s: trace sequence descriptor
388  * @ubuf: The userspace memory location to copy to
389  * @cnt: The amount to copy
390  *
391  * Copies the sequence buffer into the userspace memory pointed to
392  * by @ubuf. It starts from the last read position (@s->readpos)
393  * and writes up to @cnt characters or till it reaches the end of
394  * the content in the buffer (@s->len), which ever comes first.
395  *
396  * On success, it returns a positive number of the number of bytes
397  * it copied.
398  *
399  * On failure it returns -EBUSY if all of the content in the
400  * sequence has been already read, which includes nothing in the
401  * sequenc (@s->len == @s->readpos).
402  *
403  * Returns -EFAULT if the copy to userspace fails.
404  */
405 int trace_seq_to_user(struct trace_seq *s, char __user *ubuf, int cnt)
406 {
407 	int len;
408 	int ret;
409 
410 	if (!cnt)
411 		return 0;
412 
413 	if (s->len <= s->readpos)
414 		return -EBUSY;
415 
416 	len = s->len - s->readpos;
417 	if (cnt > len)
418 		cnt = len;
419 	ret = copy_to_user(ubuf, s->buffer + s->readpos, cnt);
420 	if (ret == cnt)
421 		return -EFAULT;
422 
423 	cnt -= ret;
424 
425 	s->readpos += cnt;
426 	return cnt;
427 }
428 EXPORT_SYMBOL_GPL(trace_seq_to_user);
429