xref: /openbmc/linux/kernel/trace/trace_seq.c (revision 9144f784f852f9a125cabe9927b986d909bfa439)
1bcea3f96SSteven Rostedt (VMware) // SPDX-License-Identifier: GPL-2.0
212306276SSteven Rostedt (Red Hat) /*
312306276SSteven Rostedt (Red Hat)  * trace_seq.c
412306276SSteven Rostedt (Red Hat)  *
512306276SSteven Rostedt (Red Hat)  * Copyright (C) 2008-2014 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
612306276SSteven Rostedt (Red Hat)  *
736aabfffSSteven Rostedt (Red Hat)  * The trace_seq is a handy tool that allows you to pass a descriptor around
836aabfffSSteven Rostedt (Red Hat)  * to a buffer that other functions can write to. It is similar to the
936aabfffSSteven Rostedt (Red Hat)  * seq_file functionality but has some differences.
1036aabfffSSteven Rostedt (Red Hat)  *
1136aabfffSSteven Rostedt (Red Hat)  * To use it, the trace_seq must be initialized with trace_seq_init().
1236aabfffSSteven Rostedt (Red Hat)  * This will set up the counters within the descriptor. You can call
1336aabfffSSteven Rostedt (Red Hat)  * trace_seq_init() more than once to reset the trace_seq to start
1436aabfffSSteven Rostedt (Red Hat)  * from scratch.
1536aabfffSSteven Rostedt (Red Hat)  *
1636aabfffSSteven Rostedt (Red Hat)  * The buffer size is currently PAGE_SIZE, although it may become dynamic
1736aabfffSSteven Rostedt (Red Hat)  * in the future.
1836aabfffSSteven Rostedt (Red Hat)  *
19f2cc020dSIngo Molnar  * A write to the buffer will either succeed or fail. That is, unlike
2036aabfffSSteven Rostedt (Red Hat)  * sprintf() there will not be a partial write (well it may write into
2136aabfffSSteven Rostedt (Red Hat)  * the buffer but it wont update the pointers). This allows users to
2236aabfffSSteven Rostedt (Red Hat)  * try to write something into the trace_seq buffer and if it fails
2336aabfffSSteven Rostedt (Red Hat)  * they can flush it and try again.
2436aabfffSSteven Rostedt (Red Hat)  *
2512306276SSteven Rostedt (Red Hat)  */
2612306276SSteven Rostedt (Red Hat) #include <linux/uaccess.h>
2712306276SSteven Rostedt (Red Hat) #include <linux/seq_file.h>
2812306276SSteven Rostedt (Red Hat) #include <linux/trace_seq.h>
2912306276SSteven Rostedt (Red Hat) 
3036aabfffSSteven Rostedt (Red Hat) /* How much buffer is left on the trace_seq? */
313a161d99SSteven Rostedt (Red Hat) #define TRACE_SEQ_BUF_LEFT(s) seq_buf_buffer_left(&(s)->seq)
3236aabfffSSteven Rostedt (Red Hat) 
333a161d99SSteven Rostedt (Red Hat) /*
343a161d99SSteven Rostedt (Red Hat)  * trace_seq should work with being initialized with 0s.
353a161d99SSteven Rostedt (Red Hat)  */
__trace_seq_init(struct trace_seq * s)363a161d99SSteven Rostedt (Red Hat) static inline void __trace_seq_init(struct trace_seq *s)
373a161d99SSteven Rostedt (Red Hat) {
383a161d99SSteven Rostedt (Red Hat) 	if (unlikely(!s->seq.size))
393a161d99SSteven Rostedt (Red Hat) 		trace_seq_init(s);
403a161d99SSteven Rostedt (Red Hat) }
4136aabfffSSteven Rostedt (Red Hat) 
4236aabfffSSteven Rostedt (Red Hat) /**
4336aabfffSSteven Rostedt (Red Hat)  * trace_print_seq - move the contents of trace_seq into a seq_file
4436aabfffSSteven Rostedt (Red Hat)  * @m: the seq_file descriptor that is the destination
4536aabfffSSteven Rostedt (Red Hat)  * @s: the trace_seq descriptor that is the source.
4636aabfffSSteven Rostedt (Red Hat)  *
4736aabfffSSteven Rostedt (Red Hat)  * Returns 0 on success and non zero on error. If it succeeds to
4836aabfffSSteven Rostedt (Red Hat)  * write to the seq_file it will reset the trace_seq, otherwise
4936aabfffSSteven Rostedt (Red Hat)  * it does not modify the trace_seq to let the caller try again.
5036aabfffSSteven Rostedt (Red Hat)  */
trace_print_seq(struct seq_file * m,struct trace_seq * s)5112306276SSteven Rostedt (Red Hat) int trace_print_seq(struct seq_file *m, struct trace_seq *s)
5212306276SSteven Rostedt (Red Hat) {
5312306276SSteven Rostedt (Red Hat) 	int ret;
5412306276SSteven Rostedt (Red Hat) 
553a161d99SSteven Rostedt (Red Hat) 	__trace_seq_init(s);
563a161d99SSteven Rostedt (Red Hat) 
573a161d99SSteven Rostedt (Red Hat) 	ret = seq_buf_print_seq(m, &s->seq);
5812306276SSteven Rostedt (Red Hat) 
5912306276SSteven Rostedt (Red Hat) 	/*
6012306276SSteven Rostedt (Red Hat) 	 * Only reset this buffer if we successfully wrote to the
6136aabfffSSteven Rostedt (Red Hat) 	 * seq_file buffer. This lets the caller try again or
6236aabfffSSteven Rostedt (Red Hat) 	 * do something else with the contents.
6312306276SSteven Rostedt (Red Hat) 	 */
6412306276SSteven Rostedt (Red Hat) 	if (!ret)
6512306276SSteven Rostedt (Red Hat) 		trace_seq_init(s);
6612306276SSteven Rostedt (Red Hat) 
6712306276SSteven Rostedt (Red Hat) 	return ret;
6812306276SSteven Rostedt (Red Hat) }
6912306276SSteven Rostedt (Red Hat) 
7012306276SSteven Rostedt (Red Hat) /**
7112306276SSteven Rostedt (Red Hat)  * trace_seq_printf - sequence printing of trace information
7212306276SSteven Rostedt (Red Hat)  * @s: trace sequence descriptor
7312306276SSteven Rostedt (Red Hat)  * @fmt: printf format string
7412306276SSteven Rostedt (Red Hat)  *
7512306276SSteven Rostedt (Red Hat)  * The tracer may use either sequence operations or its own
76f2cc020dSIngo Molnar  * copy to user routines. To simplify formatting of a trace
7736aabfffSSteven Rostedt (Red Hat)  * trace_seq_printf() is used to store strings into a special
7812306276SSteven Rostedt (Red Hat)  * buffer (@s). Then the output may be either used by
7912306276SSteven Rostedt (Red Hat)  * the sequencer or pulled into another buffer.
8012306276SSteven Rostedt (Red Hat)  */
trace_seq_printf(struct trace_seq * s,const char * fmt,...)81dba39448SSteven Rostedt (Red Hat) void trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
8212306276SSteven Rostedt (Red Hat) {
833a161d99SSteven Rostedt (Red Hat) 	unsigned int save_len = s->seq.len;
8412306276SSteven Rostedt (Red Hat) 	va_list ap;
8512306276SSteven Rostedt (Red Hat) 
863a161d99SSteven Rostedt (Red Hat) 	if (s->full)
87dba39448SSteven Rostedt (Red Hat) 		return;
8812306276SSteven Rostedt (Red Hat) 
893a161d99SSteven Rostedt (Red Hat) 	__trace_seq_init(s);
903a161d99SSteven Rostedt (Red Hat) 
9112306276SSteven Rostedt (Red Hat) 	va_start(ap, fmt);
923a161d99SSteven Rostedt (Red Hat) 	seq_buf_vprintf(&s->seq, fmt, ap);
9312306276SSteven Rostedt (Red Hat) 	va_end(ap);
9412306276SSteven Rostedt (Red Hat) 
9512306276SSteven Rostedt (Red Hat) 	/* If we can't write it all, don't bother writing anything */
963a161d99SSteven Rostedt (Red Hat) 	if (unlikely(seq_buf_has_overflowed(&s->seq))) {
973a161d99SSteven Rostedt (Red Hat) 		s->seq.len = save_len;
9812306276SSteven Rostedt (Red Hat) 		s->full = 1;
9912306276SSteven Rostedt (Red Hat) 	}
10012306276SSteven Rostedt (Red Hat) }
10112306276SSteven Rostedt (Red Hat) EXPORT_SYMBOL_GPL(trace_seq_printf);
10212306276SSteven Rostedt (Red Hat) 
10312306276SSteven Rostedt (Red Hat) /**
10436aabfffSSteven Rostedt (Red Hat)  * trace_seq_bitmask - write a bitmask array in its ASCII representation
10512306276SSteven Rostedt (Red Hat)  * @s:		trace sequence descriptor
10612306276SSteven Rostedt (Red Hat)  * @maskp:	points to an array of unsigned longs that represent a bitmask
10712306276SSteven Rostedt (Red Hat)  * @nmaskbits:	The number of bits that are valid in @maskp
10812306276SSteven Rostedt (Red Hat)  *
10912306276SSteven Rostedt (Red Hat)  * Writes a ASCII representation of a bitmask string into @s.
11012306276SSteven Rostedt (Red Hat)  */
trace_seq_bitmask(struct trace_seq * s,const unsigned long * maskp,int nmaskbits)111dba39448SSteven Rostedt (Red Hat) void trace_seq_bitmask(struct trace_seq *s, const unsigned long *maskp,
11212306276SSteven Rostedt (Red Hat) 		      int nmaskbits)
11312306276SSteven Rostedt (Red Hat) {
1143a161d99SSteven Rostedt (Red Hat) 	unsigned int save_len = s->seq.len;
11512306276SSteven Rostedt (Red Hat) 
1163a161d99SSteven Rostedt (Red Hat) 	if (s->full)
117dba39448SSteven Rostedt (Red Hat) 		return;
11812306276SSteven Rostedt (Red Hat) 
1193a161d99SSteven Rostedt (Red Hat) 	__trace_seq_init(s);
1203a161d99SSteven Rostedt (Red Hat) 
1211a40243bSTejun Heo 	seq_buf_printf(&s->seq, "%*pb", nmaskbits, maskp);
1223a161d99SSteven Rostedt (Red Hat) 
1233a161d99SSteven Rostedt (Red Hat) 	if (unlikely(seq_buf_has_overflowed(&s->seq))) {
1243a161d99SSteven Rostedt (Red Hat) 		s->seq.len = save_len;
1253a161d99SSteven Rostedt (Red Hat) 		s->full = 1;
1263a161d99SSteven Rostedt (Red Hat) 	}
12712306276SSteven Rostedt (Red Hat) }
12812306276SSteven Rostedt (Red Hat) EXPORT_SYMBOL_GPL(trace_seq_bitmask);
12912306276SSteven Rostedt (Red Hat) 
13012306276SSteven Rostedt (Red Hat) /**
13112306276SSteven Rostedt (Red Hat)  * trace_seq_vprintf - sequence printing of trace information
13212306276SSteven Rostedt (Red Hat)  * @s: trace sequence descriptor
13312306276SSteven Rostedt (Red Hat)  * @fmt: printf format string
1346c95d71bSGaosheng Cui  * @args: Arguments for the format string
13512306276SSteven Rostedt (Red Hat)  *
13612306276SSteven Rostedt (Red Hat)  * The tracer may use either sequence operations or its own
137f2cc020dSIngo Molnar  * copy to user routines. To simplify formatting of a trace
13812306276SSteven Rostedt (Red Hat)  * trace_seq_printf is used to store strings into a special
13912306276SSteven Rostedt (Red Hat)  * buffer (@s). Then the output may be either used by
14012306276SSteven Rostedt (Red Hat)  * the sequencer or pulled into another buffer.
14112306276SSteven Rostedt (Red Hat)  */
trace_seq_vprintf(struct trace_seq * s,const char * fmt,va_list args)142dba39448SSteven Rostedt (Red Hat) void trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
14312306276SSteven Rostedt (Red Hat) {
1443a161d99SSteven Rostedt (Red Hat) 	unsigned int save_len = s->seq.len;
14512306276SSteven Rostedt (Red Hat) 
1463a161d99SSteven Rostedt (Red Hat) 	if (s->full)
147dba39448SSteven Rostedt (Red Hat) 		return;
14812306276SSteven Rostedt (Red Hat) 
1493a161d99SSteven Rostedt (Red Hat) 	__trace_seq_init(s);
1503a161d99SSteven Rostedt (Red Hat) 
1513a161d99SSteven Rostedt (Red Hat) 	seq_buf_vprintf(&s->seq, fmt, args);
15212306276SSteven Rostedt (Red Hat) 
15312306276SSteven Rostedt (Red Hat) 	/* If we can't write it all, don't bother writing anything */
1543a161d99SSteven Rostedt (Red Hat) 	if (unlikely(seq_buf_has_overflowed(&s->seq))) {
1553a161d99SSteven Rostedt (Red Hat) 		s->seq.len = save_len;
15612306276SSteven Rostedt (Red Hat) 		s->full = 1;
15712306276SSteven Rostedt (Red Hat) 	}
15812306276SSteven Rostedt (Red Hat) }
15912306276SSteven Rostedt (Red Hat) EXPORT_SYMBOL_GPL(trace_seq_vprintf);
16012306276SSteven Rostedt (Red Hat) 
16136aabfffSSteven Rostedt (Red Hat) /**
16236aabfffSSteven Rostedt (Red Hat)  * trace_seq_bprintf - Write the printf string from binary arguments
16336aabfffSSteven Rostedt (Red Hat)  * @s: trace sequence descriptor
16436aabfffSSteven Rostedt (Red Hat)  * @fmt: The format string for the @binary arguments
16536aabfffSSteven Rostedt (Red Hat)  * @binary: The binary arguments for @fmt.
16636aabfffSSteven Rostedt (Red Hat)  *
16736aabfffSSteven Rostedt (Red Hat)  * When recording in a fast path, a printf may be recorded with just
16836aabfffSSteven Rostedt (Red Hat)  * saving the format and the arguments as they were passed to the
16936aabfffSSteven Rostedt (Red Hat)  * function, instead of wasting cycles converting the arguments into
17036aabfffSSteven Rostedt (Red Hat)  * ASCII characters. Instead, the arguments are saved in a 32 bit
17136aabfffSSteven Rostedt (Red Hat)  * word array that is defined by the format string constraints.
17236aabfffSSteven Rostedt (Red Hat)  *
17336aabfffSSteven Rostedt (Red Hat)  * This function will take the format and the binary array and finish
17436aabfffSSteven Rostedt (Red Hat)  * the conversion into the ASCII string within the buffer.
17536aabfffSSteven Rostedt (Red Hat)  */
trace_seq_bprintf(struct trace_seq * s,const char * fmt,const u32 * binary)176dba39448SSteven Rostedt (Red Hat) void trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary)
17712306276SSteven Rostedt (Red Hat) {
1783a161d99SSteven Rostedt (Red Hat) 	unsigned int save_len = s->seq.len;
17912306276SSteven Rostedt (Red Hat) 
1803a161d99SSteven Rostedt (Red Hat) 	if (s->full)
181dba39448SSteven Rostedt (Red Hat) 		return;
18212306276SSteven Rostedt (Red Hat) 
1833a161d99SSteven Rostedt (Red Hat) 	__trace_seq_init(s);
1843a161d99SSteven Rostedt (Red Hat) 
1853a161d99SSteven Rostedt (Red Hat) 	seq_buf_bprintf(&s->seq, fmt, binary);
18612306276SSteven Rostedt (Red Hat) 
18712306276SSteven Rostedt (Red Hat) 	/* If we can't write it all, don't bother writing anything */
1883a161d99SSteven Rostedt (Red Hat) 	if (unlikely(seq_buf_has_overflowed(&s->seq))) {
1893a161d99SSteven Rostedt (Red Hat) 		s->seq.len = save_len;
19012306276SSteven Rostedt (Red Hat) 		s->full = 1;
191dba39448SSteven Rostedt (Red Hat) 		return;
19212306276SSteven Rostedt (Red Hat) 	}
19312306276SSteven Rostedt (Red Hat) }
19436aabfffSSteven Rostedt (Red Hat) EXPORT_SYMBOL_GPL(trace_seq_bprintf);
19512306276SSteven Rostedt (Red Hat) 
19612306276SSteven Rostedt (Red Hat) /**
19712306276SSteven Rostedt (Red Hat)  * trace_seq_puts - trace sequence printing of simple string
19812306276SSteven Rostedt (Red Hat)  * @s: trace sequence descriptor
19912306276SSteven Rostedt (Red Hat)  * @str: simple string to record
20012306276SSteven Rostedt (Red Hat)  *
20112306276SSteven Rostedt (Red Hat)  * The tracer may use either the sequence operations or its own
20212306276SSteven Rostedt (Red Hat)  * copy to user routines. This function records a simple string
20312306276SSteven Rostedt (Red Hat)  * into a special buffer (@s) for later retrieval by a sequencer
20412306276SSteven Rostedt (Red Hat)  * or other mechanism.
20512306276SSteven Rostedt (Red Hat)  */
trace_seq_puts(struct trace_seq * s,const char * str)206dba39448SSteven Rostedt (Red Hat) void trace_seq_puts(struct trace_seq *s, const char *str)
20712306276SSteven Rostedt (Red Hat) {
20836aabfffSSteven Rostedt (Red Hat) 	unsigned int len = strlen(str);
20912306276SSteven Rostedt (Red Hat) 
21012306276SSteven Rostedt (Red Hat) 	if (s->full)
211dba39448SSteven Rostedt (Red Hat) 		return;
21212306276SSteven Rostedt (Red Hat) 
2133a161d99SSteven Rostedt (Red Hat) 	__trace_seq_init(s);
2143a161d99SSteven Rostedt (Red Hat) 
21536aabfffSSteven Rostedt (Red Hat) 	if (len > TRACE_SEQ_BUF_LEFT(s)) {
21612306276SSteven Rostedt (Red Hat) 		s->full = 1;
217dba39448SSteven Rostedt (Red Hat) 		return;
21812306276SSteven Rostedt (Red Hat) 	}
21912306276SSteven Rostedt (Red Hat) 
2203a161d99SSteven Rostedt (Red Hat) 	seq_buf_putmem(&s->seq, str, len);
22112306276SSteven Rostedt (Red Hat) }
22236aabfffSSteven Rostedt (Red Hat) EXPORT_SYMBOL_GPL(trace_seq_puts);
22312306276SSteven Rostedt (Red Hat) 
22436aabfffSSteven Rostedt (Red Hat) /**
22536aabfffSSteven Rostedt (Red Hat)  * trace_seq_putc - trace sequence printing of simple character
22636aabfffSSteven Rostedt (Red Hat)  * @s: trace sequence descriptor
22736aabfffSSteven Rostedt (Red Hat)  * @c: simple character to record
22836aabfffSSteven Rostedt (Red Hat)  *
22936aabfffSSteven Rostedt (Red Hat)  * The tracer may use either the sequence operations or its own
230f2cc020dSIngo Molnar  * copy to user routines. This function records a simple character
23136aabfffSSteven Rostedt (Red Hat)  * into a special buffer (@s) for later retrieval by a sequencer
23236aabfffSSteven Rostedt (Red Hat)  * or other mechanism.
23336aabfffSSteven Rostedt (Red Hat)  */
trace_seq_putc(struct trace_seq * s,unsigned char c)234dba39448SSteven Rostedt (Red Hat) void trace_seq_putc(struct trace_seq *s, unsigned char c)
23512306276SSteven Rostedt (Red Hat) {
23612306276SSteven Rostedt (Red Hat) 	if (s->full)
237dba39448SSteven Rostedt (Red Hat) 		return;
23812306276SSteven Rostedt (Red Hat) 
2393a161d99SSteven Rostedt (Red Hat) 	__trace_seq_init(s);
2403a161d99SSteven Rostedt (Red Hat) 
24136aabfffSSteven Rostedt (Red Hat) 	if (TRACE_SEQ_BUF_LEFT(s) < 1) {
24212306276SSteven Rostedt (Red Hat) 		s->full = 1;
243dba39448SSteven Rostedt (Red Hat) 		return;
24412306276SSteven Rostedt (Red Hat) 	}
24512306276SSteven Rostedt (Red Hat) 
2463a161d99SSteven Rostedt (Red Hat) 	seq_buf_putc(&s->seq, c);
24712306276SSteven Rostedt (Red Hat) }
24836aabfffSSteven Rostedt (Red Hat) EXPORT_SYMBOL_GPL(trace_seq_putc);
24912306276SSteven Rostedt (Red Hat) 
25036aabfffSSteven Rostedt (Red Hat) /**
25136aabfffSSteven Rostedt (Red Hat)  * trace_seq_putmem - write raw data into the trace_seq buffer
25236aabfffSSteven Rostedt (Red Hat)  * @s: trace sequence descriptor
25336aabfffSSteven Rostedt (Red Hat)  * @mem: The raw memory to copy into the buffer
25436aabfffSSteven Rostedt (Red Hat)  * @len: The length of the raw memory to copy (in bytes)
25536aabfffSSteven Rostedt (Red Hat)  *
25636aabfffSSteven Rostedt (Red Hat)  * There may be cases where raw memory needs to be written into the
25736aabfffSSteven Rostedt (Red Hat)  * buffer and a strcpy() would not work. Using this function allows
25836aabfffSSteven Rostedt (Red Hat)  * for such cases.
25936aabfffSSteven Rostedt (Red Hat)  */
trace_seq_putmem(struct trace_seq * s,const void * mem,unsigned int len)260dba39448SSteven Rostedt (Red Hat) void trace_seq_putmem(struct trace_seq *s, const void *mem, unsigned int len)
26112306276SSteven Rostedt (Red Hat) {
26212306276SSteven Rostedt (Red Hat) 	if (s->full)
263dba39448SSteven Rostedt (Red Hat) 		return;
26412306276SSteven Rostedt (Red Hat) 
2653a161d99SSteven Rostedt (Red Hat) 	__trace_seq_init(s);
2663a161d99SSteven Rostedt (Red Hat) 
26736aabfffSSteven Rostedt (Red Hat) 	if (len > TRACE_SEQ_BUF_LEFT(s)) {
26812306276SSteven Rostedt (Red Hat) 		s->full = 1;
269dba39448SSteven Rostedt (Red Hat) 		return;
27012306276SSteven Rostedt (Red Hat) 	}
27112306276SSteven Rostedt (Red Hat) 
2723a161d99SSteven Rostedt (Red Hat) 	seq_buf_putmem(&s->seq, mem, len);
27312306276SSteven Rostedt (Red Hat) }
27436aabfffSSteven Rostedt (Red Hat) EXPORT_SYMBOL_GPL(trace_seq_putmem);
27512306276SSteven Rostedt (Red Hat) 
27636aabfffSSteven Rostedt (Red Hat) /**
27736aabfffSSteven Rostedt (Red Hat)  * trace_seq_putmem_hex - write raw memory into the buffer in ASCII hex
27836aabfffSSteven Rostedt (Red Hat)  * @s: trace sequence descriptor
27936aabfffSSteven Rostedt (Red Hat)  * @mem: The raw memory to write its hex ASCII representation of
28036aabfffSSteven Rostedt (Red Hat)  * @len: The length of the raw memory to copy (in bytes)
28136aabfffSSteven Rostedt (Red Hat)  *
28236aabfffSSteven Rostedt (Red Hat)  * This is similar to trace_seq_putmem() except instead of just copying the
28336aabfffSSteven Rostedt (Red Hat)  * raw memory into the buffer it writes its ASCII representation of it
28436aabfffSSteven Rostedt (Red Hat)  * in hex characters.
28536aabfffSSteven Rostedt (Red Hat)  */
trace_seq_putmem_hex(struct trace_seq * s,const void * mem,unsigned int len)286dba39448SSteven Rostedt (Red Hat) void trace_seq_putmem_hex(struct trace_seq *s, const void *mem,
28736aabfffSSteven Rostedt (Red Hat) 			 unsigned int len)
28812306276SSteven Rostedt (Red Hat) {
2893a161d99SSteven Rostedt (Red Hat) 	unsigned int save_len = s->seq.len;
29012306276SSteven Rostedt (Red Hat) 
29112306276SSteven Rostedt (Red Hat) 	if (s->full)
292dba39448SSteven Rostedt (Red Hat) 		return;
29312306276SSteven Rostedt (Red Hat) 
2943a161d99SSteven Rostedt (Red Hat) 	__trace_seq_init(s);
2953a161d99SSteven Rostedt (Red Hat) 
2963a161d99SSteven Rostedt (Red Hat) 	/* Each byte is represented by two chars */
2973a161d99SSteven Rostedt (Red Hat) 	if (len * 2 > TRACE_SEQ_BUF_LEFT(s)) {
2983a161d99SSteven Rostedt (Red Hat) 		s->full = 1;
2993a161d99SSteven Rostedt (Red Hat) 		return;
30012306276SSteven Rostedt (Red Hat) 	}
3016d2289f3SSteven Rostedt (Red Hat) 
3023a161d99SSteven Rostedt (Red Hat) 	/* The added spaces can still cause an overflow */
3033a161d99SSteven Rostedt (Red Hat) 	seq_buf_putmem_hex(&s->seq, mem, len);
30412306276SSteven Rostedt (Red Hat) 
3053a161d99SSteven Rostedt (Red Hat) 	if (unlikely(seq_buf_has_overflowed(&s->seq))) {
3063a161d99SSteven Rostedt (Red Hat) 		s->seq.len = save_len;
3073a161d99SSteven Rostedt (Red Hat) 		s->full = 1;
3083a161d99SSteven Rostedt (Red Hat) 		return;
3096d2289f3SSteven Rostedt (Red Hat) 	}
31012306276SSteven Rostedt (Red Hat) }
31136aabfffSSteven Rostedt (Red Hat) EXPORT_SYMBOL_GPL(trace_seq_putmem_hex);
31212306276SSteven Rostedt (Red Hat) 
31336aabfffSSteven Rostedt (Red Hat) /**
31436aabfffSSteven Rostedt (Red Hat)  * trace_seq_path - copy a path into the sequence buffer
31536aabfffSSteven Rostedt (Red Hat)  * @s: trace sequence descriptor
31636aabfffSSteven Rostedt (Red Hat)  * @path: path to write into the sequence buffer.
31736aabfffSSteven Rostedt (Red Hat)  *
31836aabfffSSteven Rostedt (Red Hat)  * Write a path name into the sequence buffer.
31936aabfffSSteven Rostedt (Red Hat)  *
32036aabfffSSteven Rostedt (Red Hat)  * Returns 1 if we successfully written all the contents to
32136aabfffSSteven Rostedt (Red Hat)  *   the buffer.
32236aabfffSSteven Rostedt (Red Hat)  * Returns 0 if we the length to write is bigger than the
32336aabfffSSteven Rostedt (Red Hat)  *   reserved buffer space. In this case, nothing gets written.
32436aabfffSSteven Rostedt (Red Hat)  */
trace_seq_path(struct trace_seq * s,const struct path * path)32512306276SSteven Rostedt (Red Hat) int trace_seq_path(struct trace_seq *s, const struct path *path)
32612306276SSteven Rostedt (Red Hat) {
3273a161d99SSteven Rostedt (Red Hat) 	unsigned int save_len = s->seq.len;
32812306276SSteven Rostedt (Red Hat) 
32912306276SSteven Rostedt (Red Hat) 	if (s->full)
33012306276SSteven Rostedt (Red Hat) 		return 0;
33112306276SSteven Rostedt (Red Hat) 
3323a161d99SSteven Rostedt (Red Hat) 	__trace_seq_init(s);
3333a161d99SSteven Rostedt (Red Hat) 
33436aabfffSSteven Rostedt (Red Hat) 	if (TRACE_SEQ_BUF_LEFT(s) < 1) {
33512306276SSteven Rostedt (Red Hat) 		s->full = 1;
33612306276SSteven Rostedt (Red Hat) 		return 0;
33712306276SSteven Rostedt (Red Hat) 	}
33812306276SSteven Rostedt (Red Hat) 
339dd23180aSSteven Rostedt (Red Hat) 	seq_buf_path(&s->seq, path, "\n");
34012306276SSteven Rostedt (Red Hat) 
3413a161d99SSteven Rostedt (Red Hat) 	if (unlikely(seq_buf_has_overflowed(&s->seq))) {
3423a161d99SSteven Rostedt (Red Hat) 		s->seq.len = save_len;
34312306276SSteven Rostedt (Red Hat) 		s->full = 1;
34412306276SSteven Rostedt (Red Hat) 		return 0;
34512306276SSteven Rostedt (Red Hat) 	}
3463a161d99SSteven Rostedt (Red Hat) 
347dd23180aSSteven Rostedt (Red Hat) 	return 1;
3483a161d99SSteven Rostedt (Red Hat) }
34936aabfffSSteven Rostedt (Red Hat) EXPORT_SYMBOL_GPL(trace_seq_path);
35012306276SSteven Rostedt (Red Hat) 
35136aabfffSSteven Rostedt (Red Hat) /**
352f2cc020dSIngo Molnar  * trace_seq_to_user - copy the sequence buffer to user space
35336aabfffSSteven Rostedt (Red Hat)  * @s: trace sequence descriptor
35436aabfffSSteven Rostedt (Red Hat)  * @ubuf: The userspace memory location to copy to
35536aabfffSSteven Rostedt (Red Hat)  * @cnt: The amount to copy
35636aabfffSSteven Rostedt (Red Hat)  *
35736aabfffSSteven Rostedt (Red Hat)  * Copies the sequence buffer into the userspace memory pointed to
35836aabfffSSteven Rostedt (Red Hat)  * by @ubuf. It starts from the last read position (@s->readpos)
35936aabfffSSteven Rostedt (Red Hat)  * and writes up to @cnt characters or till it reaches the end of
36036aabfffSSteven Rostedt (Red Hat)  * the content in the buffer (@s->len), which ever comes first.
36136aabfffSSteven Rostedt (Red Hat)  *
36236aabfffSSteven Rostedt (Red Hat)  * On success, it returns a positive number of the number of bytes
36336aabfffSSteven Rostedt (Red Hat)  * it copied.
36436aabfffSSteven Rostedt (Red Hat)  *
36536aabfffSSteven Rostedt (Red Hat)  * On failure it returns -EBUSY if all of the content in the
36636aabfffSSteven Rostedt (Red Hat)  * sequence has been already read, which includes nothing in the
367f2cc020dSIngo Molnar  * sequence (@s->len == @s->readpos).
36836aabfffSSteven Rostedt (Red Hat)  *
36936aabfffSSteven Rostedt (Red Hat)  * Returns -EFAULT if the copy to userspace fails.
37036aabfffSSteven Rostedt (Red Hat)  */
trace_seq_to_user(struct trace_seq * s,char __user * ubuf,int cnt)37136aabfffSSteven Rostedt (Red Hat) int trace_seq_to_user(struct trace_seq *s, char __user *ubuf, int cnt)
37212306276SSteven Rostedt (Red Hat) {
373*c46547b4SMatthew Wilcox (Oracle) 	int ret;
3743a161d99SSteven Rostedt (Red Hat) 	__trace_seq_init(s);
375*c46547b4SMatthew Wilcox (Oracle) 	ret = seq_buf_to_user(&s->seq, ubuf, s->readpos, cnt);
376*c46547b4SMatthew Wilcox (Oracle) 	if (ret > 0)
377*c46547b4SMatthew Wilcox (Oracle) 		s->readpos += ret;
378*c46547b4SMatthew Wilcox (Oracle) 	return ret;
37912306276SSteven Rostedt (Red Hat) }
38036aabfffSSteven Rostedt (Red Hat) EXPORT_SYMBOL_GPL(trace_seq_to_user);
381ef56e047SPiotr Maziarz 
trace_seq_hex_dump(struct trace_seq * s,const char * prefix_str,int prefix_type,int rowsize,int groupsize,const void * buf,size_t len,bool ascii)382ef56e047SPiotr Maziarz int trace_seq_hex_dump(struct trace_seq *s, const char *prefix_str,
383ef56e047SPiotr Maziarz 		       int prefix_type, int rowsize, int groupsize,
384ef56e047SPiotr Maziarz 		       const void *buf, size_t len, bool ascii)
385ef56e047SPiotr Maziarz {
386ef56e047SPiotr Maziarz 	unsigned int save_len = s->seq.len;
387ef56e047SPiotr Maziarz 
388ef56e047SPiotr Maziarz 	if (s->full)
389ef56e047SPiotr Maziarz 		return 0;
390ef56e047SPiotr Maziarz 
391ef56e047SPiotr Maziarz 	__trace_seq_init(s);
392ef56e047SPiotr Maziarz 
393ef56e047SPiotr Maziarz 	if (TRACE_SEQ_BUF_LEFT(s) < 1) {
394ef56e047SPiotr Maziarz 		s->full = 1;
395ef56e047SPiotr Maziarz 		return 0;
396ef56e047SPiotr Maziarz 	}
397ef56e047SPiotr Maziarz 
398ef56e047SPiotr Maziarz 	seq_buf_hex_dump(&(s->seq), prefix_str,
399ef56e047SPiotr Maziarz 		   prefix_type, rowsize, groupsize,
400ef56e047SPiotr Maziarz 		   buf, len, ascii);
401ef56e047SPiotr Maziarz 
402ef56e047SPiotr Maziarz 	if (unlikely(seq_buf_has_overflowed(&s->seq))) {
403ef56e047SPiotr Maziarz 		s->seq.len = save_len;
404ef56e047SPiotr Maziarz 		s->full = 1;
405ef56e047SPiotr Maziarz 		return 0;
406ef56e047SPiotr Maziarz 	}
407ef56e047SPiotr Maziarz 
408ef56e047SPiotr Maziarz 	return 1;
409ef56e047SPiotr Maziarz }
410ef56e047SPiotr Maziarz EXPORT_SYMBOL(trace_seq_hex_dump);
411a9c4bdd5SLinyu Yuan 
412a9c4bdd5SLinyu Yuan /*
413a9c4bdd5SLinyu Yuan  * trace_seq_acquire - acquire seq buffer with size len
414a9c4bdd5SLinyu Yuan  * @s: trace sequence descriptor
415a9c4bdd5SLinyu Yuan  * @len: size of buffer to be acquired
416a9c4bdd5SLinyu Yuan  *
417a9c4bdd5SLinyu Yuan  * acquire buffer with size of @len from trace_seq for output usage,
418a9c4bdd5SLinyu Yuan  * user can fill string into that buffer.
419a9c4bdd5SLinyu Yuan  *
420a9c4bdd5SLinyu Yuan  * Returns start address of acquired buffer.
421a9c4bdd5SLinyu Yuan  *
422a9c4bdd5SLinyu Yuan  * it allow multiple usage in one trace output function call.
423a9c4bdd5SLinyu Yuan  */
trace_seq_acquire(struct trace_seq * s,unsigned int len)424a9c4bdd5SLinyu Yuan char *trace_seq_acquire(struct trace_seq *s, unsigned int len)
425a9c4bdd5SLinyu Yuan {
426a9c4bdd5SLinyu Yuan 	char *ret = trace_seq_buffer_ptr(s);
427a9c4bdd5SLinyu Yuan 
428a9c4bdd5SLinyu Yuan 	if (!WARN_ON_ONCE(seq_buf_buffer_left(&s->seq) < len))
429a9c4bdd5SLinyu Yuan 		seq_buf_commit(&s->seq, len);
430a9c4bdd5SLinyu Yuan 
431a9c4bdd5SLinyu Yuan 	return ret;
432a9c4bdd5SLinyu Yuan }
433a9c4bdd5SLinyu Yuan EXPORT_SYMBOL(trace_seq_acquire);
434