![]() |
|
|||
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);
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.1.0 LXR engine. The LXR team |
![]() ![]() |