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