Fix: destroy context hash table being NULL
[lttng-tools.git] / src / bin / lttng-sessiond / event.c
CommitLineData
54d01ffb
DG
1/*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
3 *
d14d33bf
AM
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2 only,
6 * as published by the Free Software Foundation.
54d01ffb 7 *
d14d33bf
AM
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
54d01ffb 12 *
d14d33bf
AM
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
54d01ffb
DG
16 */
17
be040666 18#define _GNU_SOURCE
d87bfb32 19#include <errno.h>
54d01ffb 20#include <urcu/list.h>
2bdd86d4 21#include <string.h>
54d01ffb
DG
22
23#include <lttng/lttng.h>
db758600 24#include <common/error.h>
10a8a223 25#include <common/sessiond-comm/sessiond-comm.h>
54d01ffb
DG
26
27#include "channel.h"
28#include "event.h"
4771f025 29#include "kernel.h"
9df8df5e 30#include "ust-ctl.h"
edb67388
DG
31#include "ust-app.h"
32#include "trace-kernel.h"
33#include "trace-ust.h"
54d01ffb 34
8c9ae521
DG
35/*
36 * Setup a lttng_event used to enable *all* syscall tracing.
37 */
38static void init_syscalls_kernel_event(struct lttng_event *event)
39{
40 event->name[0] = '\0';
41 /*
42 * We use LTTNG_EVENT* here since the trace kernel creation will make the
43 * right changes for the kernel.
44 */
45 event->type = LTTNG_EVENT_SYSCALL;
46}
47
54d01ffb 48/*
7a3d1328 49 * Disable kernel tracepoint event for a channel from the kernel session.
54d01ffb 50 */
7a3d1328 51int event_kernel_disable_tracepoint(struct ltt_kernel_session *ksession,
54d01ffb
DG
52 struct ltt_kernel_channel *kchan, char *event_name)
53{
54 int ret;
55 struct ltt_kernel_event *kevent;
56
57 kevent = trace_kernel_get_event_by_name(event_name, kchan);
58 if (kevent == NULL) {
59 ret = LTTCOMM_NO_EVENT;
60 goto error;
61 }
62
63 ret = kernel_disable_event(kevent);
64 if (ret < 0) {
65 ret = LTTCOMM_KERN_DISABLE_FAIL;
66 goto error;
67 }
68
69 DBG("Kernel event %s disable for channel %s.",
70 kevent->event->name, kchan->channel->name);
71
72 ret = LTTCOMM_OK;
73
74error:
75 return ret;
76}
77
78/*
7a3d1328 79 * Disable kernel tracepoint events for a channel from the kernel session.
54d01ffb 80 */
7a3d1328 81int event_kernel_disable_all_tracepoints(struct ltt_kernel_session *ksession,
54d01ffb
DG
82 struct ltt_kernel_channel *kchan)
83{
84 int ret;
85 struct ltt_kernel_event *kevent;
86
87 /* For each event in the kernel session */
88 cds_list_for_each_entry(kevent, &kchan->events_list.head, list) {
89 ret = kernel_disable_event(kevent);
90 if (ret < 0) {
91 /* We continue disabling the rest */
92 continue;
93 }
94 }
54d01ffb 95 ret = LTTCOMM_OK;
7a3d1328
MD
96 return ret;
97}
98
99/*
100 * Disable kernel syscall events for a channel from the kernel session.
101 */
102int event_kernel_disable_all_syscalls(struct ltt_kernel_session *ksession,
103 struct ltt_kernel_channel *kchan)
104{
105 ERR("Cannot disable syscall tracing for existing session. Please destroy session instead.");
106 return LTTCOMM_OK; /* Return OK so disable all succeeds */
107}
54d01ffb 108
7a3d1328
MD
109/*
110 * Disable all kernel event for a channel from the kernel session.
111 */
112int event_kernel_disable_all(struct ltt_kernel_session *ksession,
113 struct ltt_kernel_channel *kchan)
114{
115 int ret;
116
117 ret = event_kernel_disable_all_tracepoints(ksession, kchan);
118 if (ret != LTTCOMM_OK)
119 return ret;
120 ret = event_kernel_disable_all_syscalls(ksession, kchan);
54d01ffb
DG
121 return ret;
122}
123
124/*
7a3d1328 125 * Enable kernel tracepoint event for a channel from the kernel session.
54d01ffb 126 */
7a3d1328 127int event_kernel_enable_tracepoint(struct ltt_kernel_session *ksession,
54d01ffb
DG
128 struct ltt_kernel_channel *kchan, struct lttng_event *event)
129{
130 int ret;
131 struct ltt_kernel_event *kevent;
132
133 kevent = trace_kernel_get_event_by_name(event->name, kchan);
134 if (kevent == NULL) {
135 ret = kernel_create_event(event, kchan);
136 if (ret < 0) {
d87bfb32
DG
137 if (ret == -EEXIST) {
138 ret = LTTCOMM_KERN_EVENT_EXIST;
139 } else {
140 ret = LTTCOMM_KERN_ENABLE_FAIL;
141 }
7a3d1328 142 goto end;
54d01ffb
DG
143 }
144 } else if (kevent->enabled == 0) {
145 ret = kernel_enable_event(kevent);
146 if (ret < 0) {
147 ret = LTTCOMM_KERN_ENABLE_FAIL;
7a3d1328 148 goto end;
54d01ffb 149 }
42224349
DG
150 } else {
151 /* At this point, the event is considered enabled */
152 ret = LTTCOMM_KERN_EVENT_EXIST;
153 goto end;
54d01ffb 154 }
42224349 155
54d01ffb 156 ret = LTTCOMM_OK;
7a3d1328 157end:
54d01ffb
DG
158 return ret;
159}
160
161/*
7a3d1328 162 * Enable all kernel tracepoint events of a channel of the kernel session.
54d01ffb 163 */
7a3d1328 164int event_kernel_enable_all_tracepoints(struct ltt_kernel_session *ksession,
54d01ffb
DG
165 struct ltt_kernel_channel *kchan, int kernel_tracer_fd)
166{
167 int size, i, ret;
168 struct ltt_kernel_event *kevent;
8f69e5eb 169 struct lttng_event *event_list = NULL;
54d01ffb
DG
170
171 /* For each event in the kernel session */
172 cds_list_for_each_entry(kevent, &kchan->events_list.head, list) {
8f69e5eb
DG
173 if (kevent->enabled == 0) {
174 ret = kernel_enable_event(kevent);
175 if (ret < 0) {
176 /* Enable failed but still continue */
177 continue;
178 }
54d01ffb
DG
179 }
180 }
181
182 size = kernel_list_events(kernel_tracer_fd, &event_list);
183 if (size < 0) {
184 ret = LTTCOMM_KERN_LIST_FAIL;
7a3d1328 185 goto end;
54d01ffb
DG
186 }
187
188 for (i = 0; i < size; i++) {
189 kevent = trace_kernel_get_event_by_name(event_list[i].name, kchan);
190 if (kevent == NULL) {
191 /* Default event type for enable all */
192 event_list[i].type = LTTNG_EVENT_TRACEPOINT;
193 /* Enable each single tracepoint event */
194 ret = kernel_create_event(&event_list[i], kchan);
195 if (ret < 0) {
196 /* Ignore error here and continue */
197 }
198 }
199 }
54d01ffb 200 free(event_list);
8f69e5eb 201
54d01ffb 202 ret = LTTCOMM_OK;
7a3d1328 203end:
54d01ffb 204 return ret;
7a3d1328 205
54d01ffb 206}
8c9ae521
DG
207
208/*
7a3d1328 209 * Enable all kernel tracepoint events of a channel of the kernel session.
8c9ae521 210 */
7a3d1328 211int event_kernel_enable_all_syscalls(struct ltt_kernel_session *ksession,
8c9ae521
DG
212 struct ltt_kernel_channel *kchan, int kernel_tracer_fd)
213{
214 int ret;
215 struct lttng_event event;
216
217 init_syscalls_kernel_event(&event);
218
219 DBG("Enabling all syscall tracing");
220
221 ret = kernel_create_event(&event, kchan);
222 if (ret < 0) {
8f69e5eb
DG
223 if (ret == -EEXIST) {
224 ret = LTTCOMM_KERN_EVENT_EXIST;
225 } else {
226 ret = LTTCOMM_KERN_ENABLE_FAIL;
227 }
7a3d1328 228 goto end;
8c9ae521 229 }
8f69e5eb 230
8c9ae521 231 ret = LTTCOMM_OK;
7a3d1328
MD
232end:
233 return ret;
234}
8c9ae521 235
7a3d1328
MD
236/*
237 * Enable all kernel events of a channel of the kernel session.
238 */
239int event_kernel_enable_all(struct ltt_kernel_session *ksession,
240 struct ltt_kernel_channel *kchan, int kernel_tracer_fd)
241{
242 int ret;
243
244 ret = event_kernel_enable_all_tracepoints(ksession, kchan, kernel_tracer_fd);
245 if (ret != LTTCOMM_OK) {
246 goto end;
247 }
248 ret = event_kernel_enable_all_syscalls(ksession, kchan, kernel_tracer_fd);
249end:
8c9ae521
DG
250 return ret;
251}
2bdd86d4 252
7f79d3a1
DG
253/*
254 * ============================
255 * UST : The Ultimate Frontier!
256 * ============================
257 */
258
76d45b40
DG
259/*
260 * Enable all UST tracepoints for a channel from a UST session.
261 */
262int event_ust_enable_all_tracepoints(struct ltt_ust_session *usess, int domain,
263 struct ltt_ust_channel *uchan)
264{
265 int ret, i;
266 size_t size;
bec39940 267 struct lttng_ht_iter iter;
76d45b40 268 struct ltt_ust_event *uevent = NULL;
7f79d3a1 269 struct lttng_event *events = NULL;
76d45b40
DG
270
271 switch (domain) {
272 case LTTNG_DOMAIN_UST:
273 {
274 /* Enable existing events */
bec39940
DG
275 cds_lfht_for_each_entry(uchan->events->ht, &iter.iter, uevent,
276 node.node) {
76d45b40
DG
277 if (uevent->enabled == 0) {
278 ret = ust_app_enable_event_glb(usess, uchan, uevent);
279 if (ret < 0) {
280 continue;
281 }
282 uevent->enabled = 1;
283 }
284 }
285
286 /* Get all UST available events */
287 size = ust_app_list_events(&events);
288 if (size < 0) {
289 ret = LTTCOMM_UST_LIST_FAIL;
290 goto error;
291 }
292
293 for (i = 0; i < size; i++) {
294 /*
295 * Check if event exist and if so, continue since it was enable
296 * previously.
297 */
298 uevent = trace_ust_find_event_by_name(uchan->events,
299 events[i].name);
300 if (uevent != NULL) {
301 ret = ust_app_enable_event_pid(usess, uchan, uevent,
302 events[i].pid);
303 if (ret < 0) {
304 if (ret != -EEXIST) {
305 ret = LTTCOMM_UST_ENABLE_FAIL;
306 goto error;
307 }
308 }
309 continue;
310 }
311
312 /* Create ust event */
313 uevent = trace_ust_create_event(&events[i]);
314 if (uevent == NULL) {
315 ret = LTTCOMM_FATAL;
7f79d3a1 316 goto error_destroy;
76d45b40
DG
317 }
318
319 /* Create event for the specific PID */
320 ret = ust_app_enable_event_pid(usess, uchan, uevent,
321 events[i].pid);
322 if (ret < 0) {
323 if (ret == -EEXIST) {
324 ret = LTTCOMM_UST_EVENT_EXIST;
7f79d3a1 325 goto error;
76d45b40
DG
326 } else {
327 ret = LTTCOMM_UST_ENABLE_FAIL;
7f79d3a1 328 goto error_destroy;
76d45b40 329 }
76d45b40
DG
330 }
331
332 uevent->enabled = 1;
333 /* Add ltt ust event to channel */
334 rcu_read_lock();
bec39940 335 lttng_ht_add_unique_str(uchan->events, &uevent->node);
76d45b40
DG
336 rcu_read_unlock();
337 }
338
339 free(events);
340 break;
341 }
d78d6610 342#if 0
76d45b40
DG
343 case LTTNG_DOMAIN_UST_EXEC_NAME:
344 case LTTNG_DOMAIN_UST_PID:
345 case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
d78d6610 346#endif
76d45b40 347 default:
1ab1ea0b 348 ret = LTTCOMM_UND;
76d45b40
DG
349 goto error;
350 }
351
352 return LTTCOMM_OK;
353
7f79d3a1 354error_destroy:
76d45b40 355 trace_ust_destroy_event(uevent);
7f79d3a1
DG
356
357error:
358 free(events);
76d45b40
DG
359 return ret;
360}
361
2bdd86d4
MD
362/*
363 * Enable UST tracepoint event for a channel from a UST session.
364 */
edb67388
DG
365int event_ust_enable_tracepoint(struct ltt_ust_session *usess, int domain,
366 struct ltt_ust_channel *uchan, struct lttng_event *event)
2bdd86d4 367{
fc34caaa 368 int ret = LTTCOMM_OK, to_create = 0;
edb67388
DG
369 struct ltt_ust_event *uevent;
370
371 uevent = trace_ust_find_event_by_name(uchan->events, event->name);
372 if (uevent == NULL) {
373 uevent = trace_ust_create_event(event);
374 if (uevent == NULL) {
375 ret = LTTCOMM_FATAL;
376 goto error;
377 }
fc34caaa 378 /* Valid to set it after the goto error since uevent is still NULL */
edb67388
DG
379 to_create = 1;
380 }
2bdd86d4 381
7f79d3a1
DG
382 if (uevent->enabled) {
383 /* It's already enabled so everything is OK */
7f79d3a1
DG
384 goto end;
385 }
386
fc34caaa
DG
387 uevent->enabled = 1;
388
edb67388
DG
389 switch (domain) {
390 case LTTNG_DOMAIN_UST:
391 {
392 if (to_create) {
393 /* Create event on all UST registered apps for session */
35a9059d 394 ret = ust_app_create_event_glb(usess, uchan, uevent);
edb67388
DG
395 } else {
396 /* Enable event on all UST registered apps for session */
35a9059d 397 ret = ust_app_enable_event_glb(usess, uchan, uevent);
edb67388 398 }
48842b30 399
edb67388
DG
400 if (ret < 0) {
401 if (ret == -EEXIST) {
402 ret = LTTCOMM_UST_EVENT_EXIST;
7f79d3a1 403 goto end;
edb67388
DG
404 } else {
405 ret = LTTCOMM_UST_ENABLE_FAIL;
7f79d3a1 406 goto error;
edb67388 407 }
edb67388 408 }
edb67388
DG
409 break;
410 }
d78d6610 411#if 0
edb67388
DG
412 case LTTNG_DOMAIN_UST_EXEC_NAME:
413 case LTTNG_DOMAIN_UST_PID:
414 case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
d78d6610 415#endif
edb67388 416 default:
1ab1ea0b 417 ret = LTTCOMM_UND;
7f79d3a1 418 goto end;
2bdd86d4 419 }
48842b30 420
7f79d3a1
DG
421 if (to_create) {
422 rcu_read_lock();
fc34caaa 423 /* Add ltt ust event to channel */
bec39940 424 lttng_ht_add_unique_str(uchan->events, &uevent->node);
7f79d3a1
DG
425 rcu_read_unlock();
426 }
edb67388 427
7f79d3a1
DG
428 DBG("Event UST %s %s in channel %s", uevent->attr.name,
429 to_create ? "created" : "enabled", uchan->name);
430
fc34caaa
DG
431 ret = LTTCOMM_OK;
432
fb89d070 433end:
fc34caaa 434 return ret;
edb67388
DG
435
436error:
fc34caaa
DG
437 /*
438 * Only destroy event on creation time (not enabling time) because if the
439 * event is found in the channel (to_create == 0), it means that at some
440 * point the enable_event worked and it's thus valid to keep it alive.
441 * Destroying it also implies that we also destroy it's shadow copy to sync
442 * everyone up.
443 */
444 if (to_create) {
445 /* In this code path, the uevent was not added to the hash table */
446 trace_ust_destroy_event(uevent);
447 }
2bdd86d4
MD
448 return ret;
449}
450
7f79d3a1
DG
451/*
452 * Disable UST tracepoint of a channel from a UST session.
453 */
454int event_ust_disable_tracepoint(struct ltt_ust_session *usess, int domain,
455 struct ltt_ust_channel *uchan, char *event_name)
2bdd86d4
MD
456{
457 int ret;
7f79d3a1 458 struct ltt_ust_event *uevent;
2bdd86d4 459
7f79d3a1
DG
460 uevent = trace_ust_find_event_by_name(uchan->events, event_name);
461 if (uevent == NULL) {
462 ret = LTTCOMM_UST_EVENT_NOT_FOUND;
463 goto error;
2bdd86d4 464 }
7f79d3a1
DG
465
466 if (uevent->enabled == 0) {
467 /* It's already enabled so everything is OK */
468 ret = LTTCOMM_OK;
2bdd86d4
MD
469 goto end;
470 }
7f79d3a1
DG
471
472 switch (domain) {
473 case LTTNG_DOMAIN_UST:
474 ret = ust_app_disable_event_glb(usess, uchan, uevent);
475 if (ret < 0 && ret != -EEXIST) {
476 ret = LTTCOMM_UST_DISABLE_FAIL;
477 goto error;
478 }
479 break;
d78d6610 480#if 0
7f79d3a1
DG
481 case LTTNG_DOMAIN_UST_EXEC_NAME:
482 case LTTNG_DOMAIN_UST_PID:
483 case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
d78d6610 484#endif
7f79d3a1 485 default:
1ab1ea0b 486 ret = LTTCOMM_UND;
7f79d3a1
DG
487 goto error;
488 }
489
490 uevent->enabled = 0;
2bdd86d4 491 ret = LTTCOMM_OK;
7f79d3a1 492
2bdd86d4 493end:
7f79d3a1
DG
494 DBG2("Event UST %s disabled in channel %s", uevent->attr.name,
495 uchan->name);
496
497error:
498 return ret;
499}
500
501/*
502 * Disable all UST tracepoints for a channel from a UST session.
503 */
504int event_ust_disable_all_tracepoints(struct ltt_ust_session *usess, int domain,
505 struct ltt_ust_channel *uchan)
506{
507 int ret, i;
508 size_t size;
bec39940 509 struct lttng_ht_iter iter;
7f79d3a1
DG
510 struct ltt_ust_event *uevent = NULL;
511 struct lttng_event *events = NULL;
512
513 switch (domain) {
514 case LTTNG_DOMAIN_UST:
515 {
516 /* Disabling existing events */
bec39940
DG
517 cds_lfht_for_each_entry(uchan->events->ht, &iter.iter, uevent,
518 node.node) {
7f79d3a1
DG
519 if (uevent->enabled == 1) {
520 ret = ust_app_disable_event_glb(usess, uchan, uevent);
521 if (ret < 0) {
522 continue;
523 }
524 uevent->enabled = 0;
525 }
526 }
527
528 /* Get all UST available events */
529 size = ust_app_list_events(&events);
530 if (size < 0) {
531 ret = LTTCOMM_UST_LIST_FAIL;
532 goto error;
533 }
534
535 for (i = 0; i < size; i++) {
536 uevent = trace_ust_find_event_by_name(uchan->events,
537 events[i].name);
538 if (uevent != NULL && uevent->enabled == 1) {
539 ret = ust_app_disable_event_pid(usess, uchan, uevent,
540 events[i].pid);
541 if (ret < 0 && ret != -EEXIST) {
542 ret = LTTCOMM_UST_DISABLE_FAIL;
543 goto error;
544 }
545 uevent->enabled = 0;
546 continue;
547 }
548 }
549
550 free(events);
551 break;
552 }
d78d6610 553#if 0
7f79d3a1
DG
554 case LTTNG_DOMAIN_UST_EXEC_NAME:
555 case LTTNG_DOMAIN_UST_PID:
556 case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
d78d6610 557#endif
7f79d3a1 558 default:
1ab1ea0b 559 ret = LTTCOMM_UND;
7f79d3a1
DG
560 goto error;
561 }
562
563 return LTTCOMM_OK;
564
565error:
566 free(events);
2bdd86d4
MD
567 return ret;
568}
This page took 0.052862 seconds and 4 git commands to generate.