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 <[email protected]>
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) *
16f2cc020dSIngo Molnar * A write to the buffer will either succeed or fail. That is, unlike
1736aabfffSSteven Rostedt (Red Hat) * sprintf() there will not be a partial write (well it may write into
1836aabfffSSteven Rostedt (Red Hat) * the buffer but it wont update the pointers). This allows users to
1936aabfffSSteven Rostedt (Red Hat) * try to write something into the trace_seq buffer and if it fails
2036aabfffSSteven Rostedt (Red Hat) * they can flush it and try again.
2136aabfffSSteven Rostedt (Red Hat) *
2212306276SSteven Rostedt (Red Hat) */
2312306276SSteven Rostedt (Red Hat) #include <linux/uaccess.h>
2412306276SSteven Rostedt (Red Hat) #include <linux/seq_file.h>
2512306276SSteven Rostedt (Red Hat) #include <linux/trace_seq.h>
2612306276SSteven Rostedt (Red Hat)
2736aabfffSSteven Rostedt (Red Hat) /* How much buffer is left on the trace_seq? */
283a161d99SSteven Rostedt (Red Hat) #define TRACE_SEQ_BUF_LEFT(s) seq_buf_buffer_left(&(s)->seq)
2936aabfffSSteven Rostedt (Red Hat)
303a161d99SSteven Rostedt (Red Hat) /*
313a161d99SSteven Rostedt (Red Hat) * trace_seq should work with being initialized with 0s.
323a161d99SSteven Rostedt (Red Hat) */
__trace_seq_init(struct trace_seq * s)333a161d99SSteven Rostedt (Red Hat) static inline void __trace_seq_init(struct trace_seq *s)
343a161d99SSteven Rostedt (Red Hat) {
353a161d99SSteven Rostedt (Red Hat) if (unlikely(!s->seq.size))
363a161d99SSteven Rostedt (Red Hat) trace_seq_init(s);
373a161d99SSteven Rostedt (Red Hat) }
3836aabfffSSteven Rostedt (Red Hat)
3936aabfffSSteven Rostedt (Red Hat) /**
4036aabfffSSteven Rostedt (Red Hat) * trace_print_seq - move the contents of trace_seq into a seq_file
4136aabfffSSteven Rostedt (Red Hat) * @m: the seq_file descriptor that is the destination
4236aabfffSSteven Rostedt (Red Hat) * @s: the trace_seq descriptor that is the source.
4336aabfffSSteven Rostedt (Red Hat) *
4436aabfffSSteven Rostedt (Red Hat) * Returns 0 on success and non zero on error. If it succeeds to
4536aabfffSSteven Rostedt (Red Hat) * write to the seq_file it will reset the trace_seq, otherwise
4636aabfffSSteven Rostedt (Red Hat) * it does not modify the trace_seq to let the caller try again.
4736aabfffSSteven Rostedt (Red Hat) */
trace_print_seq(struct seq_file * m,struct trace_seq * s)4812306276SSteven Rostedt (Red Hat) int trace_print_seq(struct seq_file *m, struct trace_seq *s)
4912306276SSteven Rostedt (Red Hat) {
5012306276SSteven Rostedt (Red Hat) int ret;
5112306276SSteven Rostedt (Red Hat)
523a161d99SSteven Rostedt (Red Hat) __trace_seq_init(s);
533a161d99SSteven Rostedt (Red Hat)
543a161d99SSteven Rostedt (Red Hat) ret = seq_buf_print_seq(m, &s->seq);
5512306276SSteven Rostedt (Red Hat)
5612306276SSteven Rostedt (Red Hat) /*
5712306276SSteven Rostedt (Red Hat) * Only reset this buffer if we successfully wrote to the
5836aabfffSSteven Rostedt (Red Hat) * seq_file buffer. This lets the caller try again or
5936aabfffSSteven Rostedt (Red Hat) * do something else with the contents.
6012306276SSteven Rostedt (Red Hat) */
6112306276SSteven Rostedt (Red Hat) if (!ret)
6212306276SSteven Rostedt (Red Hat) trace_seq_init(s);
6312306276SSteven Rostedt (Red Hat)
6412306276SSteven Rostedt (Red Hat) return ret;
6512306276SSteven Rostedt (Red Hat) }
6612306276SSteven Rostedt (Red Hat)
6712306276SSteven Rostedt (Red Hat) /**
6812306276SSteven Rostedt (Red Hat) * trace_seq_printf - sequence printing of trace information
6912306276SSteven Rostedt (Red Hat) * @s: trace sequence descriptor
7012306276SSteven Rostedt (Red Hat) * @fmt: printf format string
7112306276SSteven Rostedt (Red Hat) *
7212306276SSteven Rostedt (Red Hat) * The tracer may use either sequence operations or its own
73f2cc020dSIngo Molnar * copy to user routines. To simplify formatting of a trace
7436aabfffSSteven Rostedt (Red Hat) * trace_seq_printf() is used to store strings into a special
7512306276SSteven Rostedt (Red Hat) * buffer (@s). Then the output may be either used by
7612306276SSteven Rostedt (Red Hat) * the sequencer or pulled into another buffer.
7712306276SSteven Rostedt (Red Hat) */
trace_seq_printf(struct trace_seq * s,const char * fmt,...)78dba39448SSteven Rostedt (Red Hat) void trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
7912306276SSteven Rostedt (Red Hat) {
803a161d99SSteven Rostedt (Red Hat) unsigned int save_len = s->seq.len;
8112306276SSteven Rostedt (Red Hat) va_list ap;
8212306276SSteven Rostedt (Red Hat)
833a161d99SSteven Rostedt (Red Hat) if (s->full)
84dba39448SSteven Rostedt (Red Hat) return;
8512306276SSteven Rostedt (Red Hat)
863a161d99SSteven Rostedt (Red Hat) __trace_seq_init(s);
873a161d99SSteven Rostedt (Red Hat)
8812306276SSteven Rostedt (Red Hat) va_start(ap, fmt);
893a161d99SSteven Rostedt (Red Hat) seq_buf_vprintf(&s->seq, fmt, ap);
9012306276SSteven Rostedt (Red Hat) va_end(ap);
9112306276SSteven Rostedt (Red Hat)
9212306276SSteven Rostedt (Red Hat) /* If we can't write it all, don't bother writing anything */
933a161d99SSteven Rostedt (Red Hat) if (unlikely(seq_buf_has_overflowed(&s->seq))) {
943a161d99SSteven Rostedt (Red Hat) s->seq.len = save_len;
9512306276SSteven Rostedt (Red Hat) s->full = 1;
9612306276SSteven Rostedt (Red Hat) }
9712306276SSteven Rostedt (Red Hat) }
9812306276SSteven Rostedt (Red Hat) EXPORT_SYMBOL_GPL(trace_seq_printf);
9912306276SSteven Rostedt (Red Hat)
10012306276SSteven Rostedt (Red Hat) /**
10136aabfffSSteven Rostedt (Red Hat) * trace_seq_bitmask - write a bitmask array in its ASCII representation
10212306276SSteven Rostedt (Red Hat) * @s: trace sequence descriptor
10312306276SSteven Rostedt (Red Hat) * @maskp: points to an array of unsigned longs that represent a bitmask
10412306276SSteven Rostedt (Red Hat) * @nmaskbits: The number of bits that are valid in @maskp
10512306276SSteven Rostedt (Red Hat) *
10612306276SSteven Rostedt (Red Hat) * Writes a ASCII representation of a bitmask string into @s.
10712306276SSteven Rostedt (Red Hat) */
trace_seq_bitmask(struct trace_seq * s,const unsigned long * maskp,int nmaskbits)108dba39448SSteven Rostedt (Red Hat) void trace_seq_bitmask(struct trace_seq *s, const unsigned long *maskp,
10912306276SSteven Rostedt (Red Hat) int nmaskbits)
11012306276SSteven Rostedt (Red Hat) {
1113a161d99SSteven Rostedt (Red Hat) unsigned int save_len = s->seq.len;
11212306276SSteven Rostedt (Red Hat)
1133a161d99SSteven Rostedt (Red Hat) if (s->full)
114dba39448SSteven Rostedt (Red Hat) return;
11512306276SSteven Rostedt (Red Hat)
1163a161d99SSteven Rostedt (Red Hat) __trace_seq_init(s);
1173a161d99SSteven Rostedt (Red Hat)
1181a40243bSTejun Heo seq_buf_printf(&s->seq, "%*pb", nmaskbits, maskp);
1193a161d99SSteven Rostedt (Red Hat)
1203a161d99SSteven Rostedt (Red Hat) if (unlikely(seq_buf_has_overflowed(&s->seq))) {
1213a161d99SSteven Rostedt (Red Hat) s->seq.len = save_len;
1223a161d99SSteven Rostedt (Red Hat) s->full = 1;
1233a161d99SSteven Rostedt (Red Hat) }
12412306276SSteven Rostedt (Red Hat) }
12512306276SSteven Rostedt (Red Hat) EXPORT_SYMBOL_GPL(trace_seq_bitmask);
12612306276SSteven Rostedt (Red Hat)
12712306276SSteven Rostedt (Red Hat) /**
12812306276SSteven Rostedt (Red Hat) * trace_seq_vprintf - sequence printing of trace information
12912306276SSteven Rostedt (Red Hat) * @s: trace sequence descriptor
13012306276SSteven Rostedt (Red Hat) * @fmt: printf format string
1316c95d71bSGaosheng Cui * @args: Arguments for the format string
13212306276SSteven Rostedt (Red Hat) *
13312306276SSteven Rostedt (Red Hat) * The tracer may use either sequence operations or its own
134f2cc020dSIngo Molnar * copy to user routines. To simplify formatting of a trace
13512306276SSteven Rostedt (Red Hat) * trace_seq_printf is used to store strings into a special
13612306276SSteven Rostedt (Red Hat) * buffer (@s). Then the output may be either used by
13712306276SSteven Rostedt (Red Hat) * the sequencer or pulled into another buffer.
13812306276SSteven Rostedt (Red Hat) */
trace_seq_vprintf(struct trace_seq * s,const char * fmt,va_list args)139dba39448SSteven Rostedt (Red Hat) void trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
14012306276SSteven Rostedt (Red Hat) {
1413a161d99SSteven Rostedt (Red Hat) unsigned int save_len = s->seq.len;
14212306276SSteven Rostedt (Red Hat)
1433a161d99SSteven Rostedt (Red Hat) if (s->full)
144dba39448SSteven Rostedt (Red Hat) return;
14512306276SSteven Rostedt (Red Hat)
1463a161d99SSteven Rostedt (Red Hat) __trace_seq_init(s);
1473a161d99SSteven Rostedt (Red Hat)
1483a161d99SSteven Rostedt (Red Hat) seq_buf_vprintf(&s->seq, fmt, args);
14912306276SSteven Rostedt (Red Hat)
15012306276SSteven Rostedt (Red Hat) /* If we can't write it all, don't bother writing anything */
1513a161d99SSteven Rostedt (Red Hat) if (unlikely(seq_buf_has_overflowed(&s->seq))) {
1523a161d99SSteven Rostedt (Red Hat) s->seq.len = save_len;
15312306276SSteven Rostedt (Red Hat) s->full = 1;
15412306276SSteven Rostedt (Red Hat) }
15512306276SSteven Rostedt (Red Hat) }
15612306276SSteven Rostedt (Red Hat) EXPORT_SYMBOL_GPL(trace_seq_vprintf);
15712306276SSteven Rostedt (Red Hat)
15836aabfffSSteven Rostedt (Red Hat) /**
15936aabfffSSteven Rostedt (Red Hat) * trace_seq_bprintf - Write the printf string from binary arguments
16036aabfffSSteven Rostedt (Red Hat) * @s: trace sequence descriptor
16136aabfffSSteven Rostedt (Red Hat) * @fmt: The format string for the @binary arguments
16236aabfffSSteven Rostedt (Red Hat) * @binary: The binary arguments for @fmt.
16336aabfffSSteven Rostedt (Red Hat) *
16436aabfffSSteven Rostedt (Red Hat) * When recording in a fast path, a printf may be recorded with just
16536aabfffSSteven Rostedt (Red Hat) * saving the format and the arguments as they were passed to the
16636aabfffSSteven Rostedt (Red Hat) * function, instead of wasting cycles converting the arguments into
16736aabfffSSteven Rostedt (Red Hat) * ASCII characters. Instead, the arguments are saved in a 32 bit
16836aabfffSSteven Rostedt (Red Hat) * word array that is defined by the format string constraints.
16936aabfffSSteven Rostedt (Red Hat) *
17036aabfffSSteven Rostedt (Red Hat) * This function will take the format and the binary array and finish
17136aabfffSSteven Rostedt (Red Hat) * the conversion into the ASCII string within the buffer.
17236aabfffSSteven Rostedt (Red Hat) */
trace_seq_bprintf(struct trace_seq * s,const char * fmt,const u32 * binary)173dba39448SSteven Rostedt (Red Hat) void trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary)
17412306276SSteven Rostedt (Red Hat) {
1753a161d99SSteven Rostedt (Red Hat) unsigned int save_len = s->seq.len;
17612306276SSteven Rostedt (Red Hat)
1773a161d99SSteven Rostedt (Red Hat) if (s->full)
178dba39448SSteven Rostedt (Red Hat) return;
17912306276SSteven Rostedt (Red Hat)
1803a161d99SSteven Rostedt (Red Hat) __trace_seq_init(s);
1813a161d99SSteven Rostedt (Red Hat)
1823a161d99SSteven Rostedt (Red Hat) seq_buf_bprintf(&s->seq, fmt, binary);
18312306276SSteven Rostedt (Red Hat)
18412306276SSteven Rostedt (Red Hat) /* If we can't write it all, don't bother writing anything */
1853a161d99SSteven Rostedt (Red Hat) if (unlikely(seq_buf_has_overflowed(&s->seq))) {
1863a161d99SSteven Rostedt (Red Hat) s->seq.len = save_len;
18712306276SSteven Rostedt (Red Hat) s->full = 1;
188dba39448SSteven Rostedt (Red Hat) return;
18912306276SSteven Rostedt (Red Hat) }
19012306276SSteven Rostedt (Red Hat) }
19136aabfffSSteven Rostedt (Red Hat) EXPORT_SYMBOL_GPL(trace_seq_bprintf);
19212306276SSteven Rostedt (Red Hat)
19312306276SSteven Rostedt (Red Hat) /**
19412306276SSteven Rostedt (Red Hat) * trace_seq_puts - trace sequence printing of simple string
19512306276SSteven Rostedt (Red Hat) * @s: trace sequence descriptor
19612306276SSteven Rostedt (Red Hat) * @str: simple string to record
19712306276SSteven Rostedt (Red Hat) *
19812306276SSteven Rostedt (Red Hat) * The tracer may use either the sequence operations or its own
19912306276SSteven Rostedt (Red Hat) * copy to user routines. This function records a simple string
20012306276SSteven Rostedt (Red Hat) * into a special buffer (@s) for later retrieval by a sequencer
20112306276SSteven Rostedt (Red Hat) * or other mechanism.
20212306276SSteven Rostedt (Red Hat) */
trace_seq_puts(struct trace_seq * s,const char * str)203dba39448SSteven Rostedt (Red Hat) void trace_seq_puts(struct trace_seq *s, const char *str)
20412306276SSteven Rostedt (Red Hat) {
20536aabfffSSteven Rostedt (Red Hat) unsigned int len = strlen(str);
20612306276SSteven Rostedt (Red Hat)
20712306276SSteven Rostedt (Red Hat) if (s->full)
208dba39448SSteven Rostedt (Red Hat) return;
20912306276SSteven Rostedt (Red Hat)
2103a161d99SSteven Rostedt (Red Hat) __trace_seq_init(s);
2113a161d99SSteven Rostedt (Red Hat)
21236aabfffSSteven Rostedt (Red Hat) if (len > TRACE_SEQ_BUF_LEFT(s)) {
21312306276SSteven Rostedt (Red Hat) s->full = 1;
214dba39448SSteven Rostedt (Red Hat) return;
21512306276SSteven Rostedt (Red Hat) }
21612306276SSteven Rostedt (Red Hat)
2173a161d99SSteven Rostedt (Red Hat) seq_buf_putmem(&s->seq, str, len);
21812306276SSteven Rostedt (Red Hat) }
21936aabfffSSteven Rostedt (Red Hat) EXPORT_SYMBOL_GPL(trace_seq_puts);
22012306276SSteven Rostedt (Red Hat)
22136aabfffSSteven Rostedt (Red Hat) /**
22236aabfffSSteven Rostedt (Red Hat) * trace_seq_putc - trace sequence printing of simple character
22336aabfffSSteven Rostedt (Red Hat) * @s: trace sequence descriptor
22436aabfffSSteven Rostedt (Red Hat) * @c: simple character to record
22536aabfffSSteven Rostedt (Red Hat) *
22636aabfffSSteven Rostedt (Red Hat) * The tracer may use either the sequence operations or its own
227f2cc020dSIngo Molnar * copy to user routines. This function records a simple character
22836aabfffSSteven Rostedt (Red Hat) * into a special buffer (@s) for later retrieval by a sequencer
22936aabfffSSteven Rostedt (Red Hat) * or other mechanism.
23036aabfffSSteven Rostedt (Red Hat) */
trace_seq_putc(struct trace_seq * s,unsigned char c)231dba39448SSteven Rostedt (Red Hat) void trace_seq_putc(struct trace_seq *s, unsigned char c)
23212306276SSteven Rostedt (Red Hat) {
23312306276SSteven Rostedt (Red Hat) if (s->full)
234dba39448SSteven Rostedt (Red Hat) return;
23512306276SSteven Rostedt (Red Hat)
2363a161d99SSteven Rostedt (Red Hat) __trace_seq_init(s);
2373a161d99SSteven Rostedt (Red Hat)
23836aabfffSSteven Rostedt (Red Hat) if (TRACE_SEQ_BUF_LEFT(s) < 1) {
23912306276SSteven Rostedt (Red Hat) s->full = 1;
240dba39448SSteven Rostedt (Red Hat) return;
24112306276SSteven Rostedt (Red Hat) }
24212306276SSteven Rostedt (Red Hat)
2433a161d99SSteven Rostedt (Red Hat) seq_buf_putc(&s->seq, c);
24412306276SSteven Rostedt (Red Hat) }
24536aabfffSSteven Rostedt (Red Hat) EXPORT_SYMBOL_GPL(trace_seq_putc);
24612306276SSteven Rostedt (Red Hat)
24736aabfffSSteven Rostedt (Red Hat) /**
24836aabfffSSteven Rostedt (Red Hat) * trace_seq_putmem - write raw data into the trace_seq buffer
24936aabfffSSteven Rostedt (Red Hat) * @s: trace sequence descriptor
25036aabfffSSteven Rostedt (Red Hat) * @mem: The raw memory to copy into the buffer
25136aabfffSSteven Rostedt (Red Hat) * @len: The length of the raw memory to copy (in bytes)
25236aabfffSSteven Rostedt (Red Hat) *
25336aabfffSSteven Rostedt (Red Hat) * There may be cases where raw memory needs to be written into the
25436aabfffSSteven Rostedt (Red Hat) * buffer and a strcpy() would not work. Using this function allows
25536aabfffSSteven Rostedt (Red Hat) * for such cases.
25636aabfffSSteven Rostedt (Red Hat) */
trace_seq_putmem(struct trace_seq * s,const void * mem,unsigned int len)257dba39448SSteven Rostedt (Red Hat) void trace_seq_putmem(struct trace_seq *s, const void *mem, unsigned int len)
25812306276SSteven Rostedt (Red Hat) {
25912306276SSteven Rostedt (Red Hat) if (s->full)
260dba39448SSteven Rostedt (Red Hat) return;
26112306276SSteven Rostedt (Red Hat)
2623a161d99SSteven Rostedt (Red Hat) __trace_seq_init(s);
2633a161d99SSteven Rostedt (Red Hat)
26436aabfffSSteven Rostedt (Red Hat) if (len > TRACE_SEQ_BUF_LEFT(s)) {
26512306276SSteven Rostedt (Red Hat) s->full = 1;
266dba39448SSteven Rostedt (Red Hat) return;
26712306276SSteven Rostedt (Red Hat) }
26812306276SSteven Rostedt (Red Hat)
2693a161d99SSteven Rostedt (Red Hat) seq_buf_putmem(&s->seq, mem, len);
27012306276SSteven Rostedt (Red Hat) }
27136aabfffSSteven Rostedt (Red Hat) EXPORT_SYMBOL_GPL(trace_seq_putmem);
27212306276SSteven Rostedt (Red Hat)
27336aabfffSSteven Rostedt (Red Hat) /**
27436aabfffSSteven Rostedt (Red Hat) * trace_seq_putmem_hex - write raw memory into the buffer in ASCII hex
27536aabfffSSteven Rostedt (Red Hat) * @s: trace sequence descriptor
27636aabfffSSteven Rostedt (Red Hat) * @mem: The raw memory to write its hex ASCII representation of
27736aabfffSSteven Rostedt (Red Hat) * @len: The length of the raw memory to copy (in bytes)
27836aabfffSSteven Rostedt (Red Hat) *
27936aabfffSSteven Rostedt (Red Hat) * This is similar to trace_seq_putmem() except instead of just copying the
28036aabfffSSteven Rostedt (Red Hat) * raw memory into the buffer it writes its ASCII representation of it
28136aabfffSSteven Rostedt (Red Hat) * in hex characters.
28236aabfffSSteven Rostedt (Red Hat) */
trace_seq_putmem_hex(struct trace_seq * s,const void * mem,unsigned int len)283dba39448SSteven Rostedt (Red Hat) void trace_seq_putmem_hex(struct trace_seq *s, const void *mem,
28436aabfffSSteven Rostedt (Red Hat) unsigned int len)
28512306276SSteven Rostedt (Red Hat) {
2863a161d99SSteven Rostedt (Red Hat) unsigned int save_len = s->seq.len;
28712306276SSteven Rostedt (Red Hat)
28812306276SSteven Rostedt (Red Hat) if (s->full)
289dba39448SSteven Rostedt (Red Hat) return;
29012306276SSteven Rostedt (Red Hat)
2913a161d99SSteven Rostedt (Red Hat) __trace_seq_init(s);
2923a161d99SSteven Rostedt (Red Hat)
2933a161d99SSteven Rostedt (Red Hat) /* Each byte is represented by two chars */
2943a161d99SSteven Rostedt (Red Hat) if (len * 2 > TRACE_SEQ_BUF_LEFT(s)) {
2953a161d99SSteven Rostedt (Red Hat) s->full = 1;
2963a161d99SSteven Rostedt (Red Hat) return;
29712306276SSteven Rostedt (Red Hat) }
2986d2289f3SSteven Rostedt (Red Hat)
2993a161d99SSteven Rostedt (Red Hat) /* The added spaces can still cause an overflow */
3003a161d99SSteven Rostedt (Red Hat) seq_buf_putmem_hex(&s->seq, mem, len);
30112306276SSteven Rostedt (Red Hat)
3023a161d99SSteven Rostedt (Red Hat) if (unlikely(seq_buf_has_overflowed(&s->seq))) {
3033a161d99SSteven Rostedt (Red Hat) s->seq.len = save_len;
3043a161d99SSteven Rostedt (Red Hat) s->full = 1;
3053a161d99SSteven Rostedt (Red Hat) return;
3066d2289f3SSteven Rostedt (Red Hat) }
30712306276SSteven Rostedt (Red Hat) }
30836aabfffSSteven Rostedt (Red Hat) EXPORT_SYMBOL_GPL(trace_seq_putmem_hex);
30912306276SSteven Rostedt (Red Hat)
31036aabfffSSteven Rostedt (Red Hat) /**
31136aabfffSSteven Rostedt (Red Hat) * trace_seq_path - copy a path into the sequence buffer
31236aabfffSSteven Rostedt (Red Hat) * @s: trace sequence descriptor
31336aabfffSSteven Rostedt (Red Hat) * @path: path to write into the sequence buffer.
31436aabfffSSteven Rostedt (Red Hat) *
31536aabfffSSteven Rostedt (Red Hat) * Write a path name into the sequence buffer.
31636aabfffSSteven Rostedt (Red Hat) *
31736aabfffSSteven Rostedt (Red Hat) * Returns 1 if we successfully written all the contents to
31836aabfffSSteven Rostedt (Red Hat) * the buffer.
31936aabfffSSteven Rostedt (Red Hat) * Returns 0 if we the length to write is bigger than the
32036aabfffSSteven Rostedt (Red Hat) * reserved buffer space. In this case, nothing gets written.
32136aabfffSSteven Rostedt (Red Hat) */
trace_seq_path(struct trace_seq * s,const struct path * path)32212306276SSteven Rostedt (Red Hat) int trace_seq_path(struct trace_seq *s, const struct path *path)
32312306276SSteven Rostedt (Red Hat) {
3243a161d99SSteven Rostedt (Red Hat) unsigned int save_len = s->seq.len;
32512306276SSteven Rostedt (Red Hat)
32612306276SSteven Rostedt (Red Hat) if (s->full)
32712306276SSteven Rostedt (Red Hat) return 0;
32812306276SSteven Rostedt (Red Hat)
3293a161d99SSteven Rostedt (Red Hat) __trace_seq_init(s);
3303a161d99SSteven Rostedt (Red Hat)
33136aabfffSSteven Rostedt (Red Hat) if (TRACE_SEQ_BUF_LEFT(s) < 1) {
33212306276SSteven Rostedt (Red Hat) s->full = 1;
33312306276SSteven Rostedt (Red Hat) return 0;
33412306276SSteven Rostedt (Red Hat) }
33512306276SSteven Rostedt (Red Hat)
336dd23180aSSteven Rostedt (Red Hat) seq_buf_path(&s->seq, path, "\n");
33712306276SSteven Rostedt (Red Hat)
3383a161d99SSteven Rostedt (Red Hat) if (unlikely(seq_buf_has_overflowed(&s->seq))) {
3393a161d99SSteven Rostedt (Red Hat) s->seq.len = save_len;
34012306276SSteven Rostedt (Red Hat) s->full = 1;
34112306276SSteven Rostedt (Red Hat) return 0;
34212306276SSteven Rostedt (Red Hat) }
3433a161d99SSteven Rostedt (Red Hat)
344dd23180aSSteven Rostedt (Red Hat) return 1;
3453a161d99SSteven Rostedt (Red Hat) }
34636aabfffSSteven Rostedt (Red Hat) EXPORT_SYMBOL_GPL(trace_seq_path);
34712306276SSteven Rostedt (Red Hat)
34836aabfffSSteven Rostedt (Red Hat) /**
349f2cc020dSIngo Molnar * trace_seq_to_user - copy the sequence buffer to user space
35036aabfffSSteven Rostedt (Red Hat) * @s: trace sequence descriptor
35136aabfffSSteven Rostedt (Red Hat) * @ubuf: The userspace memory location to copy to
35236aabfffSSteven Rostedt (Red Hat) * @cnt: The amount to copy
35336aabfffSSteven Rostedt (Red Hat) *
35436aabfffSSteven Rostedt (Red Hat) * Copies the sequence buffer into the userspace memory pointed to
35536aabfffSSteven Rostedt (Red Hat) * by @ubuf. It starts from the last read position (@s->readpos)
35636aabfffSSteven Rostedt (Red Hat) * and writes up to @cnt characters or till it reaches the end of
35736aabfffSSteven Rostedt (Red Hat) * the content in the buffer (@s->len), which ever comes first.
35836aabfffSSteven Rostedt (Red Hat) *
35936aabfffSSteven Rostedt (Red Hat) * On success, it returns a positive number of the number of bytes
36036aabfffSSteven Rostedt (Red Hat) * it copied.
36136aabfffSSteven Rostedt (Red Hat) *
36236aabfffSSteven Rostedt (Red Hat) * On failure it returns -EBUSY if all of the content in the
36336aabfffSSteven Rostedt (Red Hat) * sequence has been already read, which includes nothing in the
364f2cc020dSIngo Molnar * sequence (@s->len == @s->readpos).
36536aabfffSSteven Rostedt (Red Hat) *
36636aabfffSSteven Rostedt (Red Hat) * Returns -EFAULT if the copy to userspace fails.
36736aabfffSSteven Rostedt (Red Hat) */
trace_seq_to_user(struct trace_seq * s,char __user * ubuf,int cnt)36836aabfffSSteven Rostedt (Red Hat) int trace_seq_to_user(struct trace_seq *s, char __user *ubuf, int cnt)
36912306276SSteven Rostedt (Red Hat) {
370*d0ed46b6SMatthew Wilcox (Oracle) int ret;
3713a161d99SSteven Rostedt (Red Hat) __trace_seq_init(s);
372*d0ed46b6SMatthew Wilcox (Oracle) ret = seq_buf_to_user(&s->seq, ubuf, s->readpos, cnt);
373*d0ed46b6SMatthew Wilcox (Oracle) if (ret > 0)
374*d0ed46b6SMatthew Wilcox (Oracle) s->readpos += ret;
375*d0ed46b6SMatthew Wilcox (Oracle) return ret;
37612306276SSteven Rostedt (Red Hat) }
37736aabfffSSteven Rostedt (Red Hat) EXPORT_SYMBOL_GPL(trace_seq_to_user);
378ef56e047SPiotr 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)379ef56e047SPiotr Maziarz int trace_seq_hex_dump(struct trace_seq *s, const char *prefix_str,
380ef56e047SPiotr Maziarz int prefix_type, int rowsize, int groupsize,
381ef56e047SPiotr Maziarz const void *buf, size_t len, bool ascii)
382ef56e047SPiotr Maziarz {
383ef56e047SPiotr Maziarz unsigned int save_len = s->seq.len;
384ef56e047SPiotr Maziarz
385ef56e047SPiotr Maziarz if (s->full)
386ef56e047SPiotr Maziarz return 0;
387ef56e047SPiotr Maziarz
388ef56e047SPiotr Maziarz __trace_seq_init(s);
389ef56e047SPiotr Maziarz
390ef56e047SPiotr Maziarz if (TRACE_SEQ_BUF_LEFT(s) < 1) {
391ef56e047SPiotr Maziarz s->full = 1;
392ef56e047SPiotr Maziarz return 0;
393ef56e047SPiotr Maziarz }
394ef56e047SPiotr Maziarz
395ef56e047SPiotr Maziarz seq_buf_hex_dump(&(s->seq), prefix_str,
396ef56e047SPiotr Maziarz prefix_type, rowsize, groupsize,
397ef56e047SPiotr Maziarz buf, len, ascii);
398ef56e047SPiotr Maziarz
399ef56e047SPiotr Maziarz if (unlikely(seq_buf_has_overflowed(&s->seq))) {
400ef56e047SPiotr Maziarz s->seq.len = save_len;
401ef56e047SPiotr Maziarz s->full = 1;
402ef56e047SPiotr Maziarz return 0;
403ef56e047SPiotr Maziarz }
404ef56e047SPiotr Maziarz
405ef56e047SPiotr Maziarz return 1;
406ef56e047SPiotr Maziarz }
407ef56e047SPiotr Maziarz EXPORT_SYMBOL(trace_seq_hex_dump);
408a9c4bdd5SLinyu Yuan
409a9c4bdd5SLinyu Yuan /*
410a9c4bdd5SLinyu Yuan * trace_seq_acquire - acquire seq buffer with size len
411a9c4bdd5SLinyu Yuan * @s: trace sequence descriptor
412a9c4bdd5SLinyu Yuan * @len: size of buffer to be acquired
413a9c4bdd5SLinyu Yuan *
414a9c4bdd5SLinyu Yuan * acquire buffer with size of @len from trace_seq for output usage,
415a9c4bdd5SLinyu Yuan * user can fill string into that buffer.
416a9c4bdd5SLinyu Yuan *
417a9c4bdd5SLinyu Yuan * Returns start address of acquired buffer.
418a9c4bdd5SLinyu Yuan *
419a9c4bdd5SLinyu Yuan * it allow multiple usage in one trace output function call.
420a9c4bdd5SLinyu Yuan */
trace_seq_acquire(struct trace_seq * s,unsigned int len)421a9c4bdd5SLinyu Yuan char *trace_seq_acquire(struct trace_seq *s, unsigned int len)
422a9c4bdd5SLinyu Yuan {
423a9c4bdd5SLinyu Yuan char *ret = trace_seq_buffer_ptr(s);
424a9c4bdd5SLinyu Yuan
425a9c4bdd5SLinyu Yuan if (!WARN_ON_ONCE(seq_buf_buffer_left(&s->seq) < len))
426a9c4bdd5SLinyu Yuan seq_buf_commit(&s->seq, len);
427a9c4bdd5SLinyu Yuan
428a9c4bdd5SLinyu Yuan return ret;
429a9c4bdd5SLinyu Yuan }
430a9c4bdd5SLinyu Yuan EXPORT_SYMBOL(trace_seq_acquire);
431