trace_seq.c (10657B)
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 succeed 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 */ 36static inline void __trace_seq_init(struct trace_seq *s) 37{ 38 if (unlikely(!s->seq.size)) 39 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 */ 51int trace_print_seq(struct seq_file *m, struct trace_seq *s) 52{ 53 int ret; 54 55 __trace_seq_init(s); 56 57 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 if (!ret) 65 trace_seq_init(s); 66 67 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 formatting 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 */ 81void trace_seq_printf(struct trace_seq *s, const char *fmt, ...) 82{ 83 unsigned int save_len = s->seq.len; 84 va_list ap; 85 86 if (s->full) 87 return; 88 89 __trace_seq_init(s); 90 91 va_start(ap, fmt); 92 seq_buf_vprintf(&s->seq, fmt, ap); 93 va_end(ap); 94 95 /* If we can't write it all, don't bother writing anything */ 96 if (unlikely(seq_buf_has_overflowed(&s->seq))) { 97 s->seq.len = save_len; 98 s->full = 1; 99 } 100} 101EXPORT_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 */ 111void trace_seq_bitmask(struct trace_seq *s, const unsigned long *maskp, 112 int nmaskbits) 113{ 114 unsigned int save_len = s->seq.len; 115 116 if (s->full) 117 return; 118 119 __trace_seq_init(s); 120 121 seq_buf_printf(&s->seq, "%*pb", nmaskbits, maskp); 122 123 if (unlikely(seq_buf_has_overflowed(&s->seq))) { 124 s->seq.len = save_len; 125 s->full = 1; 126 } 127} 128EXPORT_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 formatting 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 */ 141void trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args) 142{ 143 unsigned int save_len = s->seq.len; 144 145 if (s->full) 146 return; 147 148 __trace_seq_init(s); 149 150 seq_buf_vprintf(&s->seq, fmt, args); 151 152 /* If we can't write it all, don't bother writing anything */ 153 if (unlikely(seq_buf_has_overflowed(&s->seq))) { 154 s->seq.len = save_len; 155 s->full = 1; 156 } 157} 158EXPORT_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 */ 175void trace_seq_bprintf(struct trace_seq *s, const char *fmt, const u32 *binary) 176{ 177 unsigned int save_len = s->seq.len; 178 179 if (s->full) 180 return; 181 182 __trace_seq_init(s); 183 184 seq_buf_bprintf(&s->seq, fmt, binary); 185 186 /* If we can't write it all, don't bother writing anything */ 187 if (unlikely(seq_buf_has_overflowed(&s->seq))) { 188 s->seq.len = save_len; 189 s->full = 1; 190 return; 191 } 192} 193EXPORT_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 */ 205void trace_seq_puts(struct trace_seq *s, const char *str) 206{ 207 unsigned int len = strlen(str); 208 209 if (s->full) 210 return; 211 212 __trace_seq_init(s); 213 214 if (len > TRACE_SEQ_BUF_LEFT(s)) { 215 s->full = 1; 216 return; 217 } 218 219 seq_buf_putmem(&s->seq, str, len); 220} 221EXPORT_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 character 230 * into a special buffer (@s) for later retrieval by a sequencer 231 * or other mechanism. 232 */ 233void trace_seq_putc(struct trace_seq *s, unsigned char c) 234{ 235 if (s->full) 236 return; 237 238 __trace_seq_init(s); 239 240 if (TRACE_SEQ_BUF_LEFT(s) < 1) { 241 s->full = 1; 242 return; 243 } 244 245 seq_buf_putc(&s->seq, c); 246} 247EXPORT_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 */ 259void trace_seq_putmem(struct trace_seq *s, const void *mem, unsigned int len) 260{ 261 if (s->full) 262 return; 263 264 __trace_seq_init(s); 265 266 if (len > TRACE_SEQ_BUF_LEFT(s)) { 267 s->full = 1; 268 return; 269 } 270 271 seq_buf_putmem(&s->seq, mem, len); 272} 273EXPORT_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 */ 285void trace_seq_putmem_hex(struct trace_seq *s, const void *mem, 286 unsigned int len) 287{ 288 unsigned int save_len = s->seq.len; 289 290 if (s->full) 291 return; 292 293 __trace_seq_init(s); 294 295 /* Each byte is represented by two chars */ 296 if (len * 2 > TRACE_SEQ_BUF_LEFT(s)) { 297 s->full = 1; 298 return; 299 } 300 301 /* The added spaces can still cause an overflow */ 302 seq_buf_putmem_hex(&s->seq, mem, len); 303 304 if (unlikely(seq_buf_has_overflowed(&s->seq))) { 305 s->seq.len = save_len; 306 s->full = 1; 307 return; 308 } 309} 310EXPORT_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 */ 324int trace_seq_path(struct trace_seq *s, const struct path *path) 325{ 326 unsigned int save_len = s->seq.len; 327 328 if (s->full) 329 return 0; 330 331 __trace_seq_init(s); 332 333 if (TRACE_SEQ_BUF_LEFT(s) < 1) { 334 s->full = 1; 335 return 0; 336 } 337 338 seq_buf_path(&s->seq, path, "\n"); 339 340 if (unlikely(seq_buf_has_overflowed(&s->seq))) { 341 s->seq.len = save_len; 342 s->full = 1; 343 return 0; 344 } 345 346 return 1; 347} 348EXPORT_SYMBOL_GPL(trace_seq_path); 349 350/** 351 * trace_seq_to_user - copy the sequence 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 * sequence (@s->len == @s->readpos). 367 * 368 * Returns -EFAULT if the copy to userspace fails. 369 */ 370int trace_seq_to_user(struct trace_seq *s, char __user *ubuf, int cnt) 371{ 372 __trace_seq_init(s); 373 return seq_buf_to_user(&s->seq, ubuf, cnt); 374} 375EXPORT_SYMBOL_GPL(trace_seq_to_user); 376 377int 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 unsigned int save_len = s->seq.len; 382 383 if (s->full) 384 return 0; 385 386 __trace_seq_init(s); 387 388 if (TRACE_SEQ_BUF_LEFT(s) < 1) { 389 s->full = 1; 390 return 0; 391 } 392 393 seq_buf_hex_dump(&(s->seq), prefix_str, 394 prefix_type, rowsize, groupsize, 395 buf, len, ascii); 396 397 if (unlikely(seq_buf_has_overflowed(&s->seq))) { 398 s->seq.len = save_len; 399 s->full = 1; 400 return 0; 401 } 402 403 return 1; 404} 405EXPORT_SYMBOL(trace_seq_hex_dump);