24 #include <linux/kernel.h> 25 #include <linux/debugfs.h> 26 #include <linux/module.h> 27 #include <linux/uaccess.h> 28 #include <linux/string.h> 29 #include <linux/ctype.h> 30 #include <linux/delay.h> 32 #include <linux/vmalloc.h> 33 #include <linux/poll.h> 34 #include <linux/version.h> 52 static struct dentry *trc_dir;
53 static const char trc_dir_name[] =
"trace";
58 static ssize_t trc_write_helper(
struct file *
file,
const char __user *ubuf,
59 size_t ubuf_size, loff_t *ppos,
60 trc_write_actor_t actor)
63 ssize_t ret_size = ubuf_size;
66 if (ubuf_size >
sizeof buf - 1)
69 if (strncpy_from_user(
buf, ubuf, ubuf_size) < 0)
71 buf[ubuf_size] =
'\0';
78 if (
buf[ubuf_size - 1] ==
'\n') {
79 buf[ubuf_size - 1] = 0;
83 pr_info(KBUILD_MODNAME
": %s (%s) command '%s'\n",
84 file->f_path.dentry->d_name.name,
85 file->f_path.dentry->d_iname,
100 static bool trc_immediate_mask_is_opened =
false;
102 static int trc_immediate_mask_open(
struct inode *
i,
struct file *
f)
104 if (trc_immediate_mask_is_opened)
107 trc_immediate_mask_is_opened =
true;
112 static int trc_immediate_mask_release(
struct inode *
i,
struct file *
f)
114 trc_immediate_mask_is_opened =
false;
119 const char *
fmt, ...)
125 n += vsnprintf(
buf + buf_used,
133 static ssize_t trc_immediate_mask_read(
struct file *
file,
char __user *ubuf,
134 size_t ubuf_size, loff_t *ppos)
137 ssize_t ret_size = 0;
139 const char *subsys_name;
141 static char buf[4096];
154 if (subsys_name ==
NULL)
158 if (buf_used >=
sizeof buf) {
159 buf_used =
sizeof buf - 2;
165 buf[buf_used++] =
'\n';
166 buf[buf_used++] =
'\0';
167 ret_size =
min(ubuf_size, buf_used);
169 return simple_read_from_buffer(ubuf, ubuf_size, ppos,
buf, ret_size);
172 static ssize_t trc_immediate_mask_write(
struct file *
file,
173 const char __user *ubuf,
174 size_t ubuf_size, loff_t *ppos)
176 return trc_write_helper(
file, ubuf, ubuf_size, ppos,
180 static const struct file_operations trc_immediate_mask_fops = {
181 .owner = THIS_MODULE,
182 .open = trc_immediate_mask_open,
183 .release = trc_immediate_mask_release,
184 .read = trc_immediate_mask_read,
185 .write = trc_immediate_mask_write,
190 static bool trc_level_is_opened =
false;
192 static int trc_level_open(
struct inode *
i,
struct file *
f)
194 if (trc_level_is_opened)
197 trc_level_is_opened =
true;
202 static int trc_level_release(
struct inode *
i,
struct file *
f)
204 trc_level_is_opened =
false;
208 static ssize_t trc_level_read(
struct file *
file,
char __user *ubuf,
209 size_t ubuf_size, loff_t *ppos)
212 ssize_t ret_size = 0;
214 const char *level_name;
216 static char buf[256];
231 if (buf_used >=
sizeof buf) {
232 buf_used =
sizeof buf - 2;
238 buf[buf_used++] =
'\n';
239 buf[buf_used++] =
'\0';
240 ret_size =
min(ubuf_size, buf_used);
242 return simple_read_from_buffer(ubuf, ubuf_size, ppos,
buf, ret_size);
245 static ssize_t trc_level_write(
struct file *
file,
const char __user *ubuf,
246 size_t ubuf_size, loff_t *ppos)
251 static const struct file_operations trc_level_fops = {
252 .owner = THIS_MODULE,
253 .open = trc_level_open,
254 .release = trc_level_release,
255 .read = trc_level_read,
256 .write = trc_level_write,
261 static bool trc_print_context_is_opened =
false;
263 static int trc_print_context_open(
struct inode *
i,
struct file *
f)
265 if (trc_print_context_is_opened)
268 trc_print_context_is_opened =
true;
273 static int trc_print_context_release(
struct inode *
i,
struct file *
f)
275 trc_print_context_is_opened =
false;
279 static ssize_t trc_print_context_read(
struct file *
file,
char __user *ubuf,
280 size_t ubuf_size, loff_t *ppos)
286 strncpy(
buf,
"func\n",
sizeof buf);
288 strncpy(
buf,
"short\n",
sizeof buf);
290 strncpy(
buf,
"full\n",
sizeof buf);
292 strncpy(
buf,
"none\n",
sizeof buf);
294 strncpy(
buf,
"INVALID\n",
sizeof buf);
296 ret_size =
min(ubuf_size, strlen(
buf) + 1);
298 return simple_read_from_buffer(ubuf, ubuf_size, ppos,
buf, ret_size);
301 static ssize_t trc_print_context_write(
struct file *
file,
const char __user *ubuf,
302 size_t ubuf_size, loff_t *ppos)
304 return trc_write_helper(
file, ubuf, ubuf_size, ppos,
308 static const struct file_operations trc_print_context_fops = {
309 .owner = THIS_MODULE,
310 .open = trc_print_context_open,
311 .release = trc_print_context_release,
312 .read = trc_print_context_read,
313 .write = trc_print_context_write,
318 static bool trc_stat_is_opened =
false;
320 static int trc_stat_open(
struct inode *
i,
struct file *
f)
322 if (trc_stat_is_opened)
325 trc_stat_is_opened =
true;
330 static int trc_stat_release(
struct inode *
i,
struct file *
f)
332 trc_stat_is_opened =
false;
336 static const char *bytes_to_human_str(uint64_t bytes)
338 static char buf[256];
345 if (bytes / 1024 / 1024 / 1024) {
346 integer = bytes / 1024 / 1024 / 1024;
347 reminder = bytes % (1024 * 1024 * 1024) / 10000000;
349 }
else if (bytes / 1024 / 1024) {
350 integer = bytes / 1024 / 1024;
351 reminder = bytes % (1024 * 1024) / 10000;
353 }
else if (bytes / 1024) {
354 integer = bytes / 1024;
355 reminder = bytes % 1024 / 10;
362 snprintf(
buf,
sizeof buf,
"%" PRIu64 ".%02u%s", integer, reminder, units);
363 buf[
sizeof buf - 1] =
'\0';
368 static ssize_t trc_stat_read(
struct file *
file,
char __user *ubuf,
369 size_t ubuf_size, loff_t *ppos)
371 static char buf[4096];
374 ssize_t ret_size = 0;
377 uint32_t logbuf_size;
378 uint64_t total_rec_num;
379 uint32_t rec_per_sec;
380 uint32_t bytes_per_sec;
381 uint32_t avg_rec_per_sec;
382 uint32_t avg_bytes_per_sec;
383 uint32_t max_rec_per_sec;
384 uint32_t max_bytes_per_sec;
385 uint32_t avg_rec_size;
386 uint32_t max_rec_size;
398 rec_per_sec =
stats->trs_rec_per_sec;
399 bytes_per_sec =
stats->trs_bytes_per_sec;
400 avg_rec_per_sec =
stats->trs_avg_rec_per_sec;
401 avg_bytes_per_sec =
stats->trs_avg_bytes_per_sec;
402 max_rec_per_sec =
stats->trs_max_rec_per_sec;
403 max_bytes_per_sec =
stats->trs_max_bytes_per_sec;
404 avg_rec_size =
stats->trs_avg_rec_size;
405 max_rec_size =
stats->trs_max_rec_size;
408 "buffer address: 0x%p\n",
412 "buffer size: %-12u %s\n",
413 logbuf_size, bytes_to_human_str(logbuf_size));
416 "buffer abs pos: %-12llu %s\n",
417 logbuf_pos, bytes_to_human_str(logbuf_pos));
420 "total rec num: %-12llu %s\n",
421 total_rec_num, bytes_to_human_str(total_rec_num));
424 "records per sec: %-12u %s\n",
425 rec_per_sec, bytes_to_human_str(rec_per_sec));
428 "bytes per sec: %-12u %s\n",
429 bytes_per_sec, bytes_to_human_str(bytes_per_sec));
432 "avg records per sec: %-12u %s\n",
434 bytes_to_human_str(avg_rec_per_sec));
437 "avg bytes per sec: %-12u %s\n",
439 bytes_to_human_str(avg_bytes_per_sec));
442 "max records per sec: %-12u %s\n",
444 bytes_to_human_str(max_rec_per_sec));
447 "max bytes per sec: %-12u %s\n",
449 bytes_to_human_str(max_bytes_per_sec));
452 "avg record size: %-12u %s\n",
453 avg_rec_size, bytes_to_human_str(avg_rec_size));
456 "max record size: %-12u %s\n",
457 max_rec_size, bytes_to_human_str(max_rec_size));
459 if (buf_used >=
sizeof buf)
461 buf[buf_used++] =
'\0';
462 ret_size =
min(ubuf_size, buf_used);
464 return simple_read_from_buffer(ubuf, ubuf_size, ppos,
buf, ret_size);
467 static const struct file_operations trc_stat_fops = {
468 .owner = THIS_MODULE,
469 .open = trc_stat_open,
470 .release = trc_stat_release,
471 .read = trc_stat_read,
476 static bool trc_records_is_opened =
false;
479 static int trc_records_open(
struct inode *
i,
struct file *
f)
481 if (trc_records_is_opened)
484 trc_records_is_opened =
true;
485 trc_records_last_trh =
NULL;
490 static int trc_records_release(
struct inode *
i,
struct file *
f)
492 trc_records_is_opened =
false;
521 static ssize_t trc_records_read(
struct file *
file,
char __user *ubuf,
522 size_t ubuf_size, loff_t *ppos)
525 static char buf[16 * 1024];
534 if (trc_records_last_trh ==
NULL)
537 trh = find_next_recornd(trc_records_last_trh);
539 if (trh !=
NULL && trh != trc_records_last_trh) {
540 trc_records_last_trh = trh;
546 rc = msleep_interruptible(100);
554 pr_warn(KBUILD_MODNAME
": internal buffer is to small to hold" 557 return simple_read_from_buffer(ubuf, ubuf_size, &fake_pos,
561 return simple_read_from_buffer(ubuf, ubuf_size, &fake_pos,
565 static const struct file_operations trc_records_fops = {
566 .owner = THIS_MODULE,
567 .open = trc_records_open,
568 .release = trc_records_release,
569 .read = trc_records_read,
574 static int trc_buffer_open(
struct inode *
i,
struct file *
f)
579 static int trc_buffer_release(
struct inode *
i,
struct file *
f)
584 static ssize_t trc_buffer_read(
struct file *
file,
char __user *ubuf,
585 size_t ubuf_size, loff_t *ppos)
591 return simple_read_from_buffer(ubuf, ubuf_size, ppos, logbuf_header,
595 static void trc_buffer_mmap_close(
struct vm_area_struct *vma)
599 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,11,0) 600 static int trc_buffer_mmap_fault(
struct vm_fault *vmf)
602 static int trc_buffer_mmap_fault(
struct vm_area_struct *vma,
struct vm_fault *vmf)
606 pgoff_t pgoff = vmf->pgoff;
609 page = vmalloc_to_page(logbuf_header + (pgoff << PAGE_SHIFT));
611 return VM_FAULT_SIGBUS;
619 static const struct vm_operations_struct trc_buffer_mmap_ops = {
620 .fault = trc_buffer_mmap_fault,
621 .close = trc_buffer_mmap_close,
624 static int trc_buffer_mmap(
struct file *filp,
struct vm_area_struct *vma)
626 unsigned long length = vma->vm_end - vma->vm_start;
630 if (length + (vma->vm_pgoff << PAGE_SHIFT) > logbuf_size)
633 vma->vm_ops = &trc_buffer_mmap_ops;
634 vma->vm_flags |= VM_DONTEXPAND;
639 static unsigned int trc_buffer_poll(
struct file *filp, poll_table *pt)
643 const uint32_t idle_timeo = 100;
645 static uint32_t timeo;
646 static const char *oldpos;
652 if (oldpos ==
NULL) {
657 while (curpos == oldpos) {
658 rc = msleep_interruptible(timeo);
666 if (++timeo > idle_timeo)
672 return (
unsigned int)(POLLIN | POLLRDNORM);
675 static const struct file_operations trc_buffer_fops = {
676 .owner = THIS_MODULE,
677 .open = trc_buffer_open,
678 .release = trc_buffer_release,
679 .read = trc_buffer_read,
680 .mmap = trc_buffer_mmap,
681 .poll = trc_buffer_poll,
688 struct dentry *trc_level_file;
689 static const char trc_level_name[] =
"level";
690 struct dentry *trc_immediate_mask_file;
691 static const char trc_immediate_mask_name[] =
"immediate_mask";
692 struct dentry *trc_print_context_file;
693 static const char trc_print_context_name[] =
"print_context";
694 struct dentry *trc_stat_file;
695 static const char trc_stat_name[] =
"stat";
696 struct dentry *trc_records_file;
697 static const char trc_records_name[] =
"records";
698 struct dentry *trc_buffer_file;
699 static const char trc_buffer_name[] =
"buffer";
702 trc_dir = debugfs_create_dir(trc_dir_name,
dfs_root_dir);
703 if (trc_dir ==
NULL) {
704 pr_err(KBUILD_MODNAME
": can't create debugfs dir '%s/%s'\n",
710 trc_level_file = debugfs_create_file(trc_level_name, S_IRUSR | S_IWUSR,
711 trc_dir,
NULL, &trc_level_fops);
712 if (trc_level_file ==
NULL) {
713 pr_err(KBUILD_MODNAME
": failed to create debugfs file" 720 trc_immediate_mask_file = debugfs_create_file(trc_immediate_mask_name,
721 S_IRUSR | S_IWUSR, trc_dir,
NULL,
722 &trc_immediate_mask_fops);
723 if (trc_immediate_mask_file ==
NULL) {
724 pr_err(KBUILD_MODNAME
": failed to create debugfs file" 726 trc_immediate_mask_name);
731 trc_print_context_file = debugfs_create_file(trc_print_context_name,
732 S_IRUSR | S_IWUSR, trc_dir,
NULL,
733 &trc_print_context_fops);
734 if (trc_print_context_file ==
NULL) {
735 pr_err(KBUILD_MODNAME
": failed to create debugfs file" 737 trc_print_context_name);
742 trc_stat_file = debugfs_create_file(trc_stat_name, S_IRUSR, trc_dir,
743 NULL, &trc_stat_fops);
744 if (trc_stat_file ==
NULL) {
745 pr_err(KBUILD_MODNAME
": failed to create debugfs file" 752 trc_records_file = debugfs_create_file(trc_records_name, S_IRUSR,
755 if (trc_records_file ==
NULL) {
756 pr_err(KBUILD_MODNAME
": failed to create debugfs file" 763 trc_buffer_file = debugfs_create_file(trc_buffer_name, S_IRUSR,
766 if (trc_buffer_file ==
NULL) {
767 pr_err(KBUILD_MODNAME
": failed to create debugfs file" 776 debugfs_remove_recursive(trc_dir);
783 debugfs_remove_recursive(trc_dir);
M0_INTERNAL const void * m0_trace_logbuf_get(void)
static struct m0_addb2_philter p
M0_INTERNAL uint32_t m0_trace_logbuf_size_get(void)
enum m0_trace_level level
M0_INTERNAL int m0_trace_record_print_yaml(char *outbuf, size_t outbuf_size, const struct m0_trace_rec_header *trh, const void *tr_body, bool yaml_stream_mode)
struct dentry * dfs_root_dir
M0_INTERNAL const struct m0_trace_rec_header * m0_trace_last_record_get(void)
void trc_dfs_cleanup(void)
M0_INTERNAL const char * m0_trace_subsys_name(uint64_t subsys)
M0_INTERNAL int m0_trace_set_print_context(const char *ctx_name)
M0_INTERNAL void m0_trace_stats_update(uint32_t rec_size)
static int struct dentry * dentry
M0_INTERNAL const char * m0_trace_level_name(enum m0_trace_level level)
static int buf_add(struct m0_net_buffer *nb)
char * fmt(const char *format,...) __attribute__((format(printf
M0_INTERNAL const struct m0_trace_buf_header * m0_trace_logbuf_header_get(void)
const char dfs_root_name[]
static int64_t m0_atomic64_get(const struct m0_atomic64 *a)
static long long min(long long a, long long b)
M0_INTERNAL int m0_trace_set_immediate_mask(const char *mask_str)
M0_INTERNAL const struct m0_trace_stats * m0_trace_get_stats(void)
unsigned long m0_trace_immediate_mask
M0_INTERNAL uint64_t m0_trace_logbuf_pos_get(void)
static uint64_t m0_align(uint64_t val, uint64_t alignment)
M0_INTERNAL int m0_trace_set_level(const char *level_str)