fix: tracepoint: Optimize using static_call() (v5.10)
[lttng-modules.git] / src / probes / lttng.c
1 /* SPDX-License-Identifier: (GPL-2.0-only or LGPL-2.1-only)
2 *
3 * lttng.c
4 *
5 * LTTng logger ABI
6 *
7 * Copyright (C) 2008-2014 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
8 */
9
10 #include <linux/module.h>
11 #include <wrapper/tracepoint.h>
12 #include <linux/uaccess.h>
13 #include <linux/gfp.h>
14 #include <linux/fs.h>
15 #include <linux/proc_fs.h>
16 #include <linux/slab.h>
17 #include <linux/mm.h>
18 #include <linux/miscdevice.h>
19 #include <wrapper/vmalloc.h>
20 #include <lttng/events.h>
21
22 #define TP_MODULE_NOAUTOLOAD
23 #define LTTNG_PACKAGE_BUILD
24 #define CREATE_TRACE_POINTS
25 #define TRACE_INCLUDE_PATH instrumentation/events
26 #define TRACE_INCLUDE_FILE lttng
27 #define LTTNG_INSTRUMENTATION
28
29 #include <instrumentation/events/lttng.h>
30
31 /* Events written through logger are truncated at 1024 bytes */
32 #define LTTNG_LOGGER_COUNT_MAX 1024
33 #define LTTNG_LOGGER_FILE "lttng-logger"
34
35 LTTNG_DEFINE_TRACE(lttng_logger,
36 PARAMS(const char __user *text, size_t len),
37 PARAMS(text, len)
38 );
39
40 static struct proc_dir_entry *lttng_logger_dentry;
41
42 /**
43 * lttng_logger_write - write a userspace string into the trace system
44 * @file: file pointer
45 * @user_buf: user string
46 * @count: length to copy
47 * @ppos: file position
48 *
49 * Copy a userspace string into a trace event named "lttng:logger".
50 * Copies at most @count bytes into the event "msg" dynamic array.
51 * Truncates the count at LTTNG_LOGGER_COUNT_MAX. Returns the number of
52 * bytes copied from the source.
53 * Return -1 on error, with EFAULT errno.
54 */
55 static
56 ssize_t lttng_logger_write(struct file *file, const char __user *user_buf,
57 size_t count, loff_t *ppos)
58 {
59 int nr_pages = 1, i;
60 unsigned long uaddr = (unsigned long) user_buf;
61 struct page *pages[2];
62 ssize_t written;
63 int ret;
64
65 /* Truncate count */
66 if (unlikely(count > LTTNG_LOGGER_COUNT_MAX))
67 count = LTTNG_LOGGER_COUNT_MAX;
68
69 /* How many pages are we dealing with ? */
70 if (unlikely((uaddr & PAGE_MASK) != ((uaddr + count) & PAGE_MASK)))
71 nr_pages = 2;
72
73 /* Pin userspace pages */
74 ret = get_user_pages_fast(uaddr, nr_pages, 0, pages);
75 if (unlikely(ret < nr_pages)) {
76 if (ret > 0) {
77 BUG_ON(ret != 1);
78 put_page(pages[0]);
79 }
80 written = -EFAULT;
81 goto end;
82 }
83
84 /* Trace the event */
85 trace_lttng_logger(user_buf, count);
86 written = count;
87 *ppos += written;
88
89 for (i = 0; i < nr_pages; i++)
90 put_page(pages[i]);
91 end:
92 return written;
93 }
94
95 static const struct file_operations lttng_logger_operations = {
96 .write = lttng_logger_write,
97 };
98
99 /*
100 * Linux 5.6 introduced a separate proc_ops struct for /proc operations
101 * to decouple it from the vfs.
102 */
103 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0))
104 static const struct proc_ops lttng_logger_proc_ops = {
105 .proc_write = lttng_logger_write,
106 };
107 #else
108 #define lttng_logger_proc_ops lttng_logger_operations
109 #endif
110
111 static struct miscdevice logger_dev = {
112 .minor = MISC_DYNAMIC_MINOR,
113 .name = "lttng-logger",
114 .mode = 0666,
115 .fops = &lttng_logger_operations
116 };
117
118 int __init lttng_logger_init(void)
119 {
120 int ret = 0;
121
122 wrapper_vmalloc_sync_mappings();
123
124 /* /dev/lttng-logger */
125 ret = misc_register(&logger_dev);
126 if (ret) {
127 printk(KERN_ERR "LTTng: Error creating logger device\n");
128 goto error;
129 }
130
131 /* /proc/lttng-logger */
132 lttng_logger_dentry = proc_create_data(LTTNG_LOGGER_FILE,
133 S_IRUGO | S_IWUGO, NULL,
134 &lttng_logger_proc_ops, NULL);
135 if (!lttng_logger_dentry) {
136 printk(KERN_ERR "LTTng: Error creating logger proc file\n");
137 ret = -ENOMEM;
138 goto error_proc;
139 }
140
141 /* Init */
142 ret = __lttng_events_init__lttng();
143 if (ret)
144 goto error_events;
145 return ret;
146
147 error_events:
148 remove_proc_entry("lttng-logger", NULL);
149 error_proc:
150 misc_deregister(&logger_dev);
151 error:
152 return ret;
153 }
154
155 void lttng_logger_exit(void)
156 {
157 __lttng_events_exit__lttng();
158 if (lttng_logger_dentry)
159 remove_proc_entry("lttng-logger", NULL);
160 misc_deregister(&logger_dev);
161 }
This page took 0.034035 seconds and 4 git commands to generate.