ongoing ABI implementation
[lttng-modules.git] / ltt-debugfs-abi.c
CommitLineData
baf20995
MD
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.
ad1c05e1
MD
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.
baf20995
MD
23 */
24
25#include <linux/debugfs.h>
ad1c05e1 26#include "ltt-events.h"
baf20995
MD
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
33static struct dentry *lttng_dentry;
ad1c05e1
MD
34static const struct file_operations lttng_fops;
35static const struct file_operations lttng_session_fops;
36static const struct file_operations lttng_channel_fops;
baf20995
MD
37
38/*
39 * LTTng DebugFS ABI structures.
40 */
41
42struct 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
51struct lttng_event {
52 int channel; /* Channel file descriptor */
53 enum instrum_type itype;
54 char name[];
55};
56
ad1c05e1 57static
baf20995
MD
58int 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]",
ad1c05e1 73 &lttng_session_fops,
baf20995
MD
74 session, O_RDWR);
75 if (IS_ERR(session_file)) {
76 ret = PTR_ERR(session_file);
77 goto file_error;
78 }
ad1c05e1 79 fd_install(session_fd, session_file);
baf20995
MD
80 return session_fd;
81
82file_error:
83 put_unused_fd(session_fd);
84fd_error:
85 ltt_session_destroy(session);
86 return ret;
87}
88
ad1c05e1
MD
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 */
102static
103long 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
114static
115long 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
126static 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
133int lttng_abi_create_channel(struct file *session_filp,
134 struct lttng_channel __user *uchan_param)
baf20995 135{
ad1c05e1 136 struct ltt_session *session = session_filp->private_data;
baf20995 137 struct ltt_channel *chan;
ad1c05e1 138 struct file *chan_filp;
baf20995
MD
139 struct lttng_channel chan_param;
140 int chan_fd;
ad1c05e1 141 int ret = 0;
baf20995
MD
142
143 if (copy_from_user(&chan_param, ucham_param, sizeof(chan_param)))
144 return -EFAULT;
ad1c05e1
MD
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 }
baf20995
MD
154 chan_fd = get_unused_fd_flags(O_RDWR);
155 if (chan_fd < 0) {
156 ret = chan_fd;
157 goto fd_error;
158 }
ad1c05e1
MD
159 chan_filp = anon_inode_getfile("[lttng_channel]",
160 &lttng_channel_fops,
baf20995 161 chan, O_RDWR);
ad1c05e1
MD
162 if (IS_ERR(chan_filp)) {
163 ret = PTR_ERR(chan_filp);
baf20995
MD
164 goto file_error;
165 }
ad1c05e1
MD
166
167 /* The channel created holds a reference on the session */
168 atomic_inc(&session_filp->f_count);
169
baf20995
MD
170 return chan_fd;
171
172file_error:
173 put_unused_fd(chan_fd);
174fd_error:
175 ltt_channel_destroy(chan);
ad1c05e1 176chan_error:
baf20995
MD
177 return ret;
178}
179
180/**
ad1c05e1 181 * lttng_session_ioctl - lttng session fd ioctl
baf20995
MD
182 *
183 * @filp: the file
184 * @cmd: the command
185 * @arg: command arg
186 *
187 * This ioctl implements lttng commands:
baf20995
MD
188 * LTTNG_CHANNEL
189 * Returns a LTTng channel file descriptor
ad1c05e1
MD
190 *
191 * The returned channel will be deleted when its file descriptor is closed.
192 */
193static
194long 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
205static
206long 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
217static 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
224static
225int 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
252file_error:
253 put_unused_fd(stream_fd);
254fd_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).
baf20995 275 * LTTNG_EVENT
ad1c05e1 276 * Returns an event file descriptor or failure.
baf20995
MD
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 */
ad1c05e1
MD
281static
282long lttng_channel_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
baf20995 283{
baf20995 284 switch (cmd) {
ad1c05e1
MD
285 case LTTNG_STREAM:
286 return lttng_abi_open_stream(filp);
287 case LTTNG_STREAM_NOTIFIER:
288 return lttng_abi_open_stream_notifier(filp);
baf20995 289 case LTTNG_EVENT:
ad1c05e1 290 return lttng_abi_create_event(filp, (struct lttng_event __user *)arg);
baf20995
MD
291 default:
292 return -ENOIOCTLCMD;
293 }
294}
295
296#ifdef CONFIG_COMPAT
ad1c05e1
MD
297static
298long lttng_channel_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
baf20995 299{
baf20995 300 switch (cmd) {
ad1c05e1
MD
301 case LTTNG_STREAM:
302 return lttng_abi_get_stream(filp);
303 case LTTNG_STREAM_NOTIFIER:
304 return lttng_abi_get_stream_notifier(filp);
baf20995 305 case LTTNG_EVENT:
ad1c05e1 306 return lttng_abi_create_event(filp, (struct lttng_event __user *)arg);
baf20995
MD
307 default:
308 return -ENOIOCTLCMD;
309 }
310}
311#endif
312
ad1c05e1
MD
313static const struct file_operations lttng_channel_fops = {
314 .unlocked_ioctl = lttng_channel_ioctl,
baf20995 315#ifdef CONFIG_COMPAT
ad1c05e1 316 .compat_ioctl = lttng_channel_compat_ioctl,
baf20995
MD
317#endif
318}
319
320static 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 }
330error:
331 return ret;
332}
333
334static void __exit ltt_debugfs_abi_exit(void)
335{
336 debugfs_remote(lttng_dentry);
337}
This page took 0.036635 seconds and 4 git commands to generate.