Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * trace_seq.c
0004  *
0005  * Copyright (C) 2008-2014 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
0006  *
0007  * The trace_seq is a handy tool that allows you to pass a descriptor around
0008  * to a buffer that other functions can write to. It is similar to the
0009  * seq_file functionality but has some differences.
0010  *
0011  * To use it, the trace_seq must be initialized with trace_seq_init().
0012  * This will set up the counters within the descriptor. You can call
0013  * trace_seq_init() more than once to reset the trace_seq to start
0014  * from scratch.
0015  * 
0016  * The buffer size is currently PAGE_SIZE, although it may become dynamic
0017  * in the future.
0018  *
0019  * A write to the buffer will either succeed or fail. That is, unlike
0020  * sprintf() there will not be a partial write (well it may write into
0021  * the buffer but it wont update the pointers). This allows users to
0022  * try to write something into the trace_seq buffer and if it fails
0023  * they can flush it and try again.
0024  *
0025  */
0026 #include <linux/uaccess.h>
0027 #include <linux/seq_file.h>
0028 #include <linux/trace_seq.h>
0029 
0030 /* How much buffer is left on the trace_seq? */
0031 #define TRACE_SEQ_BUF_LEFT(s) seq_buf_buffer_left(&(s)->seq)
0032 
0033 /*
0034  * trace_seq should work with being initialized with 0s.
0035  */
0036 static inline void __trace_seq_init(struct trace_seq *s)
0037 {
0038     if (unlikely(!s->seq.size))
0039         trace_seq_init(s);
0040 }
0041 
0042 /**
0043  * trace_print_seq - move the contents of trace_seq into a seq_file
0044  * @m: the seq_file descriptor that is the destination
0045  * @s: the trace_seq descriptor that is the source.
0046  *
0047  * Returns 0 on success and non zero on error. If it succeeds to
0048  * write to the seq_file it will reset the trace_seq, otherwise
0049  * it does not modify the trace_seq to let the caller try again.
0050  */
0051 int trace_print_seq(struct seq_file *m, struct trace_seq *s)
0052 {
0053     int ret;
0054 
0055     __trace_seq_init(s);
0056 
0057     ret = seq_buf_print_seq(m, &s->seq);
0058 
0059     /*
0060      * Only reset this buffer if we successfully wrote to the
0061      * seq_file buffer. This lets the caller try again or
0062      * do something else with the contents.
0063      */
0064     if (!ret)
0065         trace_seq_init(s);
0066 
0067     return ret;
0068 }
0069 
0070 /**
0071  * trace_seq_printf - sequence printing of trace information
0072  * @s: trace sequence descriptor
0073  * @fmt: printf format string
0074  *
0075  * The tracer may use either sequence operations or its own
0076  * copy to user routines. To simplify formatting of a trace
0077  * trace_seq_printf() is used to store strings into a special
0078  * buffer (@s). Then the output may be either used by
0079  * the sequencer or pulled into another buffer.
0080  */
0081 void trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
0082 {
0083     unsigned int save_len = s->seq.len;
0084     va_list ap;
0085 
0086     if (s->full)
0087         return;
0088 
0089     __trace_seq_init(s);
0090 
0091     va_start(ap, fmt);
0092     seq_buf_vprintf(&s->seq, fmt, ap);
0093     va_end(ap);
0094 
0095     /* If we can't write it all, don't bother writing anything */
0096     if (unlikely(seq_buf_has_overflowed(&s->seq))) {
0097         s->seq.len = save_len;
0098         s->full = 1;
0099     }
0100 }
0101 EXPORT_SYMBOL_GPL(trace_seq_printf);
0102 
0103 /**
0104  * trace_seq_bitmask - write a bitmask array in its ASCII representation
0105  * @s:      trace sequence descriptor
0106  * @maskp:  points to an array of unsigned longs that represent a bitmask
0107  * @nmaskbits:  The number of bits that are valid in @maskp
0108  *
0109  * Writes a ASCII representation of a bitmask string into @s.
0110  */
0111 void trace_seq_bitmask(struct trace_seq *s, const unsigned long *maskp,
0112               int nmaskbits)
0113 {
0114     unsigned int save_len = s->seq.len;
0115 
0116     if (s->full)
0117         return;
0118 
0119     __trace_seq_init(s);
0120 
0121     seq_buf_printf(&s->seq, "%*pb", nmaskbits, maskp);
0122 
0123     if (unlikely(seq_buf_has_overflowed(&s->seq))) {
0124         s->seq.len = save_len;
0125         s->full = 1;
0126     }
0127 }
0128 EXPORT_SYMBOL_GPL(trace_seq_bitmask);
0129 
0130 /**
0131  * trace_seq_vprintf - sequence printing of trace information
0132  * @s: trace sequence descriptor
0133  * @fmt: printf format string
0134  *
0135  * The tracer may use either sequence operations or its own
0136  * copy to user routines. To simplify formatting of a trace
0137  * trace_seq_printf is used to store strings into a special
0138  * buffer (@s). Then the output may be either used by
0139  * the sequencer or pulled into another buffer.
0140  */
0141 void trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
0142 {
0143     unsigned int save_len = s->seq.len;
0144 
0145     if (s->full)
0146         return;
0147 
0148     __trace_seq_init(s);
0149 
0150     seq_buf_vprintf(&s->seq, fmt, args);
0151 
0152     /* If we can't write it all, don't bother writing anything */
0153     if (unlikely(seq_buf_has_overflowed(&s->seq))) {
0154         s->seq.len = save_len;
0155         s->full = 1;
0156     }
0157 }
0158 EXPORT_SYMBOL_GPL(trace_seq_vprintf);
0159 
0160 /**
0161  * trace_seq_bprintf - Write the printf string from binary arguments
0162  * @s: trace sequence descriptor
0163  * @fmt: The format string for the @binary arguments
0164  * @binary: The binary arguments for @fmt.
0165  *
0166  * When recording in a fast path, a printf may be recorded with just
0167  * saving the format and the arguments as they were passed to the
0168  * function, instead of wasting cycles converting the arguments into
0169  * ASCII characters. Instead, the arguments are saved in a 32 bit
0170  * word array that is defined by the format string constraints.
0171  *
0172  * This function will take the format and the binary array and finish
0173  * the conversion into the ASCII string within the buffer.
0174  */
0175 void trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary)
0176 {
0177     unsigned int save_len = s->seq.len;
0178 
0179     if (s->full)
0180         return;
0181 
0182     __trace_seq_init(s);
0183 
0184     seq_buf_bprintf(&s->seq, fmt, binary);
0185 
0186     /* If we can't write it all, don't bother writing anything */
0187     if (unlikely(seq_buf_has_overflowed(&s->seq))) {
0188         s->seq.len = save_len;
0189         s->full = 1;
0190         return;
0191     }
0192 }
0193 EXPORT_SYMBOL_GPL(trace_seq_bprintf);
0194 
0195 /**
0196  * trace_seq_puts - trace sequence printing of simple string
0197  * @s: trace sequence descriptor
0198  * @str: simple string to record
0199  *
0200  * The tracer may use either the sequence operations or its own
0201  * copy to user routines. This function records a simple string
0202  * into a special buffer (@s) for later retrieval by a sequencer
0203  * or other mechanism.
0204  */
0205 void trace_seq_puts(struct trace_seq *s, const char *str)
0206 {
0207     unsigned int len = strlen(str);
0208 
0209     if (s->full)
0210         return;
0211 
0212     __trace_seq_init(s);
0213 
0214     if (len > TRACE_SEQ_BUF_LEFT(s)) {
0215         s->full = 1;
0216         return;
0217     }
0218 
0219     seq_buf_putmem(&s->seq, str, len);
0220 }
0221 EXPORT_SYMBOL_GPL(trace_seq_puts);
0222 
0223 /**
0224  * trace_seq_putc - trace sequence printing of simple character
0225  * @s: trace sequence descriptor
0226  * @c: simple character to record
0227  *
0228  * The tracer may use either the sequence operations or its own
0229  * copy to user routines. This function records a simple character
0230  * into a special buffer (@s) for later retrieval by a sequencer
0231  * or other mechanism.
0232  */
0233 void trace_seq_putc(struct trace_seq *s, unsigned char c)
0234 {
0235     if (s->full)
0236         return;
0237 
0238     __trace_seq_init(s);
0239 
0240     if (TRACE_SEQ_BUF_LEFT(s) < 1) {
0241         s->full = 1;
0242         return;
0243     }
0244 
0245     seq_buf_putc(&s->seq, c);
0246 }
0247 EXPORT_SYMBOL_GPL(trace_seq_putc);
0248 
0249 /**
0250  * trace_seq_putmem - write raw data into the trace_seq buffer
0251  * @s: trace sequence descriptor
0252  * @mem: The raw memory to copy into the buffer
0253  * @len: The length of the raw memory to copy (in bytes)
0254  *
0255  * There may be cases where raw memory needs to be written into the
0256  * buffer and a strcpy() would not work. Using this function allows
0257  * for such cases.
0258  */
0259 void trace_seq_putmem(struct trace_seq *s, const void *mem, unsigned int len)
0260 {
0261     if (s->full)
0262         return;
0263 
0264     __trace_seq_init(s);
0265 
0266     if (len > TRACE_SEQ_BUF_LEFT(s)) {
0267         s->full = 1;
0268         return;
0269     }
0270 
0271     seq_buf_putmem(&s->seq, mem, len);
0272 }
0273 EXPORT_SYMBOL_GPL(trace_seq_putmem);
0274 
0275 /**
0276  * trace_seq_putmem_hex - write raw memory into the buffer in ASCII hex
0277  * @s: trace sequence descriptor
0278  * @mem: The raw memory to write its hex ASCII representation of
0279  * @len: The length of the raw memory to copy (in bytes)
0280  *
0281  * This is similar to trace_seq_putmem() except instead of just copying the
0282  * raw memory into the buffer it writes its ASCII representation of it
0283  * in hex characters.
0284  */
0285 void trace_seq_putmem_hex(struct trace_seq *s, const void *mem,
0286              unsigned int len)
0287 {
0288     unsigned int save_len = s->seq.len;
0289 
0290     if (s->full)
0291         return;
0292 
0293     __trace_seq_init(s);
0294 
0295     /* Each byte is represented by two chars */
0296     if (len * 2 > TRACE_SEQ_BUF_LEFT(s)) {
0297         s->full = 1;
0298         return;
0299     }
0300 
0301     /* The added spaces can still cause an overflow */
0302     seq_buf_putmem_hex(&s->seq, mem, len);
0303 
0304     if (unlikely(seq_buf_has_overflowed(&s->seq))) {
0305         s->seq.len = save_len;
0306         s->full = 1;
0307         return;
0308     }
0309 }
0310 EXPORT_SYMBOL_GPL(trace_seq_putmem_hex);
0311 
0312 /**
0313  * trace_seq_path - copy a path into the sequence buffer
0314  * @s: trace sequence descriptor
0315  * @path: path to write into the sequence buffer.
0316  *
0317  * Write a path name into the sequence buffer.
0318  *
0319  * Returns 1 if we successfully written all the contents to
0320  *   the buffer.
0321  * Returns 0 if we the length to write is bigger than the
0322  *   reserved buffer space. In this case, nothing gets written.
0323  */
0324 int trace_seq_path(struct trace_seq *s, const struct path *path)
0325 {
0326     unsigned int save_len = s->seq.len;
0327 
0328     if (s->full)
0329         return 0;
0330 
0331     __trace_seq_init(s);
0332 
0333     if (TRACE_SEQ_BUF_LEFT(s) < 1) {
0334         s->full = 1;
0335         return 0;
0336     }
0337 
0338     seq_buf_path(&s->seq, path, "\n");
0339 
0340     if (unlikely(seq_buf_has_overflowed(&s->seq))) {
0341         s->seq.len = save_len;
0342         s->full = 1;
0343         return 0;
0344     }
0345 
0346     return 1;
0347 }
0348 EXPORT_SYMBOL_GPL(trace_seq_path);
0349 
0350 /**
0351  * trace_seq_to_user - copy the sequence buffer to user space
0352  * @s: trace sequence descriptor
0353  * @ubuf: The userspace memory location to copy to
0354  * @cnt: The amount to copy
0355  *
0356  * Copies the sequence buffer into the userspace memory pointed to
0357  * by @ubuf. It starts from the last read position (@s->readpos)
0358  * and writes up to @cnt characters or till it reaches the end of
0359  * the content in the buffer (@s->len), which ever comes first.
0360  *
0361  * On success, it returns a positive number of the number of bytes
0362  * it copied.
0363  *
0364  * On failure it returns -EBUSY if all of the content in the
0365  * sequence has been already read, which includes nothing in the
0366  * sequence (@s->len == @s->readpos).
0367  *
0368  * Returns -EFAULT if the copy to userspace fails.
0369  */
0370 int trace_seq_to_user(struct trace_seq *s, char __user *ubuf, int cnt)
0371 {
0372     __trace_seq_init(s);
0373     return seq_buf_to_user(&s->seq, ubuf, cnt);
0374 }
0375 EXPORT_SYMBOL_GPL(trace_seq_to_user);
0376 
0377 int trace_seq_hex_dump(struct trace_seq *s, const char *prefix_str,
0378                int prefix_type, int rowsize, int groupsize,
0379                const void *buf, size_t len, bool ascii)
0380 {
0381     unsigned int save_len = s->seq.len;
0382 
0383     if (s->full)
0384         return 0;
0385 
0386     __trace_seq_init(s);
0387 
0388     if (TRACE_SEQ_BUF_LEFT(s) < 1) {
0389         s->full = 1;
0390         return 0;
0391     }
0392 
0393     seq_buf_hex_dump(&(s->seq), prefix_str,
0394            prefix_type, rowsize, groupsize,
0395            buf, len, ascii);
0396 
0397     if (unlikely(seq_buf_has_overflowed(&s->seq))) {
0398         s->seq.len = save_len;
0399         s->full = 1;
0400         return 0;
0401     }
0402 
0403     return 1;
0404 }
0405 EXPORT_SYMBOL(trace_seq_hex_dump);