Commit | Line | Data |
---|---|---|
97ee3a89 | 1 | /* |
ab5be9fa MJ |
2 | * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca> |
3 | * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com> | |
97ee3a89 | 4 | * |
ab5be9fa | 5 | * SPDX-License-Identifier: GPL-2.0-only |
97ee3a89 | 6 | * |
97ee3a89 DG |
7 | */ |
8 | ||
6c1c0768 | 9 | #define _LGPL_SOURCE |
97ee3a89 DG |
10 | #include <stdio.h> |
11 | #include <stdlib.h> | |
12 | #include <string.h> | |
13 | #include <unistd.h> | |
d9bf3ca4 | 14 | #include <inttypes.h> |
97ee3a89 | 15 | |
990570ed DG |
16 | #include <common/common.h> |
17 | #include <common/defaults.h> | |
82b69413 | 18 | #include <common/trace-chunk.h> |
97ee3a89 | 19 | |
7972aab2 | 20 | #include "buffer-registry.h" |
97ee3a89 | 21 | #include "trace-ust.h" |
0b2dc8df | 22 | #include "utils.h" |
a9ad0c8f | 23 | #include "ust-app.h" |
7c1d2758 | 24 | #include "agent.h" |
97ee3a89 | 25 | |
025faf73 DG |
26 | /* |
27 | * Match function for the events hash table lookup. | |
28 | * | |
29 | * Matches by name only. Used by the disable command. | |
30 | */ | |
18eace3b DG |
31 | int trace_ust_ht_match_event_by_name(struct cds_lfht_node *node, |
32 | const void *_key) | |
33 | { | |
34 | struct ltt_ust_event *event; | |
35 | const char *name; | |
36 | ||
37 | assert(node); | |
38 | assert(_key); | |
39 | ||
40 | event = caa_container_of(node, struct ltt_ust_event, node.node); | |
41 | name = _key; | |
42 | ||
43 | /* Event name */ | |
44 | if (strncmp(event->attr.name, name, sizeof(event->attr.name)) != 0) { | |
45 | goto no_match; | |
46 | } | |
47 | ||
025faf73 | 48 | /* Match */ |
18eace3b DG |
49 | return 1; |
50 | ||
51 | no_match: | |
52 | return 0; | |
53 | } | |
54 | ||
025faf73 DG |
55 | /* |
56 | * Match function for the hash table lookup. | |
57 | * | |
58 | * It matches an ust event based on three attributes which are the event name, | |
59 | * the filter bytecode and the loglevel. | |
60 | */ | |
18eace3b DG |
61 | int trace_ust_ht_match_event(struct cds_lfht_node *node, const void *_key) |
62 | { | |
63 | struct ltt_ust_event *event; | |
64 | const struct ltt_ust_ht_key *key; | |
2106efa0 | 65 | int ev_loglevel_value; |
19a97244 | 66 | int ll_match; |
18eace3b DG |
67 | |
68 | assert(node); | |
69 | assert(_key); | |
70 | ||
71 | event = caa_container_of(node, struct ltt_ust_event, node.node); | |
72 | key = _key; | |
2106efa0 | 73 | ev_loglevel_value = event->attr.loglevel; |
18eace3b | 74 | |
f19e9f8b | 75 | /* Match the 4 elements of the key: name, filter, loglevel, exclusions. */ |
18eace3b DG |
76 | |
77 | /* Event name */ | |
78 | if (strncmp(event->attr.name, key->name, sizeof(event->attr.name)) != 0) { | |
18eace3b DG |
79 | goto no_match; |
80 | } | |
81 | ||
b953b8cd | 82 | /* Event loglevel value and type. */ |
19a97244 PP |
83 | ll_match = loglevels_match(event->attr.loglevel_type, |
84 | ev_loglevel_value, key->loglevel_type, | |
85 | key->loglevel_value, LTTNG_UST_LOGLEVEL_ALL); | |
86 | ||
87 | if (!ll_match) { | |
b953b8cd | 88 | goto no_match; |
18eace3b DG |
89 | } |
90 | ||
91 | /* Only one of the filters is NULL, fail. */ | |
92 | if ((key->filter && !event->filter) || (!key->filter && event->filter)) { | |
18eace3b DG |
93 | goto no_match; |
94 | } | |
95 | ||
025faf73 DG |
96 | if (key->filter && event->filter) { |
97 | /* Both filters exists, check length followed by the bytecode. */ | |
98 | if (event->filter->len != key->filter->len || | |
99 | memcmp(event->filter->data, key->filter->data, | |
100 | event->filter->len) != 0) { | |
101 | goto no_match; | |
102 | } | |
18eace3b DG |
103 | } |
104 | ||
f19e9f8b JI |
105 | /* If only one of the exclusions is NULL, fail. */ |
106 | if ((key->exclusion && !event->exclusion) || (!key->exclusion && event->exclusion)) { | |
107 | goto no_match; | |
108 | } | |
109 | ||
110 | if (key->exclusion && event->exclusion) { | |
a5b7e00c PP |
111 | size_t i; |
112 | ||
113 | /* Check exclusion counts first. */ | |
114 | if (event->exclusion->count != key->exclusion->count) { | |
f19e9f8b JI |
115 | goto no_match; |
116 | } | |
a5b7e00c PP |
117 | |
118 | /* Compare names individually. */ | |
119 | for (i = 0; i < event->exclusion->count; ++i) { | |
120 | size_t j; | |
121 | bool found = false; | |
122 | const char *name_ev = | |
123 | LTTNG_EVENT_EXCLUSION_NAME_AT( | |
124 | event->exclusion, i); | |
125 | ||
126 | /* | |
127 | * Compare this exclusion name to all the key's | |
128 | * exclusion names. | |
129 | */ | |
130 | for (j = 0; j < key->exclusion->count; ++j) { | |
131 | const char *name_key = | |
132 | LTTNG_EVENT_EXCLUSION_NAME_AT( | |
133 | key->exclusion, j); | |
134 | ||
135 | if (!strncmp(name_ev, name_key, | |
136 | LTTNG_SYMBOL_NAME_LEN)) { | |
137 | /* Names match! */ | |
138 | found = true; | |
139 | break; | |
140 | } | |
141 | } | |
142 | ||
143 | /* | |
144 | * If the current exclusion name was not found amongst | |
145 | * the key's exclusion names, then there's no match. | |
146 | */ | |
147 | if (!found) { | |
148 | goto no_match; | |
149 | } | |
150 | } | |
f19e9f8b | 151 | } |
025faf73 DG |
152 | /* Match. */ |
153 | return 1; | |
18eace3b DG |
154 | |
155 | no_match: | |
156 | return 0; | |
18eace3b DG |
157 | } |
158 | ||
0177d773 | 159 | /* |
2223c96f DG |
160 | * Find the channel in the hashtable and return channel pointer. RCU read side |
161 | * lock MUST be acquired before calling this. | |
0177d773 | 162 | */ |
bec39940 | 163 | struct ltt_ust_channel *trace_ust_find_channel_by_name(struct lttng_ht *ht, |
df4f5a87 | 164 | const char *name) |
0177d773 | 165 | { |
bec39940 DG |
166 | struct lttng_ht_node_str *node; |
167 | struct lttng_ht_iter iter; | |
0177d773 | 168 | |
85076754 MD |
169 | /* |
170 | * If we receive an empty string for channel name, it means the | |
171 | * default channel name is requested. | |
172 | */ | |
173 | if (name[0] == '\0') | |
174 | name = DEFAULT_CHANNEL_NAME; | |
175 | ||
bec39940 DG |
176 | lttng_ht_lookup(ht, (void *)name, &iter); |
177 | node = lttng_ht_iter_get_node_str(&iter); | |
f6a9efaa | 178 | if (node == NULL) { |
44d3bd01 DG |
179 | goto error; |
180 | } | |
181 | ||
f6a9efaa | 182 | DBG2("Trace UST channel %s found by name", name); |
0177d773 | 183 | |
f6a9efaa | 184 | return caa_container_of(node, struct ltt_ust_channel, node); |
97ee3a89 DG |
185 | |
186 | error: | |
f6a9efaa | 187 | DBG2("Trace UST channel %s not found by name", name); |
97ee3a89 DG |
188 | return NULL; |
189 | } | |
190 | ||
191 | /* | |
2223c96f DG |
192 | * Find the event in the hashtable and return event pointer. RCU read side lock |
193 | * MUST be acquired before calling this. | |
97ee3a89 | 194 | */ |
18eace3b | 195 | struct ltt_ust_event *trace_ust_find_event(struct lttng_ht *ht, |
2106efa0 | 196 | char *name, struct lttng_filter_bytecode *filter, |
b953b8cd PP |
197 | enum lttng_ust_loglevel_type loglevel_type, int loglevel_value, |
198 | struct lttng_event_exclusion *exclusion) | |
97ee3a89 | 199 | { |
bec39940 DG |
200 | struct lttng_ht_node_str *node; |
201 | struct lttng_ht_iter iter; | |
18eace3b | 202 | struct ltt_ust_ht_key key; |
97ee3a89 | 203 | |
18eace3b DG |
204 | assert(name); |
205 | assert(ht); | |
206 | ||
207 | key.name = name; | |
208 | key.filter = filter; | |
b953b8cd PP |
209 | key.loglevel_type = loglevel_type; |
210 | key.loglevel_value = loglevel_value; | |
10646003 | 211 | key.exclusion = exclusion; |
18eace3b | 212 | |
18eace3b DG |
213 | cds_lfht_lookup(ht->ht, ht->hash_fct((void *) name, lttng_ht_seed), |
214 | trace_ust_ht_match_event, &key, &iter.iter); | |
bec39940 | 215 | node = lttng_ht_iter_get_node_str(&iter); |
f6a9efaa | 216 | if (node == NULL) { |
97ee3a89 DG |
217 | goto error; |
218 | } | |
219 | ||
18eace3b | 220 | DBG2("Trace UST event %s found", key.name); |
f6a9efaa DG |
221 | |
222 | return caa_container_of(node, struct ltt_ust_event, node); | |
97ee3a89 DG |
223 | |
224 | error: | |
18eace3b | 225 | DBG2("Trace UST event %s NOT found", key.name); |
97ee3a89 DG |
226 | return NULL; |
227 | } | |
228 | ||
fefd409b DG |
229 | /* |
230 | * Lookup an agent in the session agents hash table by domain type and return | |
231 | * the object if found else NULL. | |
4da703ad JG |
232 | * |
233 | * RCU read side lock must be acquired before calling and only released | |
234 | * once the agent is no longer in scope or being used. | |
fefd409b DG |
235 | */ |
236 | struct agent *trace_ust_find_agent(struct ltt_ust_session *session, | |
237 | enum lttng_domain_type domain_type) | |
238 | { | |
239 | struct agent *agt = NULL; | |
240 | struct lttng_ht_node_u64 *node; | |
241 | struct lttng_ht_iter iter; | |
242 | uint64_t key; | |
243 | ||
244 | assert(session); | |
245 | ||
246 | DBG3("Trace ust agent lookup for domain %d", domain_type); | |
247 | ||
248 | key = domain_type; | |
249 | ||
250 | lttng_ht_lookup(session->agents, &key, &iter); | |
251 | node = lttng_ht_iter_get_node_u64(&iter); | |
252 | if (!node) { | |
253 | goto end; | |
254 | } | |
255 | agt = caa_container_of(node, struct agent, node); | |
256 | ||
257 | end: | |
258 | return agt; | |
259 | } | |
260 | ||
97ee3a89 DG |
261 | /* |
262 | * Allocate and initialize a ust session data structure. | |
263 | * | |
264 | * Return pointer to structure or NULL. | |
265 | */ | |
d9bf3ca4 | 266 | struct ltt_ust_session *trace_ust_create_session(uint64_t session_id) |
97ee3a89 DG |
267 | { |
268 | struct ltt_ust_session *lus; | |
269 | ||
270 | /* Allocate a new ltt ust session */ | |
ba7f0ae5 | 271 | lus = zmalloc(sizeof(struct ltt_ust_session)); |
97ee3a89 | 272 | if (lus == NULL) { |
ba7f0ae5 | 273 | PERROR("create ust session zmalloc"); |
55c9e7ca | 274 | goto error_alloc; |
97ee3a89 DG |
275 | } |
276 | ||
277 | /* Init data structure */ | |
a991f516 | 278 | lus->id = session_id; |
14fb1ebe | 279 | lus->active = 0; |
97ee3a89 | 280 | |
84ad93e8 DG |
281 | /* Set default metadata channel attribute. */ |
282 | lus->metadata_attr.overwrite = DEFAULT_CHANNEL_OVERWRITE; | |
283 | lus->metadata_attr.subbuf_size = default_get_metadata_subbuf_size(); | |
284 | lus->metadata_attr.num_subbuf = DEFAULT_METADATA_SUBBUF_NUM; | |
285 | lus->metadata_attr.switch_timer_interval = DEFAULT_METADATA_SWITCH_TIMER; | |
286 | lus->metadata_attr.read_timer_interval = DEFAULT_METADATA_READ_TIMER; | |
287 | lus->metadata_attr.output = LTTNG_UST_MMAP; | |
288 | ||
7972aab2 DG |
289 | /* |
290 | * Default buffer type. This can be changed through an enable channel | |
291 | * requesting a different type. Note that this can only be changed once | |
292 | * during the session lifetime which is at the first enable channel and | |
293 | * only before start. The flag buffer_type_changed indicates the status. | |
294 | */ | |
8692d4e5 | 295 | lus->buffer_type = LTTNG_BUFFER_PER_UID; |
7972aab2 DG |
296 | /* Once set to 1, the buffer_type is immutable for the session. */ |
297 | lus->buffer_type_changed = 0; | |
298 | /* Init it in case it get used after allocation. */ | |
299 | CDS_INIT_LIST_HEAD(&lus->buffer_reg_uid_list); | |
f6a9efaa DG |
300 | |
301 | /* Alloc UST global domain channels' HT */ | |
bec39940 | 302 | lus->domain_global.channels = lttng_ht_new(0, LTTNG_HT_TYPE_STRING); |
fefd409b DG |
303 | /* Alloc agent hash table. */ |
304 | lus->agents = lttng_ht_new(0, LTTNG_HT_TYPE_U64); | |
44d3bd01 | 305 | |
55c9e7ca JR |
306 | lus->tracker_list_vpid = lttng_tracker_list_create(); |
307 | if (!lus->tracker_list_vpid) { | |
308 | goto error; | |
309 | } | |
310 | lus->tracker_list_vuid = lttng_tracker_list_create(); | |
311 | if (!lus->tracker_list_vuid) { | |
312 | goto error; | |
313 | } | |
314 | lus->tracker_list_vgid = lttng_tracker_list_create(); | |
315 | if (!lus->tracker_list_vgid) { | |
316 | goto error; | |
317 | } | |
00e2e675 DG |
318 | lus->consumer = consumer_create_output(CONSUMER_DST_LOCAL); |
319 | if (lus->consumer == NULL) { | |
55c9e7ca | 320 | goto error; |
00e2e675 DG |
321 | } |
322 | ||
44d3bd01 DG |
323 | DBG2("UST trace session create successful"); |
324 | ||
97ee3a89 DG |
325 | return lus; |
326 | ||
55c9e7ca JR |
327 | error: |
328 | lttng_tracker_list_destroy(lus->tracker_list_vpid); | |
329 | lttng_tracker_list_destroy(lus->tracker_list_vuid); | |
330 | lttng_tracker_list_destroy(lus->tracker_list_vgid); | |
0b2dc8df | 331 | ht_cleanup_push(lus->domain_global.channels); |
fefd409b | 332 | ht_cleanup_push(lus->agents); |
44844c29 | 333 | free(lus); |
55c9e7ca | 334 | error_alloc: |
97ee3a89 DG |
335 | return NULL; |
336 | } | |
337 | ||
338 | /* | |
339 | * Allocate and initialize a ust channel data structure. | |
340 | * | |
341 | * Return pointer to structure or NULL. | |
342 | */ | |
51755dc8 JG |
343 | struct ltt_ust_channel *trace_ust_create_channel(struct lttng_channel *chan, |
344 | enum lttng_domain_type domain) | |
97ee3a89 | 345 | { |
97ee3a89 DG |
346 | struct ltt_ust_channel *luc; |
347 | ||
0525e9ae | 348 | assert(chan); |
0525e9ae | 349 | |
37357452 | 350 | luc = zmalloc(sizeof(struct ltt_ust_channel)); |
97ee3a89 | 351 | if (luc == NULL) { |
df0f840b | 352 | PERROR("ltt_ust_channel zmalloc"); |
97ee3a89 DG |
353 | goto error; |
354 | } | |
355 | ||
51755dc8 JG |
356 | luc->domain = domain; |
357 | ||
44d3bd01 | 358 | /* Copy UST channel attributes */ |
48842b30 DG |
359 | luc->attr.overwrite = chan->attr.overwrite; |
360 | luc->attr.subbuf_size = chan->attr.subbuf_size; | |
361 | luc->attr.num_subbuf = chan->attr.num_subbuf; | |
362 | luc->attr.switch_timer_interval = chan->attr.switch_timer_interval; | |
363 | luc->attr.read_timer_interval = chan->attr.read_timer_interval; | |
6775595e | 364 | luc->attr.output = (enum lttng_ust_output) chan->attr.output; |
82b4ebce JG |
365 | luc->monitor_timer_interval = ((struct lttng_channel_extended *) |
366 | chan->attr.extended.ptr)->monitor_timer_interval; | |
491d1539 MD |
367 | luc->attr.u.s.blocking_timeout = ((struct lttng_channel_extended *) |
368 | chan->attr.extended.ptr)->blocking_timeout; | |
44d3bd01 DG |
369 | |
370 | /* Translate to UST output enum */ | |
371 | switch (luc->attr.output) { | |
372 | default: | |
373 | luc->attr.output = LTTNG_UST_MMAP; | |
374 | break; | |
97ee3a89 | 375 | } |
97ee3a89 | 376 | |
85076754 MD |
377 | /* |
378 | * If we receive an empty string for channel name, it means the | |
379 | * default channel name is requested. | |
380 | */ | |
381 | if (chan->name[0] == '\0') { | |
382 | strncpy(luc->name, DEFAULT_CHANNEL_NAME, sizeof(luc->name)); | |
383 | } else { | |
384 | /* Copy channel name */ | |
385 | strncpy(luc->name, chan->name, sizeof(luc->name)); | |
386 | } | |
97ee3a89 DG |
387 | luc->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; |
388 | ||
f6a9efaa | 389 | /* Init node */ |
bec39940 | 390 | lttng_ht_node_init_str(&luc->node, luc->name); |
31746f93 DG |
391 | CDS_INIT_LIST_HEAD(&luc->ctx_list); |
392 | ||
f6a9efaa | 393 | /* Alloc hash tables */ |
bec39940 DG |
394 | luc->events = lttng_ht_new(0, LTTNG_HT_TYPE_STRING); |
395 | luc->ctx = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG); | |
f6a9efaa | 396 | |
1624d5b7 JD |
397 | /* On-disk circular buffer parameters */ |
398 | luc->tracefile_size = chan->attr.tracefile_size; | |
399 | luc->tracefile_count = chan->attr.tracefile_count; | |
400 | ||
f6a9efaa DG |
401 | DBG2("Trace UST channel %s created", luc->name); |
402 | ||
97ee3a89 | 403 | error: |
7972aab2 | 404 | return luc; |
97ee3a89 DG |
405 | } |
406 | ||
ad11a1d3 PP |
407 | /* |
408 | * Validates an exclusion list. | |
409 | * | |
410 | * Returns 0 if valid, negative value if invalid. | |
411 | */ | |
412 | static int validate_exclusion(struct lttng_event_exclusion *exclusion) | |
413 | { | |
414 | size_t i; | |
415 | int ret = 0; | |
416 | ||
417 | assert(exclusion); | |
418 | ||
419 | for (i = 0; i < exclusion->count; ++i) { | |
420 | size_t j; | |
421 | const char *name_a = | |
422 | LTTNG_EVENT_EXCLUSION_NAME_AT(exclusion, i); | |
423 | ||
424 | for (j = 0; j < i; ++j) { | |
425 | const char *name_b = | |
426 | LTTNG_EVENT_EXCLUSION_NAME_AT(exclusion, j); | |
427 | ||
428 | if (!strncmp(name_a, name_b, LTTNG_SYMBOL_NAME_LEN)) { | |
429 | /* Match! */ | |
430 | ret = -1; | |
431 | goto end; | |
432 | } | |
433 | } | |
434 | } | |
435 | ||
436 | end: | |
437 | return ret; | |
438 | } | |
439 | ||
97ee3a89 DG |
440 | /* |
441 | * Allocate and initialize a ust event. Set name and event type. | |
49d21f93 | 442 | * We own filter_expression, filter, and exclusion. |
97ee3a89 | 443 | * |
39687410 | 444 | * Return an lttng_error_code |
97ee3a89 | 445 | */ |
39687410 | 446 | enum lttng_error_code trace_ust_create_event(struct lttng_event *ev, |
6b453b5e | 447 | char *filter_expression, |
561c6897 | 448 | struct lttng_filter_bytecode *filter, |
88f06f15 | 449 | struct lttng_event_exclusion *exclusion, |
39687410 FD |
450 | bool internal_event, |
451 | struct ltt_ust_event **ust_event) | |
97ee3a89 | 452 | { |
39687410 FD |
453 | struct ltt_ust_event *local_ust_event; |
454 | enum lttng_error_code ret = LTTNG_OK; | |
97ee3a89 | 455 | |
0525e9ae DG |
456 | assert(ev); |
457 | ||
ad11a1d3 | 458 | if (exclusion && validate_exclusion(exclusion)) { |
39687410 | 459 | ret = LTTNG_ERR_INVALID; |
ad11a1d3 PP |
460 | goto error; |
461 | } | |
462 | ||
39687410 FD |
463 | local_ust_event = zmalloc(sizeof(struct ltt_ust_event)); |
464 | if (local_ust_event == NULL) { | |
ba7f0ae5 | 465 | PERROR("ust event zmalloc"); |
39687410 | 466 | ret = LTTNG_ERR_NOMEM; |
97ee3a89 DG |
467 | goto error; |
468 | } | |
469 | ||
39687410 | 470 | local_ust_event->internal = internal_event; |
88f06f15 | 471 | |
97ee3a89 DG |
472 | switch (ev->type) { |
473 | case LTTNG_EVENT_PROBE: | |
39687410 | 474 | local_ust_event->attr.instrumentation = LTTNG_UST_PROBE; |
97ee3a89 DG |
475 | break; |
476 | case LTTNG_EVENT_FUNCTION: | |
39687410 | 477 | local_ust_event->attr.instrumentation = LTTNG_UST_FUNCTION; |
97ee3a89 DG |
478 | break; |
479 | case LTTNG_EVENT_FUNCTION_ENTRY: | |
39687410 | 480 | local_ust_event->attr.instrumentation = LTTNG_UST_FUNCTION; |
97ee3a89 DG |
481 | break; |
482 | case LTTNG_EVENT_TRACEPOINT: | |
39687410 | 483 | local_ust_event->attr.instrumentation = LTTNG_UST_TRACEPOINT; |
97ee3a89 DG |
484 | break; |
485 | default: | |
486 | ERR("Unknown ust instrumentation type (%d)", ev->type); | |
39687410 | 487 | ret = LTTNG_ERR_INVALID; |
44844c29 | 488 | goto error_free_event; |
97ee3a89 DG |
489 | } |
490 | ||
491 | /* Copy event name */ | |
39687410 FD |
492 | strncpy(local_ust_event->attr.name, ev->name, LTTNG_UST_SYM_NAME_LEN); |
493 | local_ust_event->attr.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; | |
97ee3a89 | 494 | |
0cda4f28 | 495 | switch (ev->loglevel_type) { |
8005f29a | 496 | case LTTNG_EVENT_LOGLEVEL_ALL: |
39687410 FD |
497 | local_ust_event->attr.loglevel_type = LTTNG_UST_LOGLEVEL_ALL; |
498 | local_ust_event->attr.loglevel = -1; /* Force to -1 */ | |
0cda4f28 | 499 | break; |
8005f29a | 500 | case LTTNG_EVENT_LOGLEVEL_RANGE: |
39687410 FD |
501 | local_ust_event->attr.loglevel_type = LTTNG_UST_LOGLEVEL_RANGE; |
502 | local_ust_event->attr.loglevel = ev->loglevel; | |
8005f29a MD |
503 | break; |
504 | case LTTNG_EVENT_LOGLEVEL_SINGLE: | |
39687410 FD |
505 | local_ust_event->attr.loglevel_type = LTTNG_UST_LOGLEVEL_SINGLE; |
506 | local_ust_event->attr.loglevel = ev->loglevel; | |
0cda4f28 MD |
507 | break; |
508 | default: | |
4431494b | 509 | ERR("Unknown ust loglevel type (%d)", ev->loglevel_type); |
39687410 | 510 | ret = LTTNG_ERR_INVALID; |
0cda4f28 MD |
511 | goto error_free_event; |
512 | } | |
513 | ||
025faf73 | 514 | /* Same layout. */ |
39687410 FD |
515 | local_ust_event->filter_expression = filter_expression; |
516 | local_ust_event->filter = filter; | |
517 | local_ust_event->exclusion = exclusion; | |
0cda4f28 | 518 | |
f6a9efaa | 519 | /* Init node */ |
39687410 | 520 | lttng_ht_node_init_str(&local_ust_event->node, local_ust_event->attr.name); |
97ee3a89 | 521 | |
300b8fd5 | 522 | DBG2("Trace UST event %s, loglevel (%d,%d) created", |
39687410 FD |
523 | local_ust_event->attr.name, local_ust_event->attr.loglevel_type, |
524 | local_ust_event->attr.loglevel); | |
525 | ||
526 | *ust_event = local_ust_event; | |
284d8f55 | 527 | |
39687410 | 528 | return ret; |
97ee3a89 | 529 | |
44844c29 | 530 | error_free_event: |
39687410 | 531 | free(local_ust_event); |
97ee3a89 | 532 | error: |
49d21f93 MD |
533 | free(filter_expression); |
534 | free(filter); | |
535 | free(exclusion); | |
39687410 | 536 | return ret; |
97ee3a89 DG |
537 | } |
538 | ||
aa3514e9 | 539 | static |
bdf64013 JG |
540 | int trace_ust_context_type_event_to_ust( |
541 | enum lttng_event_context_type type) | |
55cc08a6 | 542 | { |
aa3514e9 | 543 | int utype; |
0525e9ae | 544 | |
aa3514e9 | 545 | switch (type) { |
9197c5c4 MD |
546 | case LTTNG_EVENT_CONTEXT_VTID: |
547 | utype = LTTNG_UST_CONTEXT_VTID; | |
548 | break; | |
549 | case LTTNG_EVENT_CONTEXT_VPID: | |
550 | utype = LTTNG_UST_CONTEXT_VPID; | |
551 | break; | |
552 | case LTTNG_EVENT_CONTEXT_PTHREAD_ID: | |
553 | utype = LTTNG_UST_CONTEXT_PTHREAD_ID; | |
554 | break; | |
555 | case LTTNG_EVENT_CONTEXT_PROCNAME: | |
556 | utype = LTTNG_UST_CONTEXT_PROCNAME; | |
557 | break; | |
7c612c2e WP |
558 | case LTTNG_EVENT_CONTEXT_IP: |
559 | utype = LTTNG_UST_CONTEXT_IP; | |
560 | break; | |
aa3514e9 | 561 | case LTTNG_EVENT_CONTEXT_PERF_THREAD_COUNTER: |
354e561b MD |
562 | if (!ustctl_has_perf_counters()) { |
563 | utype = -1; | |
564 | WARN("Perf counters not implemented in UST"); | |
565 | } else { | |
566 | utype = LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER; | |
567 | } | |
aa3514e9 | 568 | break; |
bdf64013 JG |
569 | case LTTNG_EVENT_CONTEXT_APP_CONTEXT: |
570 | utype = LTTNG_UST_CONTEXT_APP_CONTEXT; | |
571 | break; | |
f17b8732 MJ |
572 | case LTTNG_EVENT_CONTEXT_CGROUP_NS: |
573 | utype = LTTNG_UST_CONTEXT_CGROUP_NS; | |
574 | break; | |
575 | case LTTNG_EVENT_CONTEXT_IPC_NS: | |
576 | utype = LTTNG_UST_CONTEXT_IPC_NS; | |
577 | break; | |
578 | case LTTNG_EVENT_CONTEXT_MNT_NS: | |
579 | utype = LTTNG_UST_CONTEXT_MNT_NS; | |
580 | break; | |
581 | case LTTNG_EVENT_CONTEXT_NET_NS: | |
582 | utype = LTTNG_UST_CONTEXT_NET_NS; | |
583 | break; | |
584 | case LTTNG_EVENT_CONTEXT_PID_NS: | |
585 | utype = LTTNG_UST_CONTEXT_PID_NS; | |
586 | break; | |
587 | case LTTNG_EVENT_CONTEXT_USER_NS: | |
588 | utype = LTTNG_UST_CONTEXT_USER_NS; | |
589 | break; | |
590 | case LTTNG_EVENT_CONTEXT_UTS_NS: | |
591 | utype = LTTNG_UST_CONTEXT_UTS_NS; | |
592 | break; | |
4fc59cb8 MJ |
593 | case LTTNG_EVENT_CONTEXT_VUID: |
594 | utype = LTTNG_UST_CONTEXT_VUID; | |
595 | break; | |
596 | case LTTNG_EVENT_CONTEXT_VEUID: | |
597 | utype = LTTNG_UST_CONTEXT_VEUID; | |
598 | break; | |
599 | case LTTNG_EVENT_CONTEXT_VSUID: | |
600 | utype = LTTNG_UST_CONTEXT_VSUID; | |
601 | break; | |
602 | case LTTNG_EVENT_CONTEXT_VGID: | |
603 | utype = LTTNG_UST_CONTEXT_VGID; | |
604 | break; | |
605 | case LTTNG_EVENT_CONTEXT_VEGID: | |
606 | utype = LTTNG_UST_CONTEXT_VEGID; | |
607 | break; | |
608 | case LTTNG_EVENT_CONTEXT_VSGID: | |
609 | utype = LTTNG_UST_CONTEXT_VSGID; | |
610 | break; | |
9197c5c4 | 611 | default: |
aa3514e9 MD |
612 | utype = -1; |
613 | break; | |
614 | } | |
615 | return utype; | |
616 | } | |
617 | ||
618 | /* | |
619 | * Return 1 if contexts match, 0 otherwise. | |
620 | */ | |
df4f5a87 JG |
621 | int trace_ust_match_context(const struct ltt_ust_context *uctx, |
622 | const struct lttng_event_context *ctx) | |
aa3514e9 MD |
623 | { |
624 | int utype; | |
625 | ||
626 | utype = trace_ust_context_type_event_to_ust(ctx->ctx); | |
627 | if (utype < 0) { | |
628 | return 0; | |
629 | } | |
630 | if (uctx->ctx.ctx != utype) { | |
631 | return 0; | |
632 | } | |
633 | switch (utype) { | |
634 | case LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER: | |
635 | if (uctx->ctx.u.perf_counter.type | |
636 | != ctx->u.perf_counter.type) { | |
637 | return 0; | |
638 | } | |
639 | if (uctx->ctx.u.perf_counter.config | |
640 | != ctx->u.perf_counter.config) { | |
641 | return 0; | |
642 | } | |
643 | if (strncmp(uctx->ctx.u.perf_counter.name, | |
644 | ctx->u.perf_counter.name, | |
645 | LTTNG_UST_SYM_NAME_LEN)) { | |
646 | return 0; | |
647 | } | |
648 | break; | |
54fb33cf JG |
649 | case LTTNG_UST_CONTEXT_APP_CONTEXT: |
650 | assert(uctx->ctx.u.app_ctx.provider_name); | |
651 | assert(uctx->ctx.u.app_ctx.ctx_name); | |
652 | if (strcmp(uctx->ctx.u.app_ctx.provider_name, | |
653 | ctx->u.app_ctx.provider_name) || | |
654 | strcmp(uctx->ctx.u.app_ctx.ctx_name, | |
655 | ctx->u.app_ctx.ctx_name)) { | |
656 | return 0; | |
657 | } | |
aa3514e9 MD |
658 | default: |
659 | break; | |
660 | ||
661 | } | |
662 | return 1; | |
663 | } | |
664 | ||
665 | /* | |
666 | * Allocate and initialize an UST context. | |
667 | * | |
668 | * Return pointer to structure or NULL. | |
669 | */ | |
670 | struct ltt_ust_context *trace_ust_create_context( | |
df4f5a87 | 671 | const struct lttng_event_context *ctx) |
aa3514e9 | 672 | { |
bdf64013 | 673 | struct ltt_ust_context *uctx = NULL; |
aa3514e9 MD |
674 | int utype; |
675 | ||
676 | assert(ctx); | |
677 | ||
678 | utype = trace_ust_context_type_event_to_ust(ctx->ctx); | |
679 | if (utype < 0) { | |
1cf992b8 | 680 | ERR("Invalid UST context"); |
bdf64013 | 681 | goto end; |
9197c5c4 | 682 | } |
55cc08a6 DG |
683 | |
684 | uctx = zmalloc(sizeof(struct ltt_ust_context)); | |
bdf64013 | 685 | if (!uctx) { |
55cc08a6 | 686 | PERROR("zmalloc ltt_ust_context"); |
bdf64013 | 687 | goto end; |
55cc08a6 DG |
688 | } |
689 | ||
aa3514e9 MD |
690 | uctx->ctx.ctx = (enum lttng_ust_context_type) utype; |
691 | switch (utype) { | |
692 | case LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER: | |
693 | uctx->ctx.u.perf_counter.type = ctx->u.perf_counter.type; | |
694 | uctx->ctx.u.perf_counter.config = ctx->u.perf_counter.config; | |
695 | strncpy(uctx->ctx.u.perf_counter.name, ctx->u.perf_counter.name, | |
696 | LTTNG_UST_SYM_NAME_LEN); | |
697 | uctx->ctx.u.perf_counter.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; | |
698 | break; | |
bdf64013 JG |
699 | case LTTNG_UST_CONTEXT_APP_CONTEXT: |
700 | { | |
701 | char *provider_name = NULL, *ctx_name = NULL; | |
702 | ||
703 | provider_name = strdup(ctx->u.app_ctx.provider_name); | |
704 | if (!provider_name) { | |
705 | goto error; | |
706 | } | |
707 | uctx->ctx.u.app_ctx.provider_name = provider_name; | |
708 | ||
709 | ctx_name = strdup(ctx->u.app_ctx.ctx_name); | |
710 | if (!ctx_name) { | |
711 | goto error; | |
712 | } | |
713 | uctx->ctx.u.app_ctx.ctx_name = ctx_name; | |
714 | break; | |
715 | } | |
aa3514e9 MD |
716 | default: |
717 | break; | |
718 | } | |
bec39940 | 719 | lttng_ht_node_init_ulong(&uctx->node, (unsigned long) uctx->ctx.ctx); |
bdf64013 | 720 | end: |
55cc08a6 | 721 | return uctx; |
55cc08a6 | 722 | error: |
bdf64013 | 723 | trace_ust_destroy_context(uctx); |
55cc08a6 DG |
724 | return NULL; |
725 | } | |
726 | ||
55c9e7ca | 727 | static void destroy_id_tracker_node_rcu(struct rcu_head *head) |
a9ad0c8f | 728 | { |
55c9e7ca JR |
729 | struct ust_id_tracker_node *tracker_node = caa_container_of( |
730 | head, struct ust_id_tracker_node, node.head); | |
a9ad0c8f MD |
731 | free(tracker_node); |
732 | } | |
733 | ||
55c9e7ca | 734 | static void destroy_id_tracker_node(struct ust_id_tracker_node *tracker_node) |
a9ad0c8f | 735 | { |
55c9e7ca | 736 | call_rcu(&tracker_node->node.head, destroy_id_tracker_node_rcu); |
a9ad0c8f MD |
737 | } |
738 | ||
55c9e7ca | 739 | static int init_id_tracker(struct ust_id_tracker *id_tracker) |
a9ad0c8f | 740 | { |
55c9e7ca | 741 | int ret = LTTNG_OK; |
a9ad0c8f | 742 | |
55c9e7ca JR |
743 | id_tracker->ht = lttng_ht_new(0, LTTNG_HT_TYPE_ULONG); |
744 | if (!id_tracker->ht) { | |
745 | ret = LTTNG_ERR_NOMEM; | |
a9ad0c8f MD |
746 | goto end; |
747 | } | |
748 | ||
749 | end: | |
750 | return ret; | |
751 | } | |
752 | ||
753 | /* | |
55c9e7ca | 754 | * Teardown id tracker content, but don't free id_tracker object. |
a9ad0c8f | 755 | */ |
55c9e7ca | 756 | static void fini_id_tracker(struct ust_id_tracker *id_tracker) |
a9ad0c8f | 757 | { |
55c9e7ca | 758 | struct ust_id_tracker_node *tracker_node; |
a9ad0c8f MD |
759 | struct lttng_ht_iter iter; |
760 | ||
55c9e7ca | 761 | if (!id_tracker->ht) { |
a9ad0c8f MD |
762 | return; |
763 | } | |
764 | rcu_read_lock(); | |
55c9e7ca JR |
765 | cds_lfht_for_each_entry (id_tracker->ht->ht, &iter.iter, tracker_node, |
766 | node.node) { | |
767 | int ret = lttng_ht_del(id_tracker->ht, &iter); | |
a9ad0c8f MD |
768 | |
769 | assert(!ret); | |
55c9e7ca | 770 | destroy_id_tracker_node(tracker_node); |
a9ad0c8f MD |
771 | } |
772 | rcu_read_unlock(); | |
55c9e7ca JR |
773 | ht_cleanup_push(id_tracker->ht); |
774 | id_tracker->ht = NULL; | |
a9ad0c8f MD |
775 | } |
776 | ||
55c9e7ca JR |
777 | static struct ust_id_tracker_node *id_tracker_lookup( |
778 | struct ust_id_tracker *id_tracker, | |
779 | int id, | |
a9ad0c8f MD |
780 | struct lttng_ht_iter *iter) |
781 | { | |
55c9e7ca | 782 | unsigned long _id = (unsigned long) id; |
a9ad0c8f MD |
783 | struct lttng_ht_node_ulong *node; |
784 | ||
55c9e7ca | 785 | lttng_ht_lookup(id_tracker->ht, (void *) _id, iter); |
a9ad0c8f MD |
786 | node = lttng_ht_iter_get_node_ulong(iter); |
787 | if (node) { | |
55c9e7ca | 788 | return caa_container_of(node, struct ust_id_tracker_node, node); |
a9ad0c8f MD |
789 | } else { |
790 | return NULL; | |
791 | } | |
792 | } | |
793 | ||
55c9e7ca | 794 | static int id_tracker_add_id(struct ust_id_tracker *id_tracker, int id) |
a9ad0c8f MD |
795 | { |
796 | int retval = LTTNG_OK; | |
55c9e7ca | 797 | struct ust_id_tracker_node *tracker_node; |
a9ad0c8f MD |
798 | struct lttng_ht_iter iter; |
799 | ||
55c9e7ca | 800 | if (id < 0) { |
a9ad0c8f MD |
801 | retval = LTTNG_ERR_INVALID; |
802 | goto end; | |
803 | } | |
55c9e7ca | 804 | tracker_node = id_tracker_lookup(id_tracker, id, &iter); |
a9ad0c8f MD |
805 | if (tracker_node) { |
806 | /* Already exists. */ | |
55c9e7ca | 807 | retval = LTTNG_ERR_ID_TRACKED; |
a9ad0c8f MD |
808 | goto end; |
809 | } | |
810 | tracker_node = zmalloc(sizeof(*tracker_node)); | |
811 | if (!tracker_node) { | |
812 | retval = LTTNG_ERR_NOMEM; | |
813 | goto end; | |
814 | } | |
55c9e7ca JR |
815 | lttng_ht_node_init_ulong(&tracker_node->node, (unsigned long) id); |
816 | lttng_ht_add_unique_ulong(id_tracker->ht, &tracker_node->node); | |
a9ad0c8f MD |
817 | end: |
818 | return retval; | |
819 | } | |
820 | ||
55c9e7ca | 821 | static int id_tracker_del_id(struct ust_id_tracker *id_tracker, int id) |
a9ad0c8f MD |
822 | { |
823 | int retval = LTTNG_OK, ret; | |
55c9e7ca | 824 | struct ust_id_tracker_node *tracker_node; |
a9ad0c8f MD |
825 | struct lttng_ht_iter iter; |
826 | ||
55c9e7ca | 827 | if (id < 0) { |
a9ad0c8f MD |
828 | retval = LTTNG_ERR_INVALID; |
829 | goto end; | |
830 | } | |
55c9e7ca | 831 | tracker_node = id_tracker_lookup(id_tracker, id, &iter); |
a9ad0c8f MD |
832 | if (!tracker_node) { |
833 | /* Not found */ | |
55c9e7ca | 834 | retval = LTTNG_ERR_ID_NOT_TRACKED; |
a9ad0c8f MD |
835 | goto end; |
836 | } | |
55c9e7ca | 837 | ret = lttng_ht_del(id_tracker->ht, &iter); |
a9ad0c8f MD |
838 | assert(!ret); |
839 | ||
55c9e7ca | 840 | destroy_id_tracker_node(tracker_node); |
a9ad0c8f MD |
841 | end: |
842 | return retval; | |
843 | } | |
844 | ||
55c9e7ca JR |
845 | static struct ust_id_tracker *get_id_tracker(struct ltt_ust_session *session, |
846 | enum lttng_tracker_type tracker_type) | |
847 | { | |
848 | switch (tracker_type) { | |
849 | case LTTNG_TRACKER_VPID: | |
850 | return &session->vpid_tracker; | |
851 | case LTTNG_TRACKER_VUID: | |
852 | return &session->vuid_tracker; | |
853 | case LTTNG_TRACKER_VGID: | |
854 | return &session->vgid_tracker; | |
855 | default: | |
856 | return NULL; | |
857 | } | |
858 | } | |
859 | ||
860 | static struct lttng_tracker_list *get_id_tracker_list( | |
861 | struct ltt_ust_session *session, | |
862 | enum lttng_tracker_type tracker_type) | |
863 | { | |
864 | switch (tracker_type) { | |
865 | case LTTNG_TRACKER_VPID: | |
866 | return session->tracker_list_vpid; | |
867 | case LTTNG_TRACKER_VUID: | |
868 | return session->tracker_list_vuid; | |
869 | case LTTNG_TRACKER_VGID: | |
870 | return session->tracker_list_vgid; | |
871 | default: | |
872 | return NULL; | |
873 | } | |
874 | } | |
875 | ||
a9ad0c8f MD |
876 | /* |
877 | * The session lock is held when calling this function. | |
878 | */ | |
55c9e7ca JR |
879 | int trace_ust_id_tracker_lookup(enum lttng_tracker_type tracker_type, |
880 | struct ltt_ust_session *session, | |
881 | int id) | |
a9ad0c8f MD |
882 | { |
883 | struct lttng_ht_iter iter; | |
55c9e7ca | 884 | struct ust_id_tracker *id_tracker; |
a9ad0c8f | 885 | |
55c9e7ca JR |
886 | id_tracker = get_id_tracker(session, tracker_type); |
887 | if (!id_tracker) { | |
888 | abort(); | |
889 | } | |
890 | if (!id_tracker->ht) { | |
a9ad0c8f MD |
891 | return 1; |
892 | } | |
55c9e7ca | 893 | if (id_tracker_lookup(id_tracker, id, &iter)) { |
a9ad0c8f MD |
894 | return 1; |
895 | } | |
896 | return 0; | |
897 | } | |
898 | ||
899 | /* | |
900 | * Called with the session lock held. | |
901 | */ | |
55c9e7ca JR |
902 | int trace_ust_track_id(enum lttng_tracker_type tracker_type, |
903 | struct ltt_ust_session *session, | |
904 | const struct lttng_tracker_id *id) | |
a9ad0c8f MD |
905 | { |
906 | int retval = LTTNG_OK; | |
88e3c2f5 | 907 | bool should_update_apps = false; |
55c9e7ca JR |
908 | struct ust_id_tracker *id_tracker; |
909 | struct lttng_tracker_list *tracker_list; | |
910 | int value; | |
a7a533cd | 911 | struct lttng_tracker_ids *saved_ids; |
55c9e7ca JR |
912 | |
913 | if (tracker_type == LTTNG_TRACKER_PID) { | |
914 | DBG("Backward compatible behavior: translate PID tracker to VPID tracker for UST domain."); | |
915 | tracker_type = LTTNG_TRACKER_VPID; | |
916 | } | |
a9ad0c8f | 917 | |
55c9e7ca JR |
918 | retval = lttng_tracker_id_lookup_string(tracker_type, id, &value); |
919 | if (retval != LTTNG_OK) { | |
920 | return retval; | |
921 | } | |
922 | tracker_list = get_id_tracker_list(session, tracker_type); | |
923 | if (!tracker_list) { | |
924 | return LTTNG_ERR_INVALID; | |
925 | } | |
926 | /* Save list for restore on error. */ | |
a7a533cd JR |
927 | retval = lttng_tracker_id_get_list(tracker_list, &saved_ids); |
928 | if (retval != LTTNG_OK) { | |
55c9e7ca JR |
929 | return LTTNG_ERR_INVALID; |
930 | } | |
931 | /* Add to list. */ | |
932 | retval = lttng_tracker_list_add(tracker_list, id); | |
933 | if (retval != LTTNG_OK) { | |
934 | goto end; | |
935 | } | |
936 | ||
937 | id_tracker = get_id_tracker(session, tracker_type); | |
938 | if (!id_tracker) { | |
939 | abort(); | |
940 | } | |
941 | if (value == -1) { | |
942 | /* Track all ids: destroy tracker if exists. */ | |
943 | if (id_tracker->ht) { | |
944 | fini_id_tracker(id_tracker); | |
a9ad0c8f | 945 | /* Ensure all apps have session. */ |
88e3c2f5 | 946 | should_update_apps = true; |
a9ad0c8f MD |
947 | } |
948 | } else { | |
55c9e7ca | 949 | if (!id_tracker->ht) { |
a9ad0c8f | 950 | /* Create tracker. */ |
55c9e7ca JR |
951 | retval = init_id_tracker(id_tracker); |
952 | if (retval != LTTNG_OK) { | |
953 | ERR("Error initializing ID tracker"); | |
954 | goto end_restore; | |
a9ad0c8f | 955 | } |
55c9e7ca JR |
956 | retval = id_tracker_add_id(id_tracker, value); |
957 | if (retval != LTTNG_OK) { | |
958 | fini_id_tracker(id_tracker); | |
959 | goto end_restore; | |
a9ad0c8f MD |
960 | } |
961 | /* Remove all apps from session except pid. */ | |
88e3c2f5 | 962 | should_update_apps = true; |
a9ad0c8f MD |
963 | } else { |
964 | struct ust_app *app; | |
965 | ||
55c9e7ca JR |
966 | retval = id_tracker_add_id(id_tracker, value); |
967 | if (retval != LTTNG_OK) { | |
968 | goto end_restore; | |
a9ad0c8f MD |
969 | } |
970 | /* Add session to application */ | |
55c9e7ca JR |
971 | switch (tracker_type) { |
972 | case LTTNG_TRACKER_VPID: | |
973 | app = ust_app_find_by_pid(value); | |
974 | if (app) { | |
975 | should_update_apps = true; | |
976 | } | |
977 | break; | |
978 | default: | |
88e3c2f5 | 979 | should_update_apps = true; |
a9ad0c8f MD |
980 | } |
981 | } | |
982 | } | |
88e3c2f5 JG |
983 | if (should_update_apps && session->active) { |
984 | ust_app_global_update_all(session); | |
985 | } | |
55c9e7ca JR |
986 | goto end; |
987 | ||
988 | end_restore: | |
a7a533cd | 989 | if (lttng_tracker_id_set_list(tracker_list, saved_ids) != LTTNG_OK) { |
55c9e7ca JR |
990 | ERR("Error on tracker add error handling.\n"); |
991 | } | |
a9ad0c8f | 992 | end: |
a7a533cd | 993 | lttng_tracker_ids_destroy(saved_ids); |
a9ad0c8f MD |
994 | return retval; |
995 | } | |
996 | ||
997 | /* | |
998 | * Called with the session lock held. | |
999 | */ | |
55c9e7ca JR |
1000 | int trace_ust_untrack_id(enum lttng_tracker_type tracker_type, |
1001 | struct ltt_ust_session *session, | |
1002 | const struct lttng_tracker_id *id) | |
a9ad0c8f MD |
1003 | { |
1004 | int retval = LTTNG_OK; | |
a5a30920 | 1005 | bool should_update_apps = false; |
55c9e7ca JR |
1006 | struct ust_id_tracker *id_tracker; |
1007 | struct lttng_tracker_list *tracker_list; | |
1008 | int value; | |
a7a533cd | 1009 | struct lttng_tracker_ids *saved_ids; |
55c9e7ca JR |
1010 | |
1011 | if (tracker_type == LTTNG_TRACKER_PID) { | |
1012 | DBG("Backward compatible behavior: translate PID tracker to VPID tracker for UST domain."); | |
1013 | tracker_type = LTTNG_TRACKER_VPID; | |
1014 | } | |
1015 | ||
1016 | retval = lttng_tracker_id_lookup_string(tracker_type, id, &value); | |
1017 | if (retval != LTTNG_OK) { | |
1018 | return retval; | |
1019 | } | |
1020 | ||
1021 | tracker_list = get_id_tracker_list(session, tracker_type); | |
1022 | if (!tracker_list) { | |
1023 | return LTTNG_ERR_INVALID; | |
1024 | } | |
1025 | /* Save list for restore on error. */ | |
a7a533cd JR |
1026 | retval = lttng_tracker_id_get_list(tracker_list, &saved_ids); |
1027 | if (retval != LTTNG_OK) { | |
55c9e7ca JR |
1028 | return LTTNG_ERR_INVALID; |
1029 | } | |
1030 | /* Remove from list. */ | |
1031 | retval = lttng_tracker_list_remove(tracker_list, id); | |
1032 | if (retval != LTTNG_OK) { | |
1033 | goto end; | |
1034 | } | |
a9ad0c8f | 1035 | |
55c9e7ca JR |
1036 | id_tracker = get_id_tracker(session, tracker_type); |
1037 | if (!id_tracker) { | |
1038 | abort(); | |
1039 | } | |
1040 | ||
1041 | if (value == -1) { | |
a9ad0c8f | 1042 | /* Create empty tracker, replace old tracker. */ |
55c9e7ca | 1043 | struct ust_id_tracker tmp_tracker; |
a9ad0c8f | 1044 | |
55c9e7ca JR |
1045 | tmp_tracker = *id_tracker; |
1046 | retval = init_id_tracker(id_tracker); | |
1047 | if (retval != LTTNG_OK) { | |
1048 | ERR("Error initializing ID tracker"); | |
a9ad0c8f | 1049 | /* Rollback operation. */ |
55c9e7ca JR |
1050 | *id_tracker = tmp_tracker; |
1051 | goto end_restore; | |
a9ad0c8f | 1052 | } |
55c9e7ca | 1053 | fini_id_tracker(&tmp_tracker); |
a9ad0c8f MD |
1054 | |
1055 | /* Remove session from all applications */ | |
a5a30920 | 1056 | should_update_apps = true; |
a9ad0c8f | 1057 | } else { |
a9ad0c8f MD |
1058 | struct ust_app *app; |
1059 | ||
55c9e7ca JR |
1060 | if (!id_tracker->ht) { |
1061 | /* No ID being tracked. */ | |
1062 | retval = LTTNG_ERR_ID_NOT_TRACKED; | |
1063 | goto end_restore; | |
a9ad0c8f | 1064 | } |
55c9e7ca JR |
1065 | /* Remove ID from tracker */ |
1066 | retval = id_tracker_del_id(id_tracker, value); | |
1067 | if (retval != LTTNG_OK) { | |
1068 | goto end_restore; | |
a9ad0c8f | 1069 | } |
55c9e7ca JR |
1070 | switch (tracker_type) { |
1071 | case LTTNG_TRACKER_VPID: | |
1072 | /* Remove session from application. */ | |
1073 | app = ust_app_find_by_pid(value); | |
1074 | if (app) { | |
1075 | should_update_apps = true; | |
1076 | } | |
1077 | break; | |
1078 | default: | |
1079 | /* Keep only apps matching ID. */ | |
a5a30920 | 1080 | should_update_apps = true; |
a9ad0c8f MD |
1081 | } |
1082 | } | |
a5a30920 JR |
1083 | if (should_update_apps && session->active) { |
1084 | ust_app_global_update_all(session); | |
1085 | } | |
55c9e7ca JR |
1086 | goto end; |
1087 | ||
1088 | end_restore: | |
a7a533cd | 1089 | if (lttng_tracker_id_set_list(tracker_list, saved_ids) != LTTNG_OK) { |
55c9e7ca JR |
1090 | ERR("Error on tracker remove error handling.\n"); |
1091 | } | |
a9ad0c8f | 1092 | end: |
a7a533cd | 1093 | lttng_tracker_ids_destroy(saved_ids); |
a9ad0c8f MD |
1094 | return retval; |
1095 | } | |
1096 | ||
a5dfbb9d MD |
1097 | /* |
1098 | * Called with session lock held. | |
1099 | */ | |
a7a533cd | 1100 | int trace_ust_list_tracker_ids(enum lttng_tracker_type tracker_type, |
55c9e7ca | 1101 | struct ltt_ust_session *session, |
a7a533cd | 1102 | struct lttng_tracker_ids **_ids) |
a5dfbb9d | 1103 | { |
a7a533cd | 1104 | int ret = LTTNG_OK; |
55c9e7ca | 1105 | struct lttng_tracker_list *tracker_list; |
a5dfbb9d | 1106 | |
55c9e7ca JR |
1107 | if (tracker_type == LTTNG_TRACKER_PID) { |
1108 | DBG("Backward compatible behavior: translate PID tracker to VPID tracker for UST domain."); | |
1109 | tracker_type = LTTNG_TRACKER_VPID; | |
a5dfbb9d MD |
1110 | } |
1111 | ||
55c9e7ca JR |
1112 | tracker_list = get_id_tracker_list(session, tracker_type); |
1113 | if (!tracker_list) { | |
a7a533cd JR |
1114 | ret = -LTTNG_ERR_INVALID; |
1115 | goto end; | |
a5dfbb9d | 1116 | } |
a7a533cd JR |
1117 | |
1118 | ret = lttng_tracker_id_get_list(tracker_list, _ids); | |
1119 | if (ret != LTTNG_OK) { | |
1120 | ret = -LTTNG_ERR_INVALID; | |
1121 | goto end; | |
1122 | } | |
1123 | end: | |
1124 | return ret; | |
a5dfbb9d MD |
1125 | } |
1126 | ||
f6a9efaa DG |
1127 | /* |
1128 | * RCU safe free context structure. | |
1129 | */ | |
1130 | static void destroy_context_rcu(struct rcu_head *head) | |
1131 | { | |
bec39940 DG |
1132 | struct lttng_ht_node_ulong *node = |
1133 | caa_container_of(head, struct lttng_ht_node_ulong, head); | |
f6a9efaa DG |
1134 | struct ltt_ust_context *ctx = |
1135 | caa_container_of(node, struct ltt_ust_context, node); | |
1136 | ||
bdf64013 | 1137 | trace_ust_destroy_context(ctx); |
f6a9efaa DG |
1138 | } |
1139 | ||
1140 | /* | |
1141 | * Cleanup UST context hash table. | |
1142 | */ | |
7bd39047 | 1143 | static void destroy_contexts(struct lttng_ht *ht) |
f6a9efaa DG |
1144 | { |
1145 | int ret; | |
bec39940 DG |
1146 | struct lttng_ht_node_ulong *node; |
1147 | struct lttng_ht_iter iter; | |
31746f93 | 1148 | struct ltt_ust_context *ctx; |
f6a9efaa | 1149 | |
0525e9ae DG |
1150 | assert(ht); |
1151 | ||
36b588ed | 1152 | rcu_read_lock(); |
bec39940 | 1153 | cds_lfht_for_each_entry(ht->ht, &iter.iter, node, node) { |
31746f93 DG |
1154 | /* Remove from ordered list. */ |
1155 | ctx = caa_container_of(node, struct ltt_ust_context, node); | |
1156 | cds_list_del(&ctx->list); | |
1157 | /* Remove from channel's hash table. */ | |
bec39940 | 1158 | ret = lttng_ht_del(ht, &iter); |
f6a9efaa DG |
1159 | if (!ret) { |
1160 | call_rcu(&node->head, destroy_context_rcu); | |
1161 | } | |
f6a9efaa | 1162 | } |
36b588ed | 1163 | rcu_read_unlock(); |
ed52805d | 1164 | |
0b2dc8df | 1165 | ht_cleanup_push(ht); |
f6a9efaa DG |
1166 | } |
1167 | ||
97ee3a89 DG |
1168 | /* |
1169 | * Cleanup ust event structure. | |
1170 | */ | |
1171 | void trace_ust_destroy_event(struct ltt_ust_event *event) | |
1172 | { | |
0525e9ae DG |
1173 | assert(event); |
1174 | ||
f6a9efaa | 1175 | DBG2("Trace destroy UST event %s", event->attr.name); |
6b453b5e | 1176 | free(event->filter_expression); |
53a80697 | 1177 | free(event->filter); |
40024f8a | 1178 | free(event->exclusion); |
97ee3a89 DG |
1179 | free(event); |
1180 | } | |
1181 | ||
bdf64013 JG |
1182 | /* |
1183 | * Cleanup ust context structure. | |
1184 | */ | |
1185 | void trace_ust_destroy_context(struct ltt_ust_context *ctx) | |
1186 | { | |
1187 | assert(ctx); | |
1188 | ||
1189 | if (ctx->ctx.ctx == LTTNG_UST_CONTEXT_APP_CONTEXT) { | |
1190 | free(ctx->ctx.u.app_ctx.provider_name); | |
1191 | free(ctx->ctx.u.app_ctx.ctx_name); | |
1192 | } | |
1193 | free(ctx); | |
1194 | } | |
1195 | ||
f6a9efaa DG |
1196 | /* |
1197 | * URCU intermediate call to complete destroy event. | |
1198 | */ | |
1199 | static void destroy_event_rcu(struct rcu_head *head) | |
1200 | { | |
bec39940 DG |
1201 | struct lttng_ht_node_str *node = |
1202 | caa_container_of(head, struct lttng_ht_node_str, head); | |
f6a9efaa DG |
1203 | struct ltt_ust_event *event = |
1204 | caa_container_of(node, struct ltt_ust_event, node); | |
1205 | ||
1206 | trace_ust_destroy_event(event); | |
1207 | } | |
1208 | ||
284d8f55 DG |
1209 | /* |
1210 | * Cleanup UST events hashtable. | |
1211 | */ | |
7bd39047 | 1212 | static void destroy_events(struct lttng_ht *events) |
ed52805d DG |
1213 | { |
1214 | int ret; | |
bec39940 DG |
1215 | struct lttng_ht_node_str *node; |
1216 | struct lttng_ht_iter iter; | |
ed52805d | 1217 | |
0525e9ae DG |
1218 | assert(events); |
1219 | ||
36b588ed | 1220 | rcu_read_lock(); |
bec39940 DG |
1221 | cds_lfht_for_each_entry(events->ht, &iter.iter, node, node) { |
1222 | ret = lttng_ht_del(events, &iter); | |
7bd39047 DG |
1223 | assert(!ret); |
1224 | call_rcu(&node->head, destroy_event_rcu); | |
ed52805d | 1225 | } |
36b588ed | 1226 | rcu_read_unlock(); |
ed52805d | 1227 | |
0b2dc8df | 1228 | ht_cleanup_push(events); |
ed52805d DG |
1229 | } |
1230 | ||
97ee3a89 DG |
1231 | /* |
1232 | * Cleanup ust channel structure. | |
36b588ed MD |
1233 | * |
1234 | * Should _NOT_ be called with RCU read lock held. | |
97ee3a89 | 1235 | */ |
36b588ed | 1236 | static void _trace_ust_destroy_channel(struct ltt_ust_channel *channel) |
97ee3a89 | 1237 | { |
0525e9ae DG |
1238 | assert(channel); |
1239 | ||
f6a9efaa | 1240 | DBG2("Trace destroy UST channel %s", channel->name); |
97ee3a89 | 1241 | |
97ee3a89 | 1242 | free(channel); |
f6a9efaa DG |
1243 | } |
1244 | ||
1245 | /* | |
1246 | * URCU intermediate call to complete destroy channel. | |
1247 | */ | |
1248 | static void destroy_channel_rcu(struct rcu_head *head) | |
1249 | { | |
bec39940 DG |
1250 | struct lttng_ht_node_str *node = |
1251 | caa_container_of(head, struct lttng_ht_node_str, head); | |
f6a9efaa DG |
1252 | struct ltt_ust_channel *channel = |
1253 | caa_container_of(node, struct ltt_ust_channel, node); | |
1254 | ||
36b588ed MD |
1255 | _trace_ust_destroy_channel(channel); |
1256 | } | |
1257 | ||
1258 | void trace_ust_destroy_channel(struct ltt_ust_channel *channel) | |
1259 | { | |
627cbbe7 MD |
1260 | /* Destroying all events of the channel */ |
1261 | destroy_events(channel->events); | |
1262 | /* Destroying all context of the channel */ | |
1263 | destroy_contexts(channel->ctx); | |
1264 | ||
36b588ed | 1265 | call_rcu(&channel->node.head, destroy_channel_rcu); |
97ee3a89 DG |
1266 | } |
1267 | ||
d5979e4a DG |
1268 | /* |
1269 | * Remove an UST channel from a channel HT. | |
1270 | */ | |
1271 | void trace_ust_delete_channel(struct lttng_ht *ht, | |
1272 | struct ltt_ust_channel *channel) | |
1273 | { | |
1274 | int ret; | |
1275 | struct lttng_ht_iter iter; | |
1276 | ||
1277 | assert(ht); | |
1278 | assert(channel); | |
1279 | ||
1280 | iter.iter.node = &channel->node.node; | |
1281 | ret = lttng_ht_del(ht, &iter); | |
1282 | assert(!ret); | |
1283 | } | |
1284 | ||
97ee3a89 | 1285 | /* |
f6a9efaa | 1286 | * Iterate over a hash table containing channels and cleanup safely. |
97ee3a89 | 1287 | */ |
bec39940 | 1288 | static void destroy_channels(struct lttng_ht *channels) |
f6a9efaa | 1289 | { |
bec39940 DG |
1290 | struct lttng_ht_node_str *node; |
1291 | struct lttng_ht_iter iter; | |
f6a9efaa | 1292 | |
0525e9ae DG |
1293 | assert(channels); |
1294 | ||
24d1723f | 1295 | rcu_read_lock(); |
bec39940 | 1296 | cds_lfht_for_each_entry(channels->ht, &iter.iter, node, node) { |
627cbbe7 MD |
1297 | struct ltt_ust_channel *chan = |
1298 | caa_container_of(node, struct ltt_ust_channel, node); | |
1299 | ||
1300 | trace_ust_delete_channel(channels, chan); | |
1301 | trace_ust_destroy_channel(chan); | |
f6a9efaa | 1302 | } |
36b588ed | 1303 | rcu_read_unlock(); |
ed52805d | 1304 | |
0b2dc8df | 1305 | ht_cleanup_push(channels); |
f6a9efaa DG |
1306 | } |
1307 | ||
f6a9efaa DG |
1308 | /* |
1309 | * Cleanup UST global domain. | |
1310 | */ | |
1311 | static void destroy_domain_global(struct ltt_ust_domain_global *dom) | |
1312 | { | |
0525e9ae DG |
1313 | assert(dom); |
1314 | ||
f6a9efaa DG |
1315 | destroy_channels(dom->channels); |
1316 | } | |
97ee3a89 | 1317 | |
f6a9efaa | 1318 | /* |
d070c424 MD |
1319 | * Cleanup ust session structure, keeping data required by |
1320 | * destroy notifier. | |
36b588ed MD |
1321 | * |
1322 | * Should *NOT* be called with RCU read-side lock held. | |
f6a9efaa DG |
1323 | */ |
1324 | void trace_ust_destroy_session(struct ltt_ust_session *session) | |
1325 | { | |
fefd409b | 1326 | struct agent *agt; |
7972aab2 | 1327 | struct buffer_reg_uid *reg, *sreg; |
fefd409b | 1328 | struct lttng_ht_iter iter; |
7972aab2 | 1329 | |
0525e9ae | 1330 | assert(session); |
97ee3a89 | 1331 | |
d9bf3ca4 | 1332 | DBG2("Trace UST destroy session %" PRIu64, session->id); |
f6a9efaa | 1333 | |
f6a9efaa DG |
1334 | /* Cleaning up UST domain */ |
1335 | destroy_domain_global(&session->domain_global); | |
fefd409b | 1336 | |
0c0fcd77 | 1337 | rcu_read_lock(); |
fefd409b | 1338 | cds_lfht_for_each_entry(session->agents->ht, &iter.iter, agt, node.node) { |
d0edf546 JG |
1339 | int ret = lttng_ht_del(session->agents, &iter); |
1340 | ||
1341 | assert(!ret); | |
fefd409b DG |
1342 | agent_destroy(agt); |
1343 | } | |
0c0fcd77 | 1344 | rcu_read_unlock(); |
7972aab2 | 1345 | |
8ada2175 MD |
1346 | ht_cleanup_push(session->agents); |
1347 | ||
7972aab2 DG |
1348 | /* Cleanup UID buffer registry object(s). */ |
1349 | cds_list_for_each_entry_safe(reg, sreg, &session->buffer_reg_uid_list, | |
1350 | lnode) { | |
1351 | cds_list_del(®->lnode); | |
1352 | buffer_reg_uid_remove(reg); | |
1353 | buffer_reg_uid_destroy(reg, session->consumer); | |
1354 | } | |
44d3bd01 | 1355 | |
55c9e7ca JR |
1356 | lttng_tracker_list_destroy(session->tracker_list_vpid); |
1357 | lttng_tracker_list_destroy(session->tracker_list_vuid); | |
1358 | lttng_tracker_list_destroy(session->tracker_list_vgid); | |
1359 | ||
1360 | fini_id_tracker(&session->vpid_tracker); | |
1361 | fini_id_tracker(&session->vuid_tracker); | |
1362 | fini_id_tracker(&session->vgid_tracker); | |
82b69413 | 1363 | lttng_trace_chunk_put(session->current_trace_chunk); |
d070c424 MD |
1364 | } |
1365 | ||
1366 | /* Free elements needed by destroy notifiers. */ | |
1367 | void trace_ust_free_session(struct ltt_ust_session *session) | |
1368 | { | |
1369 | consumer_output_put(session->consumer); | |
97ee3a89 DG |
1370 | free(session); |
1371 | } |