Fix: include the filter expression in agent events' primary key
[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 _LGPL_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 "lttng-sessiond.h"
31 #include "ust-ctl.h"
32 #include "ust-app.h"
33 #include "trace-kernel.h"
34 #include "trace-ust.h"
35 #include "agent.h"
36
37 /*
38 * Add unique UST event based on the event name, filter bytecode and loglevel.
39 */
40 static void add_unique_ust_event(struct lttng_ht *ht,
41 struct ltt_ust_event *event)
42 {
43 struct cds_lfht_node *node_ptr;
44 struct ltt_ust_ht_key key;
45
46 assert(ht);
47 assert(ht->ht);
48 assert(event);
49
50 key.name = event->attr.name;
51 key.filter = (struct lttng_filter_bytecode *) event->filter;
52 key.loglevel_type = event->attr.loglevel_type;
53 key.loglevel_value = event->attr.loglevel;
54 key.exclusion = event->exclusion;
55
56 node_ptr = cds_lfht_add_unique(ht->ht,
57 ht->hash_fct(event->node.key, lttng_ht_seed),
58 trace_ust_ht_match_event, &key, &event->node.node);
59 assert(node_ptr == &event->node.node);
60 }
61
62 /*
63 * Disable kernel tracepoint events for a channel from the kernel session of
64 * a specified event_name and event type.
65 * On type LTTNG_EVENT_ALL all events with event_name are disabled.
66 * If event_name is NULL all events of the specified type are disabled.
67 */
68 int event_kernel_disable_event(struct ltt_kernel_channel *kchan,
69 char *event_name, enum lttng_event_type type)
70 {
71 int ret, error = 0, found = 0;
72 struct ltt_kernel_event *kevent;
73
74 assert(kchan);
75
76 /* For each event in the kernel session */
77 cds_list_for_each_entry(kevent, &kchan->events_list.head, list) {
78 if (type != LTTNG_EVENT_ALL && kevent->type != type)
79 continue;
80 if (event_name != NULL && strcmp(event_name, kevent->event->name)) {
81 continue;
82 }
83 found++;
84 ret = kernel_disable_event(kevent);
85 if (ret < 0) {
86 error = 1;
87 continue;
88 }
89 }
90 DBG("Disable kernel event: found %d events with name: %s and type: %d",
91 found, event_name ? event_name : "NULL", type);
92
93 if (event_name != NULL && !found) {
94 ret = LTTNG_ERR_NO_EVENT;
95 } else {
96 ret = error ? LTTNG_ERR_KERN_DISABLE_FAIL : LTTNG_OK;
97 }
98
99 return ret;
100 }
101
102 /*
103 * Enable kernel tracepoint event for a channel from the kernel session.
104 * We own filter_expression and filter.
105 */
106 int event_kernel_enable_event(struct ltt_kernel_channel *kchan,
107 struct lttng_event *event, char *filter_expression,
108 struct lttng_filter_bytecode *filter)
109 {
110 int ret;
111 struct ltt_kernel_event *kevent;
112
113 assert(kchan);
114 assert(event);
115
116 kevent = trace_kernel_find_event(event->name, kchan,
117 event->type, filter);
118 if (kevent == NULL) {
119 ret = kernel_create_event(event, kchan,
120 filter_expression, filter);
121 /* We have passed ownership */
122 filter_expression = NULL;
123 filter = NULL;
124 if (ret < 0) {
125 switch (-ret) {
126 case EEXIST:
127 ret = LTTNG_ERR_KERN_EVENT_EXIST;
128 break;
129 case ENOSYS:
130 ret = LTTNG_ERR_KERN_EVENT_ENOSYS;
131 break;
132 default:
133 ret = LTTNG_ERR_KERN_ENABLE_FAIL;
134 break;
135 }
136 goto end;
137 }
138 } else if (kevent->enabled == 0) {
139 ret = kernel_enable_event(kevent);
140 if (ret < 0) {
141 ret = LTTNG_ERR_KERN_ENABLE_FAIL;
142 goto end;
143 }
144 } else {
145 /* At this point, the event is considered enabled */
146 ret = LTTNG_ERR_KERN_EVENT_EXIST;
147 goto end;
148 }
149
150 ret = LTTNG_OK;
151 end:
152 free(filter_expression);
153 free(filter);
154 return ret;
155 }
156
157 /*
158 * ============================
159 * UST : The Ultimate Frontier!
160 * ============================
161 */
162
163 /*
164 * Enable UST tracepoint event for a channel from a UST session.
165 * We own filter_expression, filter, and exclusion.
166 */
167 int event_ust_enable_tracepoint(struct ltt_ust_session *usess,
168 struct ltt_ust_channel *uchan, struct lttng_event *event,
169 char *filter_expression,
170 struct lttng_filter_bytecode *filter,
171 struct lttng_event_exclusion *exclusion,
172 bool internal_event)
173 {
174 int ret = LTTNG_OK, to_create = 0;
175 struct ltt_ust_event *uevent;
176
177 assert(usess);
178 assert(uchan);
179 assert(event);
180
181 rcu_read_lock();
182
183 uevent = trace_ust_find_event(uchan->events, event->name, filter,
184 event->loglevel_type, event->loglevel, exclusion);
185 if (!uevent) {
186 uevent = trace_ust_create_event(event, filter_expression,
187 filter, exclusion, internal_event);
188 /* We have passed ownership */
189 filter_expression = NULL;
190 filter = NULL;
191 exclusion = NULL;
192 if (uevent == NULL) {
193 ret = LTTNG_ERR_UST_ENABLE_FAIL;
194 goto error;
195 }
196
197 /* Valid to set it after the goto error since uevent is still NULL */
198 to_create = 1;
199 }
200
201 if (uevent->enabled) {
202 /* It's already enabled so everything is OK */
203 ret = LTTNG_ERR_UST_EVENT_ENABLED;
204 goto end;
205 }
206
207 uevent->enabled = 1;
208
209 if (to_create) {
210 /* Create event on all UST registered apps for session */
211 ret = ust_app_create_event_glb(usess, uchan, uevent);
212 } else {
213 /* Enable event on all UST registered apps for session */
214 ret = ust_app_enable_event_glb(usess, uchan, uevent);
215 }
216
217 if (ret < 0) {
218 if (ret == -LTTNG_UST_ERR_EXIST) {
219 ret = LTTNG_ERR_UST_EVENT_EXIST;
220 goto end;
221 } else {
222 ret = LTTNG_ERR_UST_ENABLE_FAIL;
223 goto error;
224 }
225 }
226
227 if (to_create) {
228 /* Add ltt ust event to channel */
229 add_unique_ust_event(uchan->events, uevent);
230 }
231
232 DBG("Event UST %s %s in channel %s", uevent->attr.name,
233 to_create ? "created" : "enabled", uchan->name);
234
235 ret = LTTNG_OK;
236
237 end:
238 rcu_read_unlock();
239 free(filter_expression);
240 free(filter);
241 free(exclusion);
242 return ret;
243
244 error:
245 /*
246 * Only destroy event on creation time (not enabling time) because if the
247 * event is found in the channel (to_create == 0), it means that at some
248 * point the enable_event worked and it's thus valid to keep it alive.
249 * Destroying it also implies that we also destroy it's shadow copy to sync
250 * everyone up.
251 */
252 if (to_create) {
253 /* In this code path, the uevent was not added to the hash table */
254 trace_ust_destroy_event(uevent);
255 }
256 rcu_read_unlock();
257 free(filter_expression);
258 free(filter);
259 free(exclusion);
260 return ret;
261 }
262
263 /*
264 * Disable UST tracepoint of a channel from a UST session.
265 */
266 int event_ust_disable_tracepoint(struct ltt_ust_session *usess,
267 struct ltt_ust_channel *uchan, char *event_name)
268 {
269 int ret;
270 struct ltt_ust_event *uevent;
271 struct lttng_ht_node_str *node;
272 struct lttng_ht_iter iter;
273 struct lttng_ht *ht;
274
275 assert(usess);
276 assert(uchan);
277 assert(event_name);
278
279 ht = uchan->events;
280
281 rcu_read_lock();
282
283 /*
284 * We use a custom lookup since we need the iterator for the next_duplicate
285 * call in the do while loop below.
286 */
287 cds_lfht_lookup(ht->ht, ht->hash_fct((void *) event_name, lttng_ht_seed),
288 trace_ust_ht_match_event_by_name, event_name, &iter.iter);
289 node = lttng_ht_iter_get_node_str(&iter);
290 if (node == NULL) {
291 DBG2("Trace UST event NOT found by name %s", event_name);
292 ret = LTTNG_ERR_UST_EVENT_NOT_FOUND;
293 goto error;
294 }
295
296 do {
297 uevent = caa_container_of(node, struct ltt_ust_event, node);
298 assert(uevent);
299
300 if (uevent->enabled == 0) {
301 /* It's already disabled so everything is OK */
302 goto next;
303 }
304
305 ret = ust_app_disable_event_glb(usess, uchan, uevent);
306 if (ret < 0 && ret != -LTTNG_UST_ERR_EXIST) {
307 ret = LTTNG_ERR_UST_DISABLE_FAIL;
308 goto error;
309 }
310 uevent->enabled = 0;
311
312 DBG2("Event UST %s disabled in channel %s", uevent->attr.name,
313 uchan->name);
314
315 next:
316 /* Get next duplicate event by name. */
317 cds_lfht_next_duplicate(ht->ht, trace_ust_ht_match_event_by_name,
318 event_name, &iter.iter);
319 node = lttng_ht_iter_get_node_str(&iter);
320 } while (node);
321
322 ret = LTTNG_OK;
323
324 error:
325 rcu_read_unlock();
326 return ret;
327 }
328
329 /*
330 * Disable all UST tracepoints for a channel from a UST session.
331 */
332 int event_ust_disable_all_tracepoints(struct ltt_ust_session *usess,
333 struct ltt_ust_channel *uchan)
334 {
335 int ret, i, size, error = 0;
336 struct lttng_ht_iter iter;
337 struct ltt_ust_event *uevent = NULL;
338 struct lttng_event *events = NULL;
339
340 assert(usess);
341 assert(uchan);
342
343 rcu_read_lock();
344
345 /* Disabling existing events */
346 cds_lfht_for_each_entry(uchan->events->ht, &iter.iter, uevent,
347 node.node) {
348 if (uevent->enabled == 1) {
349 ret = event_ust_disable_tracepoint(usess, uchan,
350 uevent->attr.name);
351 if (ret < 0) {
352 error = LTTNG_ERR_UST_DISABLE_FAIL;
353 continue;
354 }
355 }
356 }
357
358 /* Get all UST available events */
359 size = ust_app_list_events(&events);
360 if (size < 0) {
361 ret = LTTNG_ERR_UST_LIST_FAIL;
362 goto error;
363 }
364
365 for (i = 0; i < size; i++) {
366 ret = event_ust_disable_tracepoint(usess, uchan,
367 events[i].name);
368 if (ret < 0) {
369 /* Continue to disable the rest... */
370 error = LTTNG_ERR_UST_DISABLE_FAIL;
371 continue;
372 }
373 }
374
375 ret = error ? error : LTTNG_OK;
376 error:
377 rcu_read_unlock();
378 free(events);
379 return ret;
380 }
381
382 /*
383 * Enable all agent event for a given UST session.
384 *
385 * Return LTTNG_OK on success or else a LTTNG_ERR* code.
386 */
387 int event_agent_enable_all(struct ltt_ust_session *usess,
388 struct agent *agt, struct lttng_event *event,
389 struct lttng_filter_bytecode *filter ,char *filter_expression)
390 {
391 int ret;
392 struct agent_event *aevent;
393 struct lttng_ht_iter iter;
394
395 assert(usess);
396
397 DBG("Event agent enabling ALL events for session %" PRIu64, usess->id);
398
399 /* Enable event on agent application through TCP socket. */
400 ret = event_agent_enable(usess, agt, event, filter, filter_expression);
401 if (ret != LTTNG_OK) {
402 goto error;
403 }
404
405 /* Flag every event that they are now enabled. */
406 rcu_read_lock();
407 cds_lfht_for_each_entry(agt->events->ht, &iter.iter, aevent,
408 node.node) {
409 aevent->enabled = 1;
410 }
411 rcu_read_unlock();
412
413 ret = LTTNG_OK;
414
415 error:
416 return ret;
417 }
418
419 /*
420 * Enable a single agent event for a given UST session.
421 *
422 * Return LTTNG_OK on success or else a LTTNG_ERR* code.
423 */
424 int event_agent_enable(struct ltt_ust_session *usess,
425 struct agent *agt, struct lttng_event *event,
426 struct lttng_filter_bytecode *filter,
427 char *filter_expression)
428 {
429 int ret, created = 0;
430 struct agent_event *aevent;
431
432 assert(usess);
433 assert(event);
434 assert(agt);
435
436 DBG("Event agent enabling %s for session %" PRIu64 " with loglevel type %d "
437 ", loglevel %d and filter \"%s\"", event->name,
438 usess->id, event->loglevel_type, event->loglevel,
439 filter_expression ? filter_expression : "NULL");
440
441 aevent = agent_find_event(event->name, event->loglevel_type,
442 event->loglevel, filter_expression, agt);
443 if (!aevent) {
444 aevent = agent_create_event(event->name, event->loglevel_type,
445 event->loglevel, filter,
446 filter_expression);
447 if (!aevent) {
448 ret = LTTNG_ERR_NOMEM;
449 goto error;
450 }
451 created = 1;
452 }
453
454 /* Already enabled? */
455 if (aevent->enabled) {
456 goto end;
457 }
458
459 ret = agent_enable_event(aevent, agt->domain);
460 if (ret != LTTNG_OK) {
461 goto error;
462 }
463
464 /* If the event was created prior to the enable, add it to the domain. */
465 if (created) {
466 agent_add_event(aevent, agt);
467 }
468
469 end:
470 return LTTNG_OK;
471
472 error:
473 if (created) {
474 agent_destroy_event(aevent);
475 }
476 return ret;
477 }
478
479 /*
480 * Return the default event name associated with the provided UST domain. Return
481 * NULL on error.
482 */
483 const char *event_get_default_agent_ust_name(enum lttng_domain_type domain)
484 {
485 const char *default_event_name = NULL;
486
487 switch (domain) {
488 case LTTNG_DOMAIN_LOG4J:
489 default_event_name = DEFAULT_LOG4J_EVENT_NAME;
490 break;
491 case LTTNG_DOMAIN_JUL:
492 default_event_name = DEFAULT_JUL_EVENT_NAME;
493 break;
494 case LTTNG_DOMAIN_PYTHON:
495 default_event_name = DEFAULT_PYTHON_EVENT_NAME;
496 break;
497 default:
498 assert(0);
499 }
500
501 return default_event_name;
502 }
503
504 /*
505 * Disable a given agent event for a given UST session.
506 *
507 * Must be called with the RCU read lock held.
508 * Return LTTNG_OK on success or else a LTTNG_ERR* code.
509 */
510 static int event_agent_disable_one(struct ltt_ust_session *usess,
511 struct agent *agt, struct agent_event *aevent)
512 {
513 int ret;
514 struct ltt_ust_event *uevent = NULL;
515 struct ltt_ust_channel *uchan = NULL;
516 const char *ust_event_name, *ust_channel_name;
517
518 assert(agt);
519 assert(usess);
520 assert(aevent);
521
522 DBG("Event agent disabling %s (loglevel type %d, loglevel value %d) for session %" PRIu64,
523 aevent->name, aevent->loglevel_type, aevent->loglevel_value,
524 usess->id);
525
526 /* Already disabled? */
527 if (!aevent->enabled) {
528 goto end;
529 }
530
531 if (agt->domain == LTTNG_DOMAIN_JUL) {
532 ust_channel_name = DEFAULT_JUL_CHANNEL_NAME;
533 } else if (agt->domain == LTTNG_DOMAIN_LOG4J) {
534 ust_channel_name = DEFAULT_LOG4J_CHANNEL_NAME;
535 } else if (agt->domain == LTTNG_DOMAIN_PYTHON) {
536 ust_channel_name = DEFAULT_PYTHON_CHANNEL_NAME;
537 } else {
538 ret = LTTNG_ERR_INVALID;
539 goto error;
540 }
541
542 /*
543 * Disable it on the UST side. First get the channel reference then find
544 * the event and finally disable it.
545 */
546 uchan = trace_ust_find_channel_by_name(usess->domain_global.channels,
547 (char *) ust_channel_name);
548 if (!uchan) {
549 ret = LTTNG_ERR_UST_CHAN_NOT_FOUND;
550 goto error;
551 }
552
553 ust_event_name = event_get_default_agent_ust_name(agt->domain);
554 if (!ust_event_name) {
555 ret = LTTNG_ERR_FATAL;
556 goto error;
557 }
558
559 /*
560 * Agent UST event has its loglevel type forced to
561 * LTTNG_UST_LOGLEVEL_ALL. The actual loglevel type/value filtering
562 * happens thanks to an UST filter. The following -1 is actually
563 * ignored since the type is LTTNG_UST_LOGLEVEL_ALL.
564 */
565 uevent = trace_ust_find_event(uchan->events, (char *) ust_event_name,
566 aevent->filter, LTTNG_UST_LOGLEVEL_ALL, -1, NULL);
567 /* If the agent event exists, it must be available on the UST side. */
568 assert(uevent);
569
570 ret = ust_app_disable_event_glb(usess, uchan, uevent);
571 if (ret < 0 && ret != -LTTNG_UST_ERR_EXIST) {
572 ret = LTTNG_ERR_UST_DISABLE_FAIL;
573 goto error;
574 }
575
576 /*
577 * Flag event that it's disabled so the shadow copy on the ust app side
578 * will disable it if an application shows up.
579 */
580 uevent->enabled = 0;
581
582 ret = agent_disable_event(aevent, agt->domain);
583 if (ret != LTTNG_OK) {
584 goto error;
585 }
586
587 end:
588 return LTTNG_OK;
589
590 error:
591 return ret;
592 }
593
594 /*
595 * Disable all agent events matching a given name for a given UST session.
596 *
597 * Return LTTNG_OK on success or else a LTTNG_ERR* code.
598 */
599 int event_agent_disable(struct ltt_ust_session *usess, struct agent *agt,
600 char *event_name)
601 {
602 int ret = LTTNG_OK;
603 struct agent_event *aevent;
604 struct lttng_ht_iter iter;
605 struct lttng_ht_node_str *node;
606
607 assert(agt);
608 assert(usess);
609 assert(event_name);
610
611 DBG("Event agent disabling %s (all loglevels) for session %" PRIu64, event_name, usess->id);
612
613 rcu_read_lock();
614 agent_find_events_by_name(event_name, agt, &iter);
615 node = lttng_ht_iter_get_node_str(&iter);
616
617 if (node == NULL) {
618 DBG2("Event agent NOT found by name %s", event_name);
619 ret = LTTNG_ERR_UST_EVENT_NOT_FOUND;
620 goto end;
621 }
622
623 do {
624 aevent = caa_container_of(node, struct agent_event, node);
625 ret = event_agent_disable_one(usess, agt, aevent);
626
627 if (ret != LTTNG_OK) {
628 goto end;
629 }
630
631 /* Get next duplicate agent event by name. */
632 agent_event_next_duplicate(event_name, agt, &iter);
633 node = lttng_ht_iter_get_node_str(&iter);
634 } while (node);
635 end:
636 rcu_read_unlock();
637 return ret;
638 }
639 /*
640 * Disable all agent event for a given UST session.
641 *
642 * Return LTTNG_OK on success or else a LTTNG_ERR* code.
643 */
644 int event_agent_disable_all(struct ltt_ust_session *usess,
645 struct agent *agt)
646 {
647 int ret;
648 struct agent_event *aevent;
649 struct lttng_ht_iter iter;
650
651 assert(agt);
652 assert(usess);
653
654 /*
655 * Disable event on agent application. Continue to disable all other events
656 * if the * event is not found.
657 */
658 ret = event_agent_disable(usess, agt, "*");
659 if (ret != LTTNG_OK && ret != LTTNG_ERR_UST_EVENT_NOT_FOUND) {
660 goto error;
661 }
662
663 /* Disable every event. */
664 rcu_read_lock();
665 cds_lfht_for_each_entry(agt->events->ht, &iter.iter, aevent,
666 node.node) {
667 if (!aevent->enabled) {
668 continue;
669 }
670
671 ret = event_agent_disable(usess, agt, aevent->name);
672 if (ret != LTTNG_OK) {
673 goto error_unlock;
674 }
675 }
676 ret = LTTNG_OK;
677
678 error_unlock:
679 rcu_read_unlock();
680 error:
681 return ret;
682 }
This page took 0.068949 seconds and 4 git commands to generate.