Add safety assert() in session daemon
[lttng-tools.git] / src / bin / lttng-sessiond / event.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 modify
5 * it under the terms of the GNU General Public License, version 2 only,
6 * as published by the Free Software Foundation.
7 *
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.
12 *
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.
16 */
17
18 #define _GNU_SOURCE
19 #include <errno.h>
20 #include <urcu/list.h>
21 #include <string.h>
22
23 #include <lttng/lttng.h>
24 #include <common/error.h>
25 #include <common/sessiond-comm/sessiond-comm.h>
26
27 #include "channel.h"
28 #include "event.h"
29 #include "kernel.h"
30 #include "ust-ctl.h"
31 #include "ust-app.h"
32 #include "trace-kernel.h"
33 #include "trace-ust.h"
34
35 /*
36 * Add unique UST event based on the event name, filter bytecode and loglevel.
37 */
38 static void add_unique_ust_event(struct lttng_ht *ht,
39 struct ltt_ust_event *event)
40 {
41 struct cds_lfht_node *node_ptr;
42 struct ltt_ust_ht_key key;
43
44 assert(ht);
45 assert(ht->ht);
46 assert(event);
47
48 key.name = event->attr.name;
49 key.filter = (struct lttng_filter_bytecode *) event->filter;
50 key.loglevel = event->attr.loglevel;
51
52 node_ptr = cds_lfht_add_unique(ht->ht,
53 ht->hash_fct(event->node.key, lttng_ht_seed),
54 trace_ust_ht_match_event, &key, &event->node.node);
55 assert(node_ptr == &event->node.node);
56 }
57
58 /*
59 * Setup a lttng_event used to enable *all* syscall tracing.
60 */
61 static void init_syscalls_kernel_event(struct lttng_event *event)
62 {
63 assert(event);
64
65 event->name[0] = '\0';
66 /*
67 * We use LTTNG_EVENT* here since the trace kernel creation will make the
68 * right changes for the kernel.
69 */
70 event->type = LTTNG_EVENT_SYSCALL;
71 }
72
73 /*
74 * Disable kernel tracepoint event for a channel from the kernel session.
75 */
76 int event_kernel_disable_tracepoint(struct ltt_kernel_session *ksession,
77 struct ltt_kernel_channel *kchan, char *event_name)
78 {
79 int ret;
80 struct ltt_kernel_event *kevent;
81
82 assert(kchan);
83
84 kevent = trace_kernel_get_event_by_name(event_name, kchan);
85 if (kevent == NULL) {
86 ret = LTTNG_ERR_NO_EVENT;
87 goto error;
88 }
89
90 ret = kernel_disable_event(kevent);
91 if (ret < 0) {
92 ret = LTTNG_ERR_KERN_DISABLE_FAIL;
93 goto error;
94 }
95
96 DBG("Kernel event %s disable for channel %s.",
97 kevent->event->name, kchan->channel->name);
98
99 ret = LTTNG_OK;
100
101 error:
102 return ret;
103 }
104
105 /*
106 * Disable kernel tracepoint events for a channel from the kernel session.
107 */
108 int event_kernel_disable_all_tracepoints(struct ltt_kernel_session *ksession,
109 struct ltt_kernel_channel *kchan)
110 {
111 int ret;
112 struct ltt_kernel_event *kevent;
113
114 assert(kchan);
115
116 /* For each event in the kernel session */
117 cds_list_for_each_entry(kevent, &kchan->events_list.head, list) {
118 ret = kernel_disable_event(kevent);
119 if (ret < 0) {
120 /* We continue disabling the rest */
121 continue;
122 }
123 }
124 ret = LTTNG_OK;
125 return ret;
126 }
127
128 /*
129 * Disable kernel syscall events for a channel from the kernel session.
130 */
131 int event_kernel_disable_all_syscalls(struct ltt_kernel_session *ksession,
132 struct ltt_kernel_channel *kchan)
133 {
134 ERR("Cannot disable syscall tracing for existing session. Please destroy session instead.");
135 return LTTNG_OK; /* Return OK so disable all succeeds */
136 }
137
138 /*
139 * Disable all kernel event for a channel from the kernel session.
140 */
141 int event_kernel_disable_all(struct ltt_kernel_session *ksession,
142 struct ltt_kernel_channel *kchan)
143 {
144 int ret;
145
146 assert(ksession);
147 assert(kchan);
148
149 ret = event_kernel_disable_all_tracepoints(ksession, kchan);
150 if (ret != LTTNG_OK)
151 return ret;
152 ret = event_kernel_disable_all_syscalls(ksession, kchan);
153 return ret;
154 }
155
156 /*
157 * Enable kernel tracepoint event for a channel from the kernel session.
158 */
159 int event_kernel_enable_tracepoint(struct ltt_kernel_session *ksession,
160 struct ltt_kernel_channel *kchan, struct lttng_event *event)
161 {
162 int ret;
163 struct ltt_kernel_event *kevent;
164
165 assert(kchan);
166 assert(event);
167
168 kevent = trace_kernel_get_event_by_name(event->name, kchan);
169 if (kevent == NULL) {
170 ret = kernel_create_event(event, kchan);
171 if (ret < 0) {
172 switch (-ret) {
173 case EEXIST:
174 ret = LTTNG_ERR_KERN_EVENT_EXIST;
175 break;
176 case ENOSYS:
177 ret = LTTNG_ERR_KERN_EVENT_ENOSYS;
178 break;
179 default:
180 ret = LTTNG_ERR_KERN_ENABLE_FAIL;
181 break;
182 }
183 goto end;
184 }
185 } else if (kevent->enabled == 0) {
186 ret = kernel_enable_event(kevent);
187 if (ret < 0) {
188 ret = LTTNG_ERR_KERN_ENABLE_FAIL;
189 goto end;
190 }
191 } else {
192 /* At this point, the event is considered enabled */
193 ret = LTTNG_ERR_KERN_EVENT_EXIST;
194 goto end;
195 }
196
197 ret = LTTNG_OK;
198 end:
199 return ret;
200 }
201
202 /*
203 * Enable all kernel tracepoint events of a channel of the kernel session.
204 */
205 int event_kernel_enable_all_tracepoints(struct ltt_kernel_session *ksession,
206 struct ltt_kernel_channel *kchan, int kernel_tracer_fd)
207 {
208 int size, i, ret;
209 struct ltt_kernel_event *kevent;
210 struct lttng_event *event_list = NULL;
211
212 assert(kchan);
213
214 /* For each event in the kernel session */
215 cds_list_for_each_entry(kevent, &kchan->events_list.head, list) {
216 if (kevent->enabled == 0) {
217 ret = kernel_enable_event(kevent);
218 if (ret < 0) {
219 /* Enable failed but still continue */
220 continue;
221 }
222 }
223 }
224
225 size = kernel_list_events(kernel_tracer_fd, &event_list);
226 if (size < 0) {
227 ret = LTTNG_ERR_KERN_LIST_FAIL;
228 goto end;
229 }
230
231 for (i = 0; i < size; i++) {
232 kevent = trace_kernel_get_event_by_name(event_list[i].name, kchan);
233 if (kevent == NULL) {
234 /* Default event type for enable all */
235 event_list[i].type = LTTNG_EVENT_TRACEPOINT;
236 /* Enable each single tracepoint event */
237 ret = kernel_create_event(&event_list[i], kchan);
238 if (ret < 0) {
239 /* Ignore error here and continue */
240 }
241 }
242 }
243 free(event_list);
244
245 ret = LTTNG_OK;
246 end:
247 return ret;
248 }
249
250 /*
251 * Enable all kernel tracepoint events of a channel of the kernel session.
252 */
253 int event_kernel_enable_all_syscalls(struct ltt_kernel_session *ksession,
254 struct ltt_kernel_channel *kchan, int kernel_tracer_fd)
255 {
256 int ret;
257 struct lttng_event event;
258
259 assert(kchan);
260
261 init_syscalls_kernel_event(&event);
262
263 DBG("Enabling all syscall tracing");
264
265 ret = kernel_create_event(&event, kchan);
266 if (ret < 0) {
267 if (ret == -EEXIST) {
268 ret = LTTNG_ERR_KERN_EVENT_EXIST;
269 } else {
270 ret = LTTNG_ERR_KERN_ENABLE_FAIL;
271 }
272 goto end;
273 }
274
275 ret = LTTNG_OK;
276 end:
277 return ret;
278 }
279
280 /*
281 * Enable all kernel events of a channel of the kernel session.
282 */
283 int event_kernel_enable_all(struct ltt_kernel_session *ksession,
284 struct ltt_kernel_channel *kchan, int kernel_tracer_fd)
285 {
286 int tp_ret;
287
288 assert(ksession);
289 assert(kchan);
290
291 tp_ret = event_kernel_enable_all_tracepoints(ksession, kchan,
292 kernel_tracer_fd);
293 if (tp_ret != LTTNG_OK) {
294 goto end;
295 }
296
297 /*
298 * Reaching this code path means that all tracepoints were enabled without
299 * errors so we ignore the error value of syscalls.
300 *
301 * At the moment, failing to enable syscalls on "lttng enable-event -a -k"
302 * is not considered an error that need to be returned to the client since
303 * tracepoints did not fail. Future work will allow us to send back
304 * multiple errors to the client in one API call.
305 */
306 (void) event_kernel_enable_all_syscalls(ksession, kchan, kernel_tracer_fd);
307
308 end:
309 return tp_ret;
310 }
311
312 /*
313 * ============================
314 * UST : The Ultimate Frontier!
315 * ============================
316 */
317
318 /*
319 * Enable all UST tracepoints for a channel from a UST session.
320 */
321 int event_ust_enable_all_tracepoints(struct ltt_ust_session *usess, int domain,
322 struct ltt_ust_channel *uchan, struct lttng_filter_bytecode *filter)
323 {
324 int ret, i, size;
325 struct lttng_ht_iter iter;
326 struct ltt_ust_event *uevent = NULL;
327 struct lttng_event *events = NULL;
328
329 assert(usess);
330 assert(uchan);
331
332 rcu_read_lock();
333
334 switch (domain) {
335 case LTTNG_DOMAIN_UST:
336 {
337 /* Enable existing events */
338 cds_lfht_for_each_entry(uchan->events->ht, &iter.iter, uevent,
339 node.node) {
340 if (uevent->enabled == 0) {
341 ret = ust_app_enable_event_glb(usess, uchan, uevent);
342 if (ret < 0) {
343 continue;
344 }
345 uevent->enabled = 1;
346 }
347 }
348
349 /* Get all UST available events */
350 size = ust_app_list_events(&events);
351 if (size < 0) {
352 ret = LTTNG_ERR_UST_LIST_FAIL;
353 goto error;
354 }
355
356 for (i = 0; i < size; i++) {
357 /*
358 * Check if event exist and if so, continue since it was enable
359 * previously.
360 */
361 uevent = trace_ust_find_event(uchan->events, events[i].name, filter,
362 events[i].loglevel);
363 if (uevent != NULL) {
364 ret = ust_app_enable_event_pid(usess, uchan, uevent,
365 events[i].pid);
366 if (ret < 0) {
367 if (ret != -LTTNG_UST_ERR_EXIST) {
368 ret = LTTNG_ERR_UST_ENABLE_FAIL;
369 goto error;
370 }
371 }
372 continue;
373 }
374
375 /* Create ust event */
376 uevent = trace_ust_create_event(&events[i], filter);
377 if (uevent == NULL) {
378 ret = LTTNG_ERR_FATAL;
379 goto error_destroy;
380 }
381
382 /* Create event for the specific PID */
383 ret = ust_app_enable_event_pid(usess, uchan, uevent,
384 events[i].pid);
385 if (ret < 0) {
386 if (ret == -LTTNG_UST_ERR_EXIST) {
387 ret = LTTNG_ERR_UST_EVENT_EXIST;
388 goto error;
389 } else {
390 ret = LTTNG_ERR_UST_ENABLE_FAIL;
391 goto error_destroy;
392 }
393 }
394
395 uevent->enabled = 1;
396 /* Add ltt ust event to channel */
397 rcu_read_lock();
398 add_unique_ust_event(uchan->events, uevent);
399 rcu_read_unlock();
400 }
401
402 free(events);
403 break;
404 }
405 #if 0
406 case LTTNG_DOMAIN_UST_EXEC_NAME:
407 case LTTNG_DOMAIN_UST_PID:
408 case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
409 #endif
410 default:
411 ret = LTTNG_ERR_UND;
412 goto error;
413 }
414
415 rcu_read_unlock();
416 return LTTNG_OK;
417
418 error_destroy:
419 trace_ust_destroy_event(uevent);
420
421 error:
422 free(events);
423 rcu_read_unlock();
424 return ret;
425 }
426
427 /*
428 * Enable UST tracepoint event for a channel from a UST session.
429 */
430 int event_ust_enable_tracepoint(struct ltt_ust_session *usess, int domain,
431 struct ltt_ust_channel *uchan, struct lttng_event *event,
432 struct lttng_filter_bytecode *filter)
433 {
434 int ret = LTTNG_OK, to_create = 0;
435 struct ltt_ust_event *uevent;
436
437 assert(usess);
438 assert(uchan);
439 assert(event);
440
441 rcu_read_lock();
442
443 uevent = trace_ust_find_event(uchan->events, event->name, filter,
444 event->loglevel);
445 if (uevent == NULL) {
446 uevent = trace_ust_create_event(event, filter);
447 if (uevent == NULL) {
448 ret = LTTNG_ERR_UST_ENABLE_FAIL;
449 goto error;
450 }
451
452 /* Valid to set it after the goto error since uevent is still NULL */
453 to_create = 1;
454 }
455
456 if (uevent->enabled) {
457 /* It's already enabled so everything is OK */
458 ret = LTTNG_ERR_UST_EVENT_ENABLED;
459 goto end;
460 }
461
462 uevent->enabled = 1;
463
464 switch (domain) {
465 case LTTNG_DOMAIN_UST:
466 {
467 if (to_create) {
468 /* Create event on all UST registered apps for session */
469 ret = ust_app_create_event_glb(usess, uchan, uevent);
470 } else {
471 /* Enable event on all UST registered apps for session */
472 ret = ust_app_enable_event_glb(usess, uchan, uevent);
473 }
474
475 if (ret < 0) {
476 if (ret == -LTTNG_UST_ERR_EXIST) {
477 ret = LTTNG_ERR_UST_EVENT_EXIST;
478 goto end;
479 } else {
480 ret = LTTNG_ERR_UST_ENABLE_FAIL;
481 goto error;
482 }
483 }
484 break;
485 }
486 #if 0
487 case LTTNG_DOMAIN_UST_EXEC_NAME:
488 case LTTNG_DOMAIN_UST_PID:
489 case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
490 #endif
491 default:
492 ret = LTTNG_ERR_UND;
493 goto end;
494 }
495
496 if (to_create) {
497 /* Add ltt ust event to channel */
498 add_unique_ust_event(uchan->events, uevent);
499 }
500
501 DBG("Event UST %s %s in channel %s", uevent->attr.name,
502 to_create ? "created" : "enabled", uchan->name);
503
504 ret = LTTNG_OK;
505
506 end:
507 rcu_read_unlock();
508 return ret;
509
510 error:
511 /*
512 * Only destroy event on creation time (not enabling time) because if the
513 * event is found in the channel (to_create == 0), it means that at some
514 * point the enable_event worked and it's thus valid to keep it alive.
515 * Destroying it also implies that we also destroy it's shadow copy to sync
516 * everyone up.
517 */
518 if (to_create) {
519 /* In this code path, the uevent was not added to the hash table */
520 trace_ust_destroy_event(uevent);
521 }
522 rcu_read_unlock();
523 return ret;
524 }
525
526 /*
527 * Disable UST tracepoint of a channel from a UST session.
528 */
529 int event_ust_disable_tracepoint(struct ltt_ust_session *usess, int domain,
530 struct ltt_ust_channel *uchan, char *event_name)
531 {
532 int ret;
533 struct ltt_ust_event *uevent;
534 struct lttng_ht_node_str *node;
535 struct lttng_ht_iter iter;
536 struct lttng_ht *ht;
537
538 assert(usess);
539 assert(uchan);
540 assert(event_name);
541
542 ht = uchan->events;
543
544 rcu_read_lock();
545
546 /*
547 * We use a custom lookup since we need the iterator for the next_duplicate
548 * call in the do while loop below.
549 */
550 cds_lfht_lookup(ht->ht, ht->hash_fct((void *) event_name, lttng_ht_seed),
551 trace_ust_ht_match_event_by_name, event_name, &iter.iter);
552 node = lttng_ht_iter_get_node_str(&iter);
553 if (node == NULL) {
554 DBG2("Trace UST event NOT found by name %s", event_name);
555 ret = LTTNG_ERR_UST_EVENT_NOT_FOUND;
556 goto error;
557 }
558
559 do {
560 uevent = caa_container_of(node, struct ltt_ust_event, node);
561 assert(uevent);
562
563 if (uevent->enabled == 0) {
564 /* It's already disabled so everything is OK */
565 ret = LTTNG_OK;
566 continue;
567 }
568
569 switch (domain) {
570 case LTTNG_DOMAIN_UST:
571 ret = ust_app_disable_event_glb(usess, uchan, uevent);
572 if (ret < 0 && ret != -LTTNG_UST_ERR_EXIST) {
573 ret = LTTNG_ERR_UST_DISABLE_FAIL;
574 goto error;
575 }
576 break;
577 #if 0
578 case LTTNG_DOMAIN_UST_EXEC_NAME:
579 case LTTNG_DOMAIN_UST_PID:
580 case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
581 #endif
582 default:
583 ret = LTTNG_ERR_UND;
584 goto error;
585 }
586
587 uevent->enabled = 0;
588
589 DBG2("Event UST %s disabled in channel %s", uevent->attr.name,
590 uchan->name);
591
592 /* Get next duplicate event by name. */
593 cds_lfht_next_duplicate(ht->ht, trace_ust_ht_match_event_by_name,
594 event_name, &iter.iter);
595 node = lttng_ht_iter_get_node_str(&iter);
596 } while (node);
597
598 ret = LTTNG_OK;
599
600 error:
601 rcu_read_unlock();
602 return ret;
603 }
604
605 /*
606 * Disable all UST tracepoints for a channel from a UST session.
607 */
608 int event_ust_disable_all_tracepoints(struct ltt_ust_session *usess, int domain,
609 struct ltt_ust_channel *uchan)
610 {
611 int ret, i, size;
612 struct lttng_ht_iter iter;
613 struct ltt_ust_event *uevent = NULL;
614 struct lttng_event *events = NULL;
615
616 assert(usess);
617 assert(uchan);
618
619 rcu_read_lock();
620
621 switch (domain) {
622 case LTTNG_DOMAIN_UST:
623 {
624 /* Disabling existing events */
625 cds_lfht_for_each_entry(uchan->events->ht, &iter.iter, uevent,
626 node.node) {
627 if (uevent->enabled == 1) {
628 ret = event_ust_disable_tracepoint(usess, domain, uchan,
629 uevent->attr.name);
630 if (ret < 0) {
631 continue;
632 }
633 }
634 }
635
636 /* Get all UST available events */
637 size = ust_app_list_events(&events);
638 if (size < 0) {
639 ret = LTTNG_ERR_UST_LIST_FAIL;
640 goto error;
641 }
642
643 for (i = 0; i < size; i++) {
644 ret = event_ust_disable_tracepoint(usess, domain, uchan,
645 events[i].name);
646 if (ret != LTTNG_OK) {
647 /* Continue to disable the rest... */
648 continue;
649 }
650 }
651
652 free(events);
653 break;
654 }
655 #if 0
656 case LTTNG_DOMAIN_UST_EXEC_NAME:
657 case LTTNG_DOMAIN_UST_PID:
658 case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
659 #endif
660 default:
661 ret = LTTNG_ERR_UND;
662 goto error;
663 }
664
665 rcu_read_unlock();
666 return LTTNG_OK;
667
668 error:
669 free(events);
670 rcu_read_unlock();
671 return ret;
672 }
This page took 0.04221 seconds and 4 git commands to generate.