fe70f9a9fd3b9c3ea1ce9f2f66138dee892b68df
[lttng-modules.git] / ltt-debugfs-abi.c
1 /*
2 * ltt-debugfs-abi.c
3 *
4 * Copyright 2010 (c) - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 *
6 * LTTng debugfs ABI
7 *
8 * Mimic system calls for:
9 * - session creation, returns a file descriptor or failure.
10 * - channel creation, returns a file descriptor or failure.
11 * - Operates on a session file descriptor
12 * - Takes all channel options as parameters.
13 * - stream get, returns a file descriptor or failure.
14 * - Operates on a channel file descriptor.
15 * - stream notifier get, returns a file descriptor or failure.
16 * - Operates on a channel file descriptor.
17 * - event creation, returns a file descriptor or failure.
18 * - Operates on a channel file descriptor
19 * - Takes an event name as parameter
20 * - Takes an instrumentation source as parameter
21 * - e.g. tracepoints, dynamic_probes...
22 * - Takes instrumentation source specific arguments.
23 */
24
25 #include <linux/debugfs.h>
26 #include "ltt-events.h"
27
28 /*
29 * This is LTTng's own personal way to create a system call as an external
30 * module. We use ioctl() on /sys/kernel/debug/lttng.
31 */
32
33 static struct dentry *lttng_dentry;
34 static const struct file_operations lttng_fops;
35 static const struct file_operations lttng_session_fops;
36 static const struct file_operations lttng_channel_fops;
37
38 /*
39 * LTTng DebugFS ABI structures.
40 */
41
42 struct lttng_channel {
43 int session; /* Session file descriptor */
44 int overwrite; /* 1: overwrite, 0: discard */
45 u64 subbuf_size;
46 u64 num_subbuf;
47 unsigned int switch_timer_interval;
48 unsigned int read_timer_interval;
49 };
50
51 struct lttng_event {
52 int channel; /* Channel file descriptor */
53 enum instrum_type itype;
54 char name[];
55 };
56
57 static
58 int lttng_abi_create_session(void)
59 {
60 struct ltt_session *session;
61 struct file *session_file;
62 int session_fd;
63
64 session = ltt_session_create()
65 if (!session)
66 return -ENOMEM;
67 session_fd = get_unused_fd_flags(O_RDWR);
68 if (session_fd < 0) {
69 ret = session_fd;
70 goto fd_error;
71 }
72 session_file = anon_inode_getfile("[lttng_session]",
73 &lttng_session_fops,
74 session, O_RDWR);
75 if (IS_ERR(session_file)) {
76 ret = PTR_ERR(session_file);
77 goto file_error;
78 }
79 fd_install(session_fd, session_file);
80 return session_fd;
81
82 file_error:
83 put_unused_fd(session_fd);
84 fd_error:
85 ltt_session_destroy(session);
86 return ret;
87 }
88
89 /**
90 * lttng_ioctl - lttng syscall through ioctl
91 *
92 * @filp: the file
93 * @cmd: the command
94 * @arg: command arg
95 *
96 * This ioctl implements lttng commands:
97 * LTTNG_SESSION
98 * Returns a LTTng trace session file descriptor
99 *
100 * The returned session will be deleted when its file descriptor is closed.
101 */
102 static
103 long lttng_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
104 {
105 switch (cmd) {
106 case LTTNG_SESSION:
107 return lttng_abi_create_session();
108 default:
109 return -ENOIOCTLCMD;
110 }
111 }
112
113 #ifdef CONFIG_COMPAT
114 static
115 long lttng_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
116 {
117 switch (cmd) {
118 case LTTNG_SESSION:
119 return lttng_abi_create_session();
120 default:
121 return -ENOIOCTLCMD;
122 }
123 }
124 #endif
125
126 static const struct file_operations lttng_fops = {
127 .unlocked_ioctl = lttng_ioctl,
128 #ifdef CONFIG_COMPAT
129 .compat_ioctl = lttng_compat_ioctl,
130 #endif
131 }
132
133 int lttng_abi_create_channel(struct file *session_filp,
134 struct lttng_channel __user *uchan_param)
135 {
136 struct ltt_session *session = session_filp->private_data;
137 struct ltt_channel *chan;
138 struct file *chan_filp;
139 struct lttng_channel chan_param;
140 int chan_fd;
141 int ret = 0;
142
143 if (copy_from_user(&chan_param, ucham_param, sizeof(chan_param)))
144 return -EFAULT;
145 chan = ltt_channel_create(session, chan_param->overwrite, NULL,
146 chan_param->subbuf_size,
147 chan_param->num_subbuf,
148 chan_param->switch_timer_interval,
149 chan_param->read_timer_interval);
150 if (!chan) {
151 ret = -ENOMEM;
152 goto chan_error;
153 }
154 chan_fd = get_unused_fd_flags(O_RDWR);
155 if (chan_fd < 0) {
156 ret = chan_fd;
157 goto fd_error;
158 }
159 chan_filp = anon_inode_getfile("[lttng_channel]",
160 &lttng_channel_fops,
161 chan, O_RDWR);
162 if (IS_ERR(chan_filp)) {
163 ret = PTR_ERR(chan_filp);
164 goto file_error;
165 }
166
167 /* The channel created holds a reference on the session */
168 atomic_inc(&session_filp->f_count);
169
170 return chan_fd;
171
172 file_error:
173 put_unused_fd(chan_fd);
174 fd_error:
175 ltt_channel_destroy(chan);
176 chan_error:
177 return ret;
178 }
179
180 /**
181 * lttng_session_ioctl - lttng session fd ioctl
182 *
183 * @filp: the file
184 * @cmd: the command
185 * @arg: command arg
186 *
187 * This ioctl implements lttng commands:
188 * LTTNG_CHANNEL
189 * Returns a LTTng channel file descriptor
190 *
191 * The returned channel will be deleted when its file descriptor is closed.
192 */
193 static
194 long lttng_session_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
195 {
196 switch (cmd) {
197 case LTTNG_CHANNEL:
198 return lttng_abi_create_channel(filp, (struct lttng_channel __user *)arg);
199 default:
200 return -ENOIOCTLCMD;
201 }
202 }
203
204 #ifdef CONFIG_COMPAT
205 static
206 long lttng_session_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
207 {
208 switch (cmd) {
209 case LTTNG_CHANNEL:
210 return lttng_abi_create_channel(filp, (struct lttng_channel __user *)arg);
211 default:
212 return -ENOIOCTLCMD;
213 }
214 }
215 #endif
216
217 static const struct file_operations lttng_session_fops = {
218 .unlocked_ioctl = lttng_session_ioctl,
219 #ifdef CONFIG_COMPAT
220 .compat_ioctl = lttng_session_compat_ioctl,
221 #endif
222 }
223
224 static
225 int lttng_abi_open_stream(struct file *channel_filp)
226 {
227 struct ltt_channel *channel = channel_filp->private_data;
228 struct lib_ring_buffer *buf;
229 int stream_fd, ret;
230
231 buf = ltt_buffer_read_open(channel->chan);
232 if (!buf)
233 return -ENOENT;
234
235 stream_fd = get_unused_fd_flags(O_RDWR);
236 if (stream_fd < 0) {
237 ret = stream_fd;
238 goto fd_error;
239 }
240 stream_filp = anon_inode_getfile("[lttng_stream]",
241 &lttng_stream_fops,
242 buf, O_RDWR);
243 if (IS_ERR(stream_filp)) {
244 ret = PTR_ERR(stream_filp);
245 goto file_error;
246 }
247
248 /* The stream holds a reference on the channel */
249 atomic_inc(&channel_filp->f_count);
250 return stream_fd;
251
252 file_error:
253 put_unused_fd(stream_fd);
254 fd_error:
255 ltt_buffer_read_close(buf);
256 return ret;
257 }
258
259
260 /**
261 * lttng_channel_ioctl - lttng syscall through ioctl
262 *
263 * @filp: the file
264 * @cmd: the command
265 * @arg: command arg
266 *
267 * This ioctl implements lttng commands:
268 * LTTNG_STREAM
269 * Returns an event stream file descriptor or failure.
270 * (typically, one event stream records events from one CPU)
271 * LTTNG_STREAM_NOTIFIER
272 * Returns a file descriptor that can be used to monitor
273 * addition/removal of streams to/from a channel. (e.g. notifier
274 * called on CPU hotplug).
275 * LTTNG_EVENT
276 * Returns an event file descriptor or failure.
277 *
278 * The returned session will be deleted when its file descriptor is closed.
279 * Channel and event file descriptors also hold a reference on the session.
280 */
281 static
282 long lttng_channel_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
283 {
284 switch (cmd) {
285 case LTTNG_STREAM:
286 return lttng_abi_open_stream(filp);
287 case LTTNG_STREAM_NOTIFIER:
288 return lttng_abi_open_stream_notifier(filp);
289 case LTTNG_EVENT:
290 return lttng_abi_create_event(filp, (struct lttng_event __user *)arg);
291 default:
292 return -ENOIOCTLCMD;
293 }
294 }
295
296 #ifdef CONFIG_COMPAT
297 static
298 long lttng_channel_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
299 {
300 switch (cmd) {
301 case LTTNG_STREAM:
302 return lttng_abi_get_stream(filp);
303 case LTTNG_STREAM_NOTIFIER:
304 return lttng_abi_get_stream_notifier(filp);
305 case LTTNG_EVENT:
306 return lttng_abi_create_event(filp, (struct lttng_event __user *)arg);
307 default:
308 return -ENOIOCTLCMD;
309 }
310 }
311 #endif
312
313 static const struct file_operations lttng_channel_fops = {
314 .unlocked_ioctl = lttng_channel_ioctl,
315 #ifdef CONFIG_COMPAT
316 .compat_ioctl = lttng_channel_compat_ioctl,
317 #endif
318 }
319
320 static int __init ltt_debugfs_abi_init(void)
321 {
322 int ret = 0;
323
324 lttng_dentry = debugfs_create_file("lttng", NULL);
325 if (IS_ERR(lttng_dentry) || !lttng_dentry)
326 printk(KERN_ERR "Error creating LTTng control file\n");
327 ret = -ENOMEM;
328 goto error;
329 }
330 error:
331 return ret;
332 }
333
334 static void __exit ltt_debugfs_abi_exit(void)
335 {
336 debugfs_remote(lttng_dentry);
337 }
This page took 0.045973 seconds and 4 git commands to generate.