1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun #ifndef _LINUX_TRACE_SEQ_H
3*4882a593Smuzhiyun #define _LINUX_TRACE_SEQ_H
4*4882a593Smuzhiyun
5*4882a593Smuzhiyun #include <linux/seq_buf.h>
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun #include <asm/page.h>
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun /*
10*4882a593Smuzhiyun * Trace sequences are used to allow a function to call several other functions
11*4882a593Smuzhiyun * to create a string of data to use (up to a max of PAGE_SIZE).
12*4882a593Smuzhiyun */
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun struct trace_seq {
15*4882a593Smuzhiyun char buffer[PAGE_SIZE];
16*4882a593Smuzhiyun struct seq_buf seq;
17*4882a593Smuzhiyun int full;
18*4882a593Smuzhiyun };
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun static inline void
trace_seq_init(struct trace_seq * s)21*4882a593Smuzhiyun trace_seq_init(struct trace_seq *s)
22*4882a593Smuzhiyun {
23*4882a593Smuzhiyun seq_buf_init(&s->seq, s->buffer, PAGE_SIZE);
24*4882a593Smuzhiyun s->full = 0;
25*4882a593Smuzhiyun }
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun /**
28*4882a593Smuzhiyun * trace_seq_used - amount of actual data written to buffer
29*4882a593Smuzhiyun * @s: trace sequence descriptor
30*4882a593Smuzhiyun *
31*4882a593Smuzhiyun * Returns the amount of data written to the buffer.
32*4882a593Smuzhiyun *
33*4882a593Smuzhiyun * IMPORTANT!
34*4882a593Smuzhiyun *
35*4882a593Smuzhiyun * Use this instead of @s->seq.len if you need to pass the amount
36*4882a593Smuzhiyun * of data from the buffer to another buffer (userspace, or what not).
37*4882a593Smuzhiyun * The @s->seq.len on overflow is bigger than the buffer size and
38*4882a593Smuzhiyun * using it can cause access to undefined memory.
39*4882a593Smuzhiyun */
trace_seq_used(struct trace_seq * s)40*4882a593Smuzhiyun static inline int trace_seq_used(struct trace_seq *s)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun return seq_buf_used(&s->seq);
43*4882a593Smuzhiyun }
44*4882a593Smuzhiyun
45*4882a593Smuzhiyun /**
46*4882a593Smuzhiyun * trace_seq_buffer_ptr - return pointer to next location in buffer
47*4882a593Smuzhiyun * @s: trace sequence descriptor
48*4882a593Smuzhiyun *
49*4882a593Smuzhiyun * Returns the pointer to the buffer where the next write to
50*4882a593Smuzhiyun * the buffer will happen. This is useful to save the location
51*4882a593Smuzhiyun * that is about to be written to and then return the result
52*4882a593Smuzhiyun * of that write.
53*4882a593Smuzhiyun */
54*4882a593Smuzhiyun static inline char *
trace_seq_buffer_ptr(struct trace_seq * s)55*4882a593Smuzhiyun trace_seq_buffer_ptr(struct trace_seq *s)
56*4882a593Smuzhiyun {
57*4882a593Smuzhiyun return s->buffer + seq_buf_used(&s->seq);
58*4882a593Smuzhiyun }
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun /**
61*4882a593Smuzhiyun * trace_seq_has_overflowed - return true if the trace_seq took too much
62*4882a593Smuzhiyun * @s: trace sequence descriptor
63*4882a593Smuzhiyun *
64*4882a593Smuzhiyun * Returns true if too much data was added to the trace_seq and it is
65*4882a593Smuzhiyun * now full and will not take anymore.
66*4882a593Smuzhiyun */
trace_seq_has_overflowed(struct trace_seq * s)67*4882a593Smuzhiyun static inline bool trace_seq_has_overflowed(struct trace_seq *s)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun return s->full || seq_buf_has_overflowed(&s->seq);
70*4882a593Smuzhiyun }
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun /*
73*4882a593Smuzhiyun * Currently only defined when tracing is enabled.
74*4882a593Smuzhiyun */
75*4882a593Smuzhiyun #ifdef CONFIG_TRACING
76*4882a593Smuzhiyun extern __printf(2, 3)
77*4882a593Smuzhiyun void trace_seq_printf(struct trace_seq *s, const char *fmt, ...);
78*4882a593Smuzhiyun extern __printf(2, 0)
79*4882a593Smuzhiyun void trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args);
80*4882a593Smuzhiyun extern void
81*4882a593Smuzhiyun trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary);
82*4882a593Smuzhiyun extern int trace_print_seq(struct seq_file *m, struct trace_seq *s);
83*4882a593Smuzhiyun extern int trace_seq_to_user(struct trace_seq *s, char __user *ubuf,
84*4882a593Smuzhiyun int cnt);
85*4882a593Smuzhiyun extern void trace_seq_puts(struct trace_seq *s, const char *str);
86*4882a593Smuzhiyun extern void trace_seq_putc(struct trace_seq *s, unsigned char c);
87*4882a593Smuzhiyun extern void trace_seq_putmem(struct trace_seq *s, const void *mem, unsigned int len);
88*4882a593Smuzhiyun extern void trace_seq_putmem_hex(struct trace_seq *s, const void *mem,
89*4882a593Smuzhiyun unsigned int len);
90*4882a593Smuzhiyun extern int trace_seq_path(struct trace_seq *s, const struct path *path);
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun extern void trace_seq_bitmask(struct trace_seq *s, const unsigned long *maskp,
93*4882a593Smuzhiyun int nmaskbits);
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun extern int trace_seq_hex_dump(struct trace_seq *s, const char *prefix_str,
96*4882a593Smuzhiyun int prefix_type, int rowsize, int groupsize,
97*4882a593Smuzhiyun const void *buf, size_t len, bool ascii);
98*4882a593Smuzhiyun
99*4882a593Smuzhiyun #else /* CONFIG_TRACING */
trace_seq_printf(struct trace_seq * s,const char * fmt,...)100*4882a593Smuzhiyun static inline void trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun static inline void
trace_seq_bprintf(struct trace_seq * s,const char * fmt,const u32 * binary)104*4882a593Smuzhiyun trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun static inline void
trace_seq_bitmask(struct trace_seq * s,const unsigned long * maskp,int nmaskbits)109*4882a593Smuzhiyun trace_seq_bitmask(struct trace_seq *s, const unsigned long *maskp,
110*4882a593Smuzhiyun int nmaskbits)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun }
113*4882a593Smuzhiyun
trace_print_seq(struct seq_file * m,struct trace_seq * s)114*4882a593Smuzhiyun static inline int trace_print_seq(struct seq_file *m, struct trace_seq *s)
115*4882a593Smuzhiyun {
116*4882a593Smuzhiyun return 0;
117*4882a593Smuzhiyun }
trace_seq_to_user(struct trace_seq * s,char __user * ubuf,int cnt)118*4882a593Smuzhiyun static inline int trace_seq_to_user(struct trace_seq *s, char __user *ubuf,
119*4882a593Smuzhiyun int cnt)
120*4882a593Smuzhiyun {
121*4882a593Smuzhiyun return 0;
122*4882a593Smuzhiyun }
trace_seq_puts(struct trace_seq * s,const char * str)123*4882a593Smuzhiyun static inline void trace_seq_puts(struct trace_seq *s, const char *str)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun }
trace_seq_putc(struct trace_seq * s,unsigned char c)126*4882a593Smuzhiyun static inline void trace_seq_putc(struct trace_seq *s, unsigned char c)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun static inline void
trace_seq_putmem(struct trace_seq * s,const void * mem,unsigned int len)130*4882a593Smuzhiyun trace_seq_putmem(struct trace_seq *s, const void *mem, unsigned int len)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun }
trace_seq_putmem_hex(struct trace_seq * s,const void * mem,unsigned int len)133*4882a593Smuzhiyun static inline void trace_seq_putmem_hex(struct trace_seq *s, const void *mem,
134*4882a593Smuzhiyun unsigned int len)
135*4882a593Smuzhiyun {
136*4882a593Smuzhiyun }
trace_seq_path(struct trace_seq * s,const struct path * path)137*4882a593Smuzhiyun static inline int trace_seq_path(struct trace_seq *s, const struct path *path)
138*4882a593Smuzhiyun {
139*4882a593Smuzhiyun return 0;
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun #endif /* CONFIG_TRACING */
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun #endif /* _LINUX_TRACE_SEQ_H */
144