Commit | Line | Data |
---|---|---|
b579acd9 DG |
1 | /* |
2 | * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca> | |
3 | * | |
1e307fab DG |
4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms of the GNU General Public License as published by the Free | |
6 | * Software Foundation; only version 2 of the License. | |
b579acd9 | 7 | * |
1e307fab DG |
8 | * This program is distributed in the hope that it will be useful, but WITHOUT |
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
11 | * more details. | |
b579acd9 | 12 | * |
1e307fab DG |
13 | * You should have received a copy of the GNU General Public License along with |
14 | * this program; if not, write to the Free Software Foundation, Inc., 59 Temple | |
15 | * Place - Suite 330, Boston, MA 02111-1307, USA. | |
b579acd9 DG |
16 | */ |
17 | ||
18 | #define _GNU_SOURCE | |
19 | #include <stdio.h> | |
20 | #include <stdlib.h> | |
21 | #include <string.h> | |
22 | #include <unistd.h> | |
54d01ffb | 23 | #include <urcu/list.h> |
1e307fab DG |
24 | |
25 | #include <lttng-sessiond-comm.h> | |
54d01ffb | 26 | #include <lttngerr.h> |
b579acd9 | 27 | |
2bdd86d4 MD |
28 | #ifdef CONFIG_LTTNG_TOOLS_HAVE_UST |
29 | #include <ust/lttng-ust-ctl.h> | |
30 | #include <ust/lttng-ust-abi.h> | |
31 | #else | |
32 | #include "lttng-ust-ctl.h" | |
33 | #include "lttng-ust-abi.h" | |
34 | #endif | |
35 | ||
b579acd9 | 36 | #include "context.h" |
1e307fab | 37 | #include "kernel-ctl.h" |
b579acd9 DG |
38 | |
39 | /* | |
40 | * Add kernel context to an event of a specific channel. | |
41 | */ | |
42 | static int add_kctx_to_event(struct lttng_kernel_context *kctx, | |
43 | struct ltt_kernel_channel *kchan, char *event_name) | |
44 | { | |
45 | int ret, found = 0; | |
46 | struct ltt_kernel_event *kevent; | |
47 | ||
48 | DBG("Add kernel context to event %s", event_name); | |
49 | ||
62499ad6 | 50 | kevent = trace_kernel_get_event_by_name(event_name, kchan); |
b579acd9 DG |
51 | if (kevent != NULL) { |
52 | ret = kernel_add_event_context(kevent, kctx); | |
53 | if (ret < 0) { | |
54 | goto error; | |
55 | } | |
56 | found = 1; | |
57 | } | |
58 | ||
59 | ret = found; | |
60 | ||
61 | error: | |
62 | return ret; | |
63 | } | |
64 | ||
65 | /* | |
66 | * Add kernel context to all channel. | |
67 | * | |
68 | * If event_name is specified, add context to event instead. | |
69 | */ | |
70 | static int add_kctx_all_channels(struct ltt_kernel_session *ksession, | |
71 | struct lttng_kernel_context *kctx, char *event_name) | |
72 | { | |
73 | int ret, no_event = 0, found = 0; | |
74 | struct ltt_kernel_channel *kchan; | |
75 | ||
76 | if (strlen(event_name) == 0) { | |
77 | no_event = 1; | |
78 | } | |
79 | ||
80 | DBG("Adding kernel context to all channels (event: %s)", event_name); | |
81 | ||
82 | /* Go over all channels */ | |
83 | cds_list_for_each_entry(kchan, &ksession->channel_list.head, list) { | |
84 | if (no_event) { | |
85 | ret = kernel_add_channel_context(kchan, kctx); | |
86 | if (ret < 0) { | |
87 | ret = LTTCOMM_KERN_CONTEXT_FAIL; | |
88 | goto error; | |
89 | } | |
90 | } else { | |
91 | ret = add_kctx_to_event(kctx, kchan, event_name); | |
92 | if (ret < 0) { | |
93 | ret = LTTCOMM_KERN_CONTEXT_FAIL; | |
94 | goto error; | |
95 | } else if (ret == 1) { | |
96 | /* Event found and context added */ | |
97 | found = 1; | |
98 | break; | |
99 | } | |
100 | } | |
101 | } | |
102 | ||
103 | if (!found && !no_event) { | |
104 | ret = LTTCOMM_NO_EVENT; | |
105 | goto error; | |
106 | } | |
107 | ||
108 | ret = LTTCOMM_OK; | |
109 | ||
110 | error: | |
111 | return ret; | |
112 | } | |
113 | ||
114 | /* | |
115 | * Add kernel context to a specific channel. | |
116 | * | |
117 | * If event_name is specified, add context to that event. | |
118 | */ | |
119 | static int add_kctx_to_channel(struct lttng_kernel_context *kctx, | |
120 | struct ltt_kernel_channel *kchan, char *event_name) | |
121 | { | |
122 | int ret, no_event = 0, found = 0; | |
123 | ||
124 | if (strlen(event_name) == 0) { | |
125 | no_event = 1; | |
126 | } | |
127 | ||
128 | DBG("Add kernel context to channel '%s', event '%s'", | |
129 | kchan->channel->name, event_name); | |
130 | ||
131 | if (no_event) { | |
132 | ret = kernel_add_channel_context(kchan, kctx); | |
133 | if (ret < 0) { | |
134 | ret = LTTCOMM_KERN_CONTEXT_FAIL; | |
135 | goto error; | |
136 | } | |
137 | } else { | |
138 | ret = add_kctx_to_event(kctx, kchan, event_name); | |
139 | if (ret < 0) { | |
140 | ret = LTTCOMM_KERN_CONTEXT_FAIL; | |
141 | goto error; | |
142 | } else if (ret == 1) { | |
143 | /* Event found and context added */ | |
144 | found = 1; | |
145 | } | |
146 | } | |
147 | ||
148 | if (!found && !no_event) { | |
149 | ret = LTTCOMM_NO_EVENT; | |
150 | goto error; | |
151 | } | |
152 | ||
153 | ret = LTTCOMM_OK; | |
154 | ||
155 | error: | |
156 | return ret; | |
157 | } | |
158 | ||
159 | /* | |
160 | * Add kernel context to tracer. | |
161 | */ | |
54d01ffb DG |
162 | int context_kernel_add(struct ltt_kernel_session *ksession, |
163 | struct lttng_event_context *ctx, char *event_name, | |
b579acd9 DG |
164 | char *channel_name) |
165 | { | |
166 | int ret; | |
167 | struct ltt_kernel_channel *kchan; | |
54d01ffb DG |
168 | struct lttng_kernel_context kctx; |
169 | ||
170 | /* Setup kernel context structure */ | |
171 | kctx.ctx = ctx->ctx; | |
172 | kctx.u.perf_counter.type = ctx->u.perf_counter.type; | |
173 | kctx.u.perf_counter.config = ctx->u.perf_counter.config; | |
174 | strncpy(kctx.u.perf_counter.name, ctx->u.perf_counter.name, | |
175 | LTTNG_SYMBOL_NAME_LEN); | |
176 | kctx.u.perf_counter.name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0'; | |
b579acd9 DG |
177 | |
178 | if (strlen(channel_name) == 0) { | |
54d01ffb | 179 | ret = add_kctx_all_channels(ksession, &kctx, event_name); |
b579acd9 DG |
180 | if (ret != LTTCOMM_OK) { |
181 | goto error; | |
182 | } | |
183 | } else { | |
184 | /* Get kernel channel */ | |
62499ad6 | 185 | kchan = trace_kernel_get_channel_by_name(channel_name, ksession); |
b579acd9 DG |
186 | if (kchan == NULL) { |
187 | ret = LTTCOMM_KERN_CHAN_NOT_FOUND; | |
188 | goto error; | |
189 | } | |
190 | ||
54d01ffb | 191 | ret = add_kctx_to_channel(&kctx, kchan, event_name); |
b579acd9 DG |
192 | if (ret != LTTCOMM_OK) { |
193 | goto error; | |
194 | } | |
195 | } | |
196 | ||
197 | ret = LTTCOMM_OK; | |
198 | ||
199 | error: | |
200 | return ret; | |
201 | } | |
2bdd86d4 MD |
202 | |
203 | /* | |
204 | * UST support. | |
205 | */ | |
206 | ||
207 | /* | |
208 | * Add UST context to an event of a specific channel. | |
209 | */ | |
210 | static int add_ustctx_to_event(struct ltt_ust_session *ustsession, | |
211 | struct lttng_ust_context *ustctx, | |
212 | struct ltt_ust_channel *ustchan, char *event_name) | |
213 | { | |
214 | int ret, found = 0; | |
215 | struct ltt_ust_event *ustevent; | |
216 | struct object_data *context_data; /* FIXME: currently a memleak */ | |
217 | ||
218 | DBG("Add UST context to event %s", event_name); | |
219 | ||
220 | ustevent = trace_ust_get_event_by_name(event_name, ustchan); | |
221 | if (ustevent != NULL) { | |
222 | ret = ustctl_add_context(ustsession->sock, ustctx, | |
223 | ustevent->obj, &context_data); | |
224 | if (ret < 0) { | |
225 | goto error; | |
226 | } | |
227 | found = 1; | |
228 | } | |
229 | ||
230 | ret = found; | |
231 | ||
232 | error: | |
233 | return ret; | |
234 | } | |
235 | ||
236 | /* | |
237 | * Add UST context to all channel. | |
238 | * | |
239 | * If event_name is specified, add context to event instead. | |
240 | */ | |
241 | static int add_ustctx_all_channels(struct ltt_ust_session *ustsession, | |
242 | struct lttng_ust_context *ustctx, char *event_name) | |
243 | { | |
244 | int ret, no_event = 0, found = 0; | |
245 | struct ltt_ust_channel *ustchan; | |
246 | struct object_data *context_data; /* FIXME: currently a memleak */ | |
247 | ||
248 | if (strlen(event_name) == 0) { | |
249 | no_event = 1; | |
250 | } | |
251 | ||
252 | DBG("Adding ust context to all channels (event: %s)", event_name); | |
253 | ||
254 | /* Go over all channels */ | |
255 | cds_list_for_each_entry(ustchan, &ustsession->channels.head, list) { | |
256 | if (no_event) { | |
257 | ret = ustctl_add_context(ustsession->sock, | |
258 | ustctx, ustchan->obj, &context_data); | |
259 | if (ret < 0) { | |
260 | ret = LTTCOMM_UST_CONTEXT_FAIL; | |
261 | goto error; | |
262 | } | |
263 | } else { | |
264 | ret = add_ustctx_to_event(ustsession, ustctx, ustchan, event_name); | |
265 | if (ret < 0) { | |
266 | ret = LTTCOMM_UST_CONTEXT_FAIL; | |
267 | goto error; | |
268 | } else if (ret == 1) { | |
269 | /* Event found and context added */ | |
270 | found = 1; | |
271 | break; | |
272 | } | |
273 | } | |
274 | } | |
275 | ||
276 | if (!found && !no_event) { | |
277 | ret = LTTCOMM_NO_EVENT; | |
278 | goto error; | |
279 | } | |
280 | ||
281 | ret = LTTCOMM_OK; | |
282 | ||
283 | error: | |
284 | return ret; | |
285 | } | |
286 | ||
287 | /* | |
288 | * Add UST context to a specific channel. | |
289 | * | |
290 | * If event_name is specified, add context to that event. | |
291 | */ | |
292 | static int add_ustctx_to_channel(struct ltt_ust_session *ustsession, | |
293 | struct lttng_ust_context *ustctx, | |
294 | struct ltt_ust_channel *ustchan, char *event_name) | |
295 | { | |
296 | int ret, no_event = 0, found = 0; | |
297 | struct object_data *context_data; /* FIXME: currently a memleak */ | |
298 | ||
299 | if (strlen(event_name) == 0) { | |
300 | no_event = 1; | |
301 | } | |
302 | ||
303 | DBG("Add UST context to channel '%s', event '%s'", | |
304 | ustchan->name, event_name); | |
305 | ||
306 | if (no_event) { | |
307 | ret = ustctl_add_context(ustsession->sock, ustctx, | |
308 | ustchan->obj, &context_data); | |
309 | if (ret < 0) { | |
310 | ret = LTTCOMM_UST_CONTEXT_FAIL; | |
311 | goto error; | |
312 | } | |
313 | } else { | |
314 | ret = add_ustctx_to_event(ustsession, ustctx, ustchan, event_name); | |
315 | if (ret < 0) { | |
316 | ret = LTTCOMM_UST_CONTEXT_FAIL; | |
317 | goto error; | |
318 | } else if (ret == 1) { | |
319 | /* Event found and context added */ | |
320 | found = 1; | |
321 | } | |
322 | } | |
323 | ||
324 | if (!found && !no_event) { | |
325 | ret = LTTCOMM_NO_EVENT; | |
326 | goto error; | |
327 | } | |
328 | ||
329 | ret = LTTCOMM_OK; | |
330 | ||
331 | error: | |
332 | return ret; | |
333 | } | |
334 | ||
335 | /* | |
336 | * Add UST context to tracer. | |
337 | */ | |
338 | int context_ust_add(struct ltt_ust_session *ustsession, | |
339 | struct lttng_event_context *ctx, char *event_name, | |
340 | char *channel_name) | |
341 | { | |
342 | int ret; | |
343 | struct ltt_ust_channel *ustchan; | |
344 | struct lttng_ust_context ustctx; | |
345 | ||
346 | /* Setup UST context structure */ | |
347 | ustctx.ctx = ctx->ctx; | |
348 | ||
349 | if (strlen(channel_name) == 0) { | |
350 | ret = add_ustctx_all_channels(ustsession, &ustctx, event_name); | |
351 | if (ret != LTTCOMM_OK) { | |
352 | goto error; | |
353 | } | |
354 | } else { | |
355 | /* Get UST channel */ | |
356 | ustchan = trace_ust_get_channel_by_name(channel_name, ustsession); | |
357 | if (ustchan == NULL) { | |
358 | ret = LTTCOMM_UST_CHAN_NOT_FOUND; | |
359 | goto error; | |
360 | } | |
361 | ||
362 | ret = add_ustctx_to_channel(ustsession, &ustctx, ustchan, event_name); | |
363 | if (ret != LTTCOMM_OK) { | |
364 | goto error; | |
365 | } | |
366 | } | |
367 | ||
368 | ret = LTTCOMM_OK; | |
369 | ||
370 | error: | |
371 | return ret; | |
372 | } |