LCOV - code coverage report
Current view: top level - kernel/trace - trace_seq.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 0 108 0.0 %
Date: 2021-04-22 12:43:58 Functions: 0 12 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * trace_seq.c
       4             :  *
       5             :  * Copyright (C) 2008-2014 Red Hat Inc, Steven Rostedt <srostedt@redhat.com>
       6             :  *
       7             :  * The trace_seq is a handy tool that allows you to pass a descriptor around
       8             :  * to a buffer that other functions can write to. It is similar to the
       9             :  * seq_file functionality but has some differences.
      10             :  *
      11             :  * To use it, the trace_seq must be initialized with trace_seq_init().
      12             :  * This will set up the counters within the descriptor. You can call
      13             :  * trace_seq_init() more than once to reset the trace_seq to start
      14             :  * from scratch.
      15             :  * 
      16             :  * The buffer size is currently PAGE_SIZE, although it may become dynamic
      17             :  * in the future.
      18             :  *
      19             :  * A write to the buffer will either succed or fail. That is, unlike
      20             :  * sprintf() there will not be a partial write (well it may write into
      21             :  * the buffer but it wont update the pointers). This allows users to
      22             :  * try to write something into the trace_seq buffer and if it fails
      23             :  * they can flush it and try again.
      24             :  *
      25             :  */
      26             : #include <linux/uaccess.h>
      27             : #include <linux/seq_file.h>
      28             : #include <linux/trace_seq.h>
      29             : 
      30             : /* How much buffer is left on the trace_seq? */
      31             : #define TRACE_SEQ_BUF_LEFT(s) seq_buf_buffer_left(&(s)->seq)
      32             : 
      33             : /*
      34             :  * trace_seq should work with being initialized with 0s.
      35             :  */
      36           0 : static inline void __trace_seq_init(struct trace_seq *s)
      37             : {
      38           0 :         if (unlikely(!s->seq.size))
      39           0 :                 trace_seq_init(s);
      40             : }
      41             : 
      42             : /**
      43             :  * trace_print_seq - move the contents of trace_seq into a seq_file
      44             :  * @m: the seq_file descriptor that is the destination
      45             :  * @s: the trace_seq descriptor that is the source.
      46             :  *
      47             :  * Returns 0 on success and non zero on error. If it succeeds to
      48             :  * write to the seq_file it will reset the trace_seq, otherwise
      49             :  * it does not modify the trace_seq to let the caller try again.
      50             :  */
      51           0 : int trace_print_seq(struct seq_file *m, struct trace_seq *s)
      52             : {
      53           0 :         int ret;
      54             : 
      55           0 :         __trace_seq_init(s);
      56             : 
      57           0 :         ret = seq_buf_print_seq(m, &s->seq);
      58             : 
      59             :         /*
      60             :          * Only reset this buffer if we successfully wrote to the
      61             :          * seq_file buffer. This lets the caller try again or
      62             :          * do something else with the contents.
      63             :          */
      64           0 :         if (!ret)
      65           0 :                 trace_seq_init(s);
      66             : 
      67           0 :         return ret;
      68             : }
      69             : 
      70             : /**
      71             :  * trace_seq_printf - sequence printing of trace information
      72             :  * @s: trace sequence descriptor
      73             :  * @fmt: printf format string
      74             :  *
      75             :  * The tracer may use either sequence operations or its own
      76             :  * copy to user routines. To simplify formating of a trace
      77             :  * trace_seq_printf() is used to store strings into a special
      78             :  * buffer (@s). Then the output may be either used by
      79             :  * the sequencer or pulled into another buffer.
      80             :  */
      81           0 : void trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
      82             : {
      83           0 :         unsigned int save_len = s->seq.len;
      84           0 :         va_list ap;
      85             : 
      86           0 :         if (s->full)
      87           0 :                 return;
      88             : 
      89           0 :         __trace_seq_init(s);
      90             : 
      91           0 :         va_start(ap, fmt);
      92           0 :         seq_buf_vprintf(&s->seq, fmt, ap);
      93           0 :         va_end(ap);
      94             : 
      95             :         /* If we can't write it all, don't bother writing anything */
      96           0 :         if (unlikely(seq_buf_has_overflowed(&s->seq))) {
      97           0 :                 s->seq.len = save_len;
      98           0 :                 s->full = 1;
      99             :         }
     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           0 : void trace_seq_bitmask(struct trace_seq *s, const unsigned long *maskp,
     112             :                       int nmaskbits)
     113             : {
     114           0 :         unsigned int save_len = s->seq.len;
     115             : 
     116           0 :         if (s->full)
     117             :                 return;
     118             : 
     119           0 :         __trace_seq_init(s);
     120             : 
     121           0 :         seq_buf_printf(&s->seq, "%*pb", nmaskbits, maskp);
     122             : 
     123           0 :         if (unlikely(seq_buf_has_overflowed(&s->seq))) {
     124           0 :                 s->seq.len = save_len;
     125           0 :                 s->full = 1;
     126             :         }
     127             : }
     128             : EXPORT_SYMBOL_GPL(trace_seq_bitmask);
     129             : 
     130             : /**
     131             :  * trace_seq_vprintf - sequence printing of trace information
     132             :  * @s: trace sequence descriptor
     133             :  * @fmt: printf format string
     134             :  *
     135             :  * The tracer may use either sequence operations or its own
     136             :  * copy to user routines. To simplify formating of a trace
     137             :  * trace_seq_printf is used to store strings into a special
     138             :  * buffer (@s). Then the output may be either used by
     139             :  * the sequencer or pulled into another buffer.
     140             :  */
     141           0 : void trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
     142             : {
     143           0 :         unsigned int save_len = s->seq.len;
     144             : 
     145           0 :         if (s->full)
     146             :                 return;
     147             : 
     148           0 :         __trace_seq_init(s);
     149             : 
     150           0 :         seq_buf_vprintf(&s->seq, fmt, args);
     151             : 
     152             :         /* If we can't write it all, don't bother writing anything */
     153           0 :         if (unlikely(seq_buf_has_overflowed(&s->seq))) {
     154           0 :                 s->seq.len = save_len;
     155           0 :                 s->full = 1;
     156             :         }
     157             : }
     158             : EXPORT_SYMBOL_GPL(trace_seq_vprintf);
     159             : 
     160             : /**
     161             :  * trace_seq_bprintf - Write the printf string from binary arguments
     162             :  * @s: trace sequence descriptor
     163             :  * @fmt: The format string for the @binary arguments
     164             :  * @binary: The binary arguments for @fmt.
     165             :  *
     166             :  * When recording in a fast path, a printf may be recorded with just
     167             :  * saving the format and the arguments as they were passed to the
     168             :  * function, instead of wasting cycles converting the arguments into
     169             :  * ASCII characters. Instead, the arguments are saved in a 32 bit
     170             :  * word array that is defined by the format string constraints.
     171             :  *
     172             :  * This function will take the format and the binary array and finish
     173             :  * the conversion into the ASCII string within the buffer.
     174             :  */
     175           0 : void trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary)
     176             : {
     177           0 :         unsigned int save_len = s->seq.len;
     178             : 
     179           0 :         if (s->full)
     180             :                 return;
     181             : 
     182           0 :         __trace_seq_init(s);
     183             : 
     184           0 :         seq_buf_bprintf(&s->seq, fmt, binary);
     185             : 
     186             :         /* If we can't write it all, don't bother writing anything */
     187           0 :         if (unlikely(seq_buf_has_overflowed(&s->seq))) {
     188           0 :                 s->seq.len = save_len;
     189           0 :                 s->full = 1;
     190           0 :                 return;
     191             :         }
     192             : }
     193             : EXPORT_SYMBOL_GPL(trace_seq_bprintf);
     194             : 
     195             : /**
     196             :  * trace_seq_puts - trace sequence printing of simple string
     197             :  * @s: trace sequence descriptor
     198             :  * @str: simple string to record
     199             :  *
     200             :  * The tracer may use either the sequence operations or its own
     201             :  * copy to user routines. This function records a simple string
     202             :  * into a special buffer (@s) for later retrieval by a sequencer
     203             :  * or other mechanism.
     204             :  */
     205           0 : void trace_seq_puts(struct trace_seq *s, const char *str)
     206             : {
     207           0 :         unsigned int len = strlen(str);
     208             : 
     209           0 :         if (s->full)
     210             :                 return;
     211             : 
     212           0 :         __trace_seq_init(s);
     213             : 
     214           0 :         if (len > TRACE_SEQ_BUF_LEFT(s)) {
     215           0 :                 s->full = 1;
     216           0 :                 return;
     217             :         }
     218             : 
     219           0 :         seq_buf_putmem(&s->seq, str, len);
     220             : }
     221             : EXPORT_SYMBOL_GPL(trace_seq_puts);
     222             : 
     223             : /**
     224             :  * trace_seq_putc - trace sequence printing of simple character
     225             :  * @s: trace sequence descriptor
     226             :  * @c: simple character to record
     227             :  *
     228             :  * The tracer may use either the sequence operations or its own
     229             :  * copy to user routines. This function records a simple charater
     230             :  * into a special buffer (@s) for later retrieval by a sequencer
     231             :  * or other mechanism.
     232             :  */
     233           0 : void trace_seq_putc(struct trace_seq *s, unsigned char c)
     234             : {
     235           0 :         if (s->full)
     236             :                 return;
     237             : 
     238           0 :         __trace_seq_init(s);
     239             : 
     240           0 :         if (TRACE_SEQ_BUF_LEFT(s) < 1) {
     241           0 :                 s->full = 1;
     242           0 :                 return;
     243             :         }
     244             : 
     245           0 :         seq_buf_putc(&s->seq, c);
     246             : }
     247             : EXPORT_SYMBOL_GPL(trace_seq_putc);
     248             : 
     249             : /**
     250             :  * trace_seq_putmem - write raw data into the trace_seq buffer
     251             :  * @s: trace sequence descriptor
     252             :  * @mem: The raw memory to copy into the buffer
     253             :  * @len: The length of the raw memory to copy (in bytes)
     254             :  *
     255             :  * There may be cases where raw memory needs to be written into the
     256             :  * buffer and a strcpy() would not work. Using this function allows
     257             :  * for such cases.
     258             :  */
     259           0 : void trace_seq_putmem(struct trace_seq *s, const void *mem, unsigned int len)
     260             : {
     261           0 :         if (s->full)
     262             :                 return;
     263             : 
     264           0 :         __trace_seq_init(s);
     265             : 
     266           0 :         if (len > TRACE_SEQ_BUF_LEFT(s)) {
     267           0 :                 s->full = 1;
     268           0 :                 return;
     269             :         }
     270             : 
     271           0 :         seq_buf_putmem(&s->seq, mem, len);
     272             : }
     273             : EXPORT_SYMBOL_GPL(trace_seq_putmem);
     274             : 
     275             : /**
     276             :  * trace_seq_putmem_hex - write raw memory into the buffer in ASCII hex
     277             :  * @s: trace sequence descriptor
     278             :  * @mem: The raw memory to write its hex ASCII representation of
     279             :  * @len: The length of the raw memory to copy (in bytes)
     280             :  *
     281             :  * This is similar to trace_seq_putmem() except instead of just copying the
     282             :  * raw memory into the buffer it writes its ASCII representation of it
     283             :  * in hex characters.
     284             :  */
     285           0 : void trace_seq_putmem_hex(struct trace_seq *s, const void *mem,
     286             :                          unsigned int len)
     287             : {
     288           0 :         unsigned int save_len = s->seq.len;
     289             : 
     290           0 :         if (s->full)
     291             :                 return;
     292             : 
     293           0 :         __trace_seq_init(s);
     294             : 
     295             :         /* Each byte is represented by two chars */
     296           0 :         if (len * 2 > TRACE_SEQ_BUF_LEFT(s)) {
     297           0 :                 s->full = 1;
     298           0 :                 return;
     299             :         }
     300             : 
     301             :         /* The added spaces can still cause an overflow */
     302           0 :         seq_buf_putmem_hex(&s->seq, mem, len);
     303             : 
     304           0 :         if (unlikely(seq_buf_has_overflowed(&s->seq))) {
     305           0 :                 s->seq.len = save_len;
     306           0 :                 s->full = 1;
     307           0 :                 return;
     308             :         }
     309             : }
     310             : EXPORT_SYMBOL_GPL(trace_seq_putmem_hex);
     311             : 
     312             : /**
     313             :  * trace_seq_path - copy a path into the sequence buffer
     314             :  * @s: trace sequence descriptor
     315             :  * @path: path to write into the sequence buffer.
     316             :  *
     317             :  * Write a path name into the sequence buffer.
     318             :  *
     319             :  * Returns 1 if we successfully written all the contents to
     320             :  *   the buffer.
     321             :  * Returns 0 if we the length to write is bigger than the
     322             :  *   reserved buffer space. In this case, nothing gets written.
     323             :  */
     324           0 : int trace_seq_path(struct trace_seq *s, const struct path *path)
     325             : {
     326           0 :         unsigned int save_len = s->seq.len;
     327             : 
     328           0 :         if (s->full)
     329             :                 return 0;
     330             : 
     331           0 :         __trace_seq_init(s);
     332             : 
     333           0 :         if (TRACE_SEQ_BUF_LEFT(s) < 1) {
     334           0 :                 s->full = 1;
     335           0 :                 return 0;
     336             :         }
     337             : 
     338           0 :         seq_buf_path(&s->seq, path, "\n");
     339             : 
     340           0 :         if (unlikely(seq_buf_has_overflowed(&s->seq))) {
     341           0 :                 s->seq.len = save_len;
     342           0 :                 s->full = 1;
     343           0 :                 return 0;
     344             :         }
     345             : 
     346             :         return 1;
     347             : }
     348             : EXPORT_SYMBOL_GPL(trace_seq_path);
     349             : 
     350             : /**
     351             :  * trace_seq_to_user - copy the squence buffer to user space
     352             :  * @s: trace sequence descriptor
     353             :  * @ubuf: The userspace memory location to copy to
     354             :  * @cnt: The amount to copy
     355             :  *
     356             :  * Copies the sequence buffer into the userspace memory pointed to
     357             :  * by @ubuf. It starts from the last read position (@s->readpos)
     358             :  * and writes up to @cnt characters or till it reaches the end of
     359             :  * the content in the buffer (@s->len), which ever comes first.
     360             :  *
     361             :  * On success, it returns a positive number of the number of bytes
     362             :  * it copied.
     363             :  *
     364             :  * On failure it returns -EBUSY if all of the content in the
     365             :  * sequence has been already read, which includes nothing in the
     366             :  * sequenc (@s->len == @s->readpos).
     367             :  *
     368             :  * Returns -EFAULT if the copy to userspace fails.
     369             :  */
     370           0 : int trace_seq_to_user(struct trace_seq *s, char __user *ubuf, int cnt)
     371             : {
     372           0 :         __trace_seq_init(s);
     373           0 :         return seq_buf_to_user(&s->seq, ubuf, cnt);
     374             : }
     375             : EXPORT_SYMBOL_GPL(trace_seq_to_user);
     376             : 
     377           0 : int trace_seq_hex_dump(struct trace_seq *s, const char *prefix_str,
     378             :                        int prefix_type, int rowsize, int groupsize,
     379             :                        const void *buf, size_t len, bool ascii)
     380             : {
     381           0 :         unsigned int save_len = s->seq.len;
     382             : 
     383           0 :         if (s->full)
     384             :                 return 0;
     385             : 
     386           0 :         __trace_seq_init(s);
     387             : 
     388           0 :         if (TRACE_SEQ_BUF_LEFT(s) < 1) {
     389           0 :                 s->full = 1;
     390           0 :                 return 0;
     391             :         }
     392             : 
     393           0 :         seq_buf_hex_dump(&(s->seq), prefix_str,
     394             :                    prefix_type, rowsize, groupsize,
     395             :                    buf, len, ascii);
     396             : 
     397           0 :         if (unlikely(seq_buf_has_overflowed(&s->seq))) {
     398           0 :                 s->seq.len = save_len;
     399           0 :                 s->full = 1;
     400           0 :                 return 0;
     401             :         }
     402             : 
     403             :         return 1;
     404             : }
     405             : EXPORT_SYMBOL(trace_seq_hex_dump);

Generated by: LCOV version 1.14