Initial work for kernel tracing support
[lttng-tools.git] / ltt-sessiond / kernel-ctl.c
1 /*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19 #define _GNU_SOURCE
20 #include <errno.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <string.h>
24 #include <unistd.h>
25
26 #include "lttngerr.h"
27 #include "ltt-sessiond.h"
28 #include "libkernelctl.h"
29 #include "kernel-ctl.h"
30 #include "trace.h"
31
32 /*
33 * kernel_create_session
34 *
35 * Create a new kernel session using the command context session.
36 */
37 int kernel_create_session(struct ltt_session *session, int tracer_fd)
38 {
39 int ret;
40 struct ltt_kernel_session *lks;
41
42 /* Allocate a new kernel session */
43 lks = malloc(sizeof(struct ltt_kernel_session));
44 if (lks == NULL) {
45 perror("kernel session malloc");
46 ret = -errno;
47 goto error;
48 }
49
50 ret = kernctl_create_session(tracer_fd);
51 if (ret < 0) {
52 goto error;
53 }
54
55 /* Assigning session fd and to the command context */
56 lks->fd = ret;
57 lks->channel_count = 0;
58 lks->stream_count_global = 0;
59 session->kernel_session = lks;
60 session->kern_session_count++;
61 CDS_INIT_LIST_HEAD(&lks->channel_list.head);
62
63 DBG("Kernel session created (fd: %d)", lks->fd);
64
65 return 0;
66
67 error:
68 return ret;
69 }
70
71 /*
72 * kernel_create_channel
73 *
74 * Create a kernel channel within the kernel session.
75 */
76 int kernel_create_channel(struct ltt_kernel_session *session)
77 {
78 int ret;
79 struct ltt_kernel_channel *lkc;
80 struct lttng_kernel_channel *chan;
81
82 lkc = malloc(sizeof(struct ltt_kernel_channel));
83 chan = malloc(sizeof(struct lttng_kernel_channel));
84
85 if (lkc == NULL || chan == NULL) {
86 perror("kernel channel malloc");
87 ret = -errno;
88 goto error;
89 }
90
91 chan->overwrite = DEFAULT_KERNEL_OVERWRITE;
92 chan->subbuf_size = DEFAULT_KERNEL_SUBBUF_SIZE;
93 chan->num_subbuf = DEFAULT_KERNEL_SUBBUF_NUM;
94 chan->switch_timer_interval = DEFAULT_KERNEL_SWITCH_TIMER;
95 chan->read_timer_interval = DEFAULT_KERNEL_READ_TIMER;
96
97 ret = kernctl_create_channel(session->fd, chan);
98 if (ret < 0) {
99 perror("ioctl create channel");
100 goto error;
101 }
102
103 /* Setup the channel */
104 lkc->fd = ret;
105 lkc->channel = chan;
106 lkc->stream_count = 0;
107 ret = asprintf(&lkc->pathname, "%s", DEFAULT_TRACE_OUTPUT);
108 if (ret < 0) {
109 perror("asprintf kernel create channel");
110 goto error;
111 }
112
113 DBG("Channel path set to %s", lkc->pathname);
114
115 CDS_INIT_LIST_HEAD(&lkc->events_list.head);
116 CDS_INIT_LIST_HEAD(&lkc->stream_list.head);
117 cds_list_add(&lkc->list, &session->channel_list.head);
118 session->channel_count++;
119
120 DBG("Kernel channel created (fd: %d)", lkc->fd);
121
122 return 0;
123
124 error:
125 return ret;
126 }
127
128 /*
129 * kernel_enable_event
130 *
131 * Enable kernel event.
132 */
133 int kernel_enable_event(struct ltt_kernel_session *session, char *name)
134 {
135 int ret;
136 struct ltt_kernel_channel *chan;
137 struct ltt_kernel_event *event;
138 struct lttng_kernel_event *lke;
139
140 event = malloc(sizeof(struct ltt_kernel_event));
141 lke = malloc(sizeof(struct lttng_kernel_event));
142
143 if (event == NULL || lke == NULL) {
144 perror("kernel enable event malloc");
145 ret = -errno;
146 goto error;
147 }
148
149 /* Setting up a kernel event */
150 strncpy(lke->name, name, LTTNG_SYM_NAME_LEN);
151 lke->instrumentation = LTTNG_KERNEL_TRACEPOINTS;
152 event->event = lke;
153
154 cds_list_for_each_entry(chan, &session->channel_list.head, list) {
155 ret = kernctl_create_event(chan->fd, lke);
156 if (ret < 0) {
157 goto error;
158 }
159
160 event->fd = ret;
161 /* Add event to event list */
162 cds_list_add(&event->list, &chan->events_list.head);
163 DBG("Event %s enabled (fd: %d)", name, event->fd);
164 }
165
166 return 0;
167
168 error:
169 return ret;
170 }
171
172 /*
173 * kernel_open_metadata
174 *
175 * Open metadata stream.
176 */
177 int kernel_open_metadata(struct ltt_kernel_session *session)
178 {
179 int ret;
180 struct ltt_kernel_metadata *lkm;
181 struct lttng_kernel_channel *conf;
182
183 lkm = malloc(sizeof(struct ltt_kernel_metadata));
184 conf = malloc(sizeof(struct lttng_kernel_channel));
185
186 if (lkm == NULL || conf == NULL) {
187 perror("kernel open metadata malloc");
188 ret = -errno;
189 goto error;
190 }
191
192 conf->overwrite = DEFAULT_KERNEL_OVERWRITE;
193 conf->subbuf_size = DEFAULT_KERNEL_SUBBUF_SIZE;
194 conf->num_subbuf = DEFAULT_KERNEL_SUBBUF_NUM;
195 conf->switch_timer_interval = DEFAULT_KERNEL_SWITCH_TIMER;
196 conf->read_timer_interval = DEFAULT_KERNEL_READ_TIMER;
197
198 ret = kernctl_open_metadata(session->fd, conf);
199 if (ret < 0) {
200 goto error;
201 }
202
203 lkm->fd = ret;
204 lkm->conf = conf;
205 ret = asprintf(&lkm->pathname, "%s/metadata", DEFAULT_TRACE_OUTPUT);
206 if (ret < 0) {
207 perror("asprintf kernel metadata");
208 goto error;
209 }
210 session->metadata = lkm;
211
212 DBG("Kernel metadata opened (fd: %d)", lkm->fd);
213
214 return 0;
215
216 error:
217 return ret;
218 }
219
220 /*
221 * kernel_start_session
222 *
223 * Start tracing session.
224 */
225 int kernel_start_session(struct ltt_kernel_session *session)
226 {
227 int ret;
228
229 ret = kernctl_start_session(session->fd);
230 if (ret < 0) {
231 goto error;
232 }
233
234 DBG("Kernel session started");
235
236 return 0;
237
238 error:
239 return ret;
240 }
241
242 /*
243 * kernel_stop_session
244 *
245 * Stop tracing session.
246 */
247 int kernel_stop_session(struct ltt_kernel_session *session)
248 {
249 int ret;
250
251 ret = kernctl_stop_session(session->fd);
252 if (ret < 0) {
253 goto error;
254 }
255
256 DBG("Kernel session stopped");
257
258 return 0;
259
260 error:
261 return ret;
262 }
263
264 /*
265 * kernel_create_channel_stream
266 *
267 * Create a stream for a channel.
268 *
269 * Return the number of created stream. Else, a negative value.
270 */
271 int kernel_create_channel_stream(struct ltt_kernel_channel *channel)
272 {
273 int ret;
274 struct ltt_kernel_stream *lks;
275
276 while ((ret = kernctl_create_stream(channel->fd)) > 0) {
277 lks = malloc(sizeof(struct ltt_kernel_stream));
278 if (lks == NULL) {
279 perror("kernel create stream malloc");
280 ret = -errno;
281 goto error;
282 }
283
284 lks->fd = ret;
285 ret = asprintf(&lks->pathname, "%s/trace_%d",
286 channel->pathname, channel->stream_count);
287 if (ret < 0) {
288 perror("asprintf kernel create stream");
289 goto error;
290 }
291 lks->state = 0;
292
293 cds_list_add(&lks->list, &channel->stream_list.head);
294 channel->stream_count++;
295 }
296
297 DBG("Kernel channel stream created (num: %d)", channel->stream_count);
298
299 return channel->stream_count;
300
301 error:
302 return ret;
303 }
304
305 /*
306 * kernel_create_metadata_stream
307 *
308 * Create the metadata stream.
309 */
310 int kernel_create_metadata_stream(struct ltt_kernel_session *session)
311 {
312 int ret;
313
314 ret = kernctl_create_stream(session->metadata->fd);
315 if (ret < 0) {
316 perror("kernel create metadata stream");
317 ret = -errno;
318 goto error;
319 }
320
321 DBG("Kernel metadata stream created (fd: %d)", ret);
322 session->metadata_stream_fd = ret;
323
324 return 0;
325
326 error:
327 return ret;
328 }
This page took 0.037229 seconds and 5 git commands to generate.