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