Commit | Line | Data |
---|---|---|
54012638 | 1 | /* |
ab5be9fa | 2 | * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca> |
54012638 | 3 | * |
ab5be9fa | 4 | * SPDX-License-Identifier: GPL-2.0-only |
54012638 | 5 | * |
54012638 DG |
6 | */ |
7 | ||
6c1c0768 | 8 | #define _LGPL_SOURCE |
54012638 DG |
9 | #include <stdio.h> |
10 | #include <stdlib.h> | |
11 | #include <string.h> | |
c363b55d | 12 | #include <unistd.h> |
54012638 | 13 | |
dcabc190 FD |
14 | #include <lttng/event.h> |
15 | #include <lttng/lttng-error.h> | |
352b58f5 | 16 | #include <lttng/kernel-probe.h> |
dcabc190 FD |
17 | #include <lttng/userspace-probe.h> |
18 | #include <lttng/userspace-probe-internal.h> | |
352b58f5 JR |
19 | #include <lttng/event-rule/event-rule.h> |
20 | #include <lttng/event-rule/event-rule-internal.h> | |
85522de5 JR |
21 | #include <lttng/event-rule/kernel-kprobe.h> |
22 | #include <lttng/event-rule/kernel-kprobe-internal.h> | |
4f7da553 JR |
23 | #include <lttng/event-rule/kernel-syscall.h> |
24 | #include <lttng/event-rule/kernel-syscall-internal.h> | |
695f7044 JR |
25 | #include <lttng/event-rule/kernel-tracepoint.h> |
26 | #include <lttng/event-rule/kernel-tracepoint-internal.h> | |
27 | #include <lttng/event-rule/kernel-uprobe.h> | |
46fd07ac | 28 | #include <lttng/event-rule/kernel-uprobe-internal.h> |
990570ed DG |
29 | #include <common/common.h> |
30 | #include <common/defaults.h> | |
82b69413 | 31 | #include <common/trace-chunk.h> |
d42266a4 | 32 | #include <common/macros.h> |
1e307fab | 33 | |
00e2e675 | 34 | #include "consumer.h" |
62499ad6 | 35 | #include "trace-kernel.h" |
e9404c27 JG |
36 | #include "lttng-sessiond.h" |
37 | #include "notification-thread-commands.h" | |
54012638 | 38 | |
19e70852 | 39 | /* |
050349bb | 40 | * Find the channel name for the given kernel session. |
19e70852 | 41 | */ |
62499ad6 | 42 | struct ltt_kernel_channel *trace_kernel_get_channel_by_name( |
df4f5a87 | 43 | const char *name, struct ltt_kernel_session *session) |
19e70852 DG |
44 | { |
45 | struct ltt_kernel_channel *chan; | |
46 | ||
a0377dfe FD |
47 | LTTNG_ASSERT(session); |
48 | LTTNG_ASSERT(name); | |
19e70852 | 49 | |
85076754 MD |
50 | /* |
51 | * If we receive an empty string for channel name, it means the | |
52 | * default channel name is requested. | |
53 | */ | |
54 | if (name[0] == '\0') | |
55 | name = DEFAULT_CHANNEL_NAME; | |
56 | ||
54d01ffb DG |
57 | DBG("Trying to find channel %s", name); |
58 | ||
19e70852 DG |
59 | cds_list_for_each_entry(chan, &session->channel_list.head, list) { |
60 | if (strcmp(name, chan->channel->name) == 0) { | |
61 | DBG("Found channel by name %s", name); | |
62 | return chan; | |
63 | } | |
64 | } | |
65 | ||
19e70852 DG |
66 | return NULL; |
67 | } | |
68 | ||
00a62084 MD |
69 | /* |
70 | * Find the event for the given channel. | |
71 | */ | |
72 | struct ltt_kernel_event *trace_kernel_find_event( | |
73 | char *name, struct ltt_kernel_channel *channel, | |
74 | enum lttng_event_type type, | |
2b00d462 | 75 | struct lttng_bytecode *filter) |
00a62084 MD |
76 | { |
77 | struct ltt_kernel_event *ev; | |
78 | int found = 0; | |
79 | ||
a0377dfe FD |
80 | LTTNG_ASSERT(name); |
81 | LTTNG_ASSERT(channel); | |
00a62084 MD |
82 | |
83 | cds_list_for_each_entry(ev, &channel->events_list.head, list) { | |
84 | if (type != LTTNG_EVENT_ALL && ev->type != type) { | |
85 | continue; | |
86 | } | |
87 | if (strcmp(name, ev->event->name)) { | |
88 | continue; | |
89 | } | |
90 | if ((ev->filter && !filter) || (!ev->filter && filter)) { | |
91 | continue; | |
92 | } | |
93 | if (ev->filter && filter) { | |
94 | if (ev->filter->len != filter->len || | |
95 | memcmp(ev->filter->data, filter->data, | |
96 | filter->len) != 0) { | |
97 | continue; | |
98 | } | |
99 | } | |
100 | found = 1; | |
101 | break; | |
102 | } | |
103 | if (found) { | |
104 | DBG("Found event %s for channel %s", name, | |
105 | channel->channel->name); | |
106 | return ev; | |
107 | } else { | |
108 | return NULL; | |
109 | } | |
110 | } | |
111 | ||
19e70852 | 112 | /* |
050349bb | 113 | * Find the event name for the given channel. |
19e70852 | 114 | */ |
62499ad6 | 115 | struct ltt_kernel_event *trace_kernel_get_event_by_name( |
d0ae4ea8 MD |
116 | char *name, struct ltt_kernel_channel *channel, |
117 | enum lttng_event_type type) | |
19e70852 DG |
118 | { |
119 | struct ltt_kernel_event *ev; | |
00a62084 | 120 | int found = 0; |
19e70852 | 121 | |
a0377dfe FD |
122 | LTTNG_ASSERT(name); |
123 | LTTNG_ASSERT(channel); | |
19e70852 DG |
124 | |
125 | cds_list_for_each_entry(ev, &channel->events_list.head, list) { | |
00a62084 | 126 | if (type != LTTNG_EVENT_ALL && ev->type != type) { |
d0ae4ea8 | 127 | continue; |
19e70852 | 128 | } |
00a62084 MD |
129 | if (strcmp(name, ev->event->name)) { |
130 | continue; | |
131 | } | |
132 | found = 1; | |
133 | break; | |
134 | } | |
135 | if (found) { | |
136 | DBG("Found event %s for channel %s", name, | |
137 | channel->channel->name); | |
138 | return ev; | |
139 | } else { | |
140 | return NULL; | |
19e70852 | 141 | } |
19e70852 DG |
142 | } |
143 | ||
54012638 | 144 | /* |
050349bb | 145 | * Allocate and initialize a kernel session data structure. |
54012638 | 146 | * |
050349bb | 147 | * Return pointer to structure or NULL. |
54012638 | 148 | */ |
dec56f6c | 149 | struct ltt_kernel_session *trace_kernel_create_session(void) |
54012638 | 150 | { |
a4b92340 | 151 | struct ltt_kernel_session *lks = NULL; |
54012638 DG |
152 | |
153 | /* Allocate a new ltt kernel session */ | |
7966af57 | 154 | lks = (ltt_kernel_session *) zmalloc(sizeof(struct ltt_kernel_session)); |
54012638 | 155 | if (lks == NULL) { |
df0f840b | 156 | PERROR("create kernel session zmalloc"); |
a4b92340 | 157 | goto alloc_error; |
54012638 DG |
158 | } |
159 | ||
160 | /* Init data structure */ | |
03550b58 MD |
161 | lks->fd = -1; |
162 | lks->metadata_stream_fd = -1; | |
54012638 DG |
163 | lks->channel_count = 0; |
164 | lks->stream_count_global = 0; | |
165 | lks->metadata = NULL; | |
166 | CDS_INIT_LIST_HEAD(&lks->channel_list.head); | |
167 | ||
159b042f JG |
168 | lks->tracker_pid = process_attr_tracker_create(); |
169 | if (!lks->tracker_pid) { | |
55c9e7ca JR |
170 | goto error; |
171 | } | |
159b042f JG |
172 | lks->tracker_vpid = process_attr_tracker_create(); |
173 | if (!lks->tracker_vpid) { | |
55c9e7ca JR |
174 | goto error; |
175 | } | |
159b042f JG |
176 | lks->tracker_uid = process_attr_tracker_create(); |
177 | if (!lks->tracker_uid) { | |
55c9e7ca JR |
178 | goto error; |
179 | } | |
159b042f JG |
180 | lks->tracker_vuid = process_attr_tracker_create(); |
181 | if (!lks->tracker_vuid) { | |
55c9e7ca JR |
182 | goto error; |
183 | } | |
159b042f JG |
184 | lks->tracker_gid = process_attr_tracker_create(); |
185 | if (!lks->tracker_gid) { | |
55c9e7ca JR |
186 | goto error; |
187 | } | |
159b042f JG |
188 | lks->tracker_vgid = process_attr_tracker_create(); |
189 | if (!lks->tracker_vgid) { | |
55c9e7ca JR |
190 | goto error; |
191 | } | |
00e2e675 DG |
192 | lks->consumer = consumer_create_output(CONSUMER_DST_LOCAL); |
193 | if (lks->consumer == NULL) { | |
194 | goto error; | |
195 | } | |
196 | ||
54012638 DG |
197 | return lks; |
198 | ||
199 | error: | |
159b042f JG |
200 | process_attr_tracker_destroy(lks->tracker_pid); |
201 | process_attr_tracker_destroy(lks->tracker_vpid); | |
202 | process_attr_tracker_destroy(lks->tracker_uid); | |
203 | process_attr_tracker_destroy(lks->tracker_vuid); | |
204 | process_attr_tracker_destroy(lks->tracker_gid); | |
205 | process_attr_tracker_destroy(lks->tracker_vgid); | |
a4b92340 DG |
206 | free(lks); |
207 | ||
208 | alloc_error: | |
54012638 DG |
209 | return NULL; |
210 | } | |
211 | ||
212 | /* | |
050349bb | 213 | * Allocate and initialize a kernel channel data structure. |
54012638 | 214 | * |
050349bb | 215 | * Return pointer to structure or NULL. |
54012638 | 216 | */ |
00e2e675 | 217 | struct ltt_kernel_channel *trace_kernel_create_channel( |
fdd9eb17 | 218 | struct lttng_channel *chan) |
54012638 | 219 | { |
54012638 | 220 | struct ltt_kernel_channel *lkc; |
61a5b6b1 | 221 | struct lttng_channel_extended *extended = NULL; |
54012638 | 222 | |
a0377dfe | 223 | LTTNG_ASSERT(chan); |
0525e9ae | 224 | |
7966af57 | 225 | lkc = (ltt_kernel_channel *) zmalloc(sizeof(struct ltt_kernel_channel)); |
f3ed775e | 226 | if (lkc == NULL) { |
df0f840b | 227 | PERROR("ltt_kernel_channel zmalloc"); |
54012638 DG |
228 | goto error; |
229 | } | |
230 | ||
7966af57 | 231 | lkc->channel = (lttng_channel *) zmalloc(sizeof(struct lttng_channel)); |
f3ed775e | 232 | if (lkc->channel == NULL) { |
df0f840b | 233 | PERROR("lttng_channel zmalloc"); |
e9404c27 JG |
234 | goto error; |
235 | } | |
236 | ||
7966af57 | 237 | extended = (lttng_channel_extended *) zmalloc(sizeof(struct lttng_channel_extended)); |
e9404c27 JG |
238 | if (!extended) { |
239 | PERROR("lttng_channel_channel zmalloc"); | |
f3ed775e DG |
240 | goto error; |
241 | } | |
242 | memcpy(lkc->channel, chan, sizeof(struct lttng_channel)); | |
e9404c27 JG |
243 | memcpy(extended, chan->attr.extended.ptr, sizeof(struct lttng_channel_extended)); |
244 | lkc->channel->attr.extended.ptr = extended; | |
245 | extended = NULL; | |
54012638 | 246 | |
85076754 MD |
247 | /* |
248 | * If we receive an empty string for channel name, it means the | |
249 | * default channel name is requested. | |
250 | */ | |
251 | if (chan->name[0] == '\0') { | |
252 | strncpy(lkc->channel->name, DEFAULT_CHANNEL_NAME, | |
253 | sizeof(lkc->channel->name)); | |
254 | } | |
b8e2fb80 | 255 | lkc->channel->name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0'; |
85076754 | 256 | |
03550b58 | 257 | lkc->fd = -1; |
54012638 | 258 | lkc->stream_count = 0; |
cbbbb275 | 259 | lkc->event_count = 0; |
d36b8583 | 260 | lkc->enabled = 1; |
753873bf | 261 | lkc->published_to_notification_thread = false; |
54012638 DG |
262 | /* Init linked list */ |
263 | CDS_INIT_LIST_HEAD(&lkc->events_list.head); | |
264 | CDS_INIT_LIST_HEAD(&lkc->stream_list.head); | |
645328ae | 265 | CDS_INIT_LIST_HEAD(&lkc->ctx_list); |
54012638 DG |
266 | |
267 | return lkc; | |
268 | ||
269 | error: | |
e9404c27 JG |
270 | if (lkc) { |
271 | free(lkc->channel); | |
272 | } | |
273 | free(extended); | |
274 | free(lkc); | |
54012638 DG |
275 | return NULL; |
276 | } | |
277 | ||
645328ae DG |
278 | /* |
279 | * Allocate and init a kernel context object. | |
280 | * | |
281 | * Return the allocated object or NULL on error. | |
282 | */ | |
283 | struct ltt_kernel_context *trace_kernel_create_context( | |
b8e2fb80 | 284 | struct lttng_kernel_abi_context *ctx) |
645328ae DG |
285 | { |
286 | struct ltt_kernel_context *kctx; | |
287 | ||
7966af57 | 288 | kctx = (ltt_kernel_context *) zmalloc(sizeof(*kctx)); |
645328ae DG |
289 | if (!kctx) { |
290 | PERROR("zmalloc kernel context"); | |
291 | goto error; | |
292 | } | |
293 | ||
294 | if (ctx) { | |
295 | memcpy(&kctx->ctx, ctx, sizeof(kctx->ctx)); | |
296 | } | |
df3c77c8 JG |
297 | error: |
298 | return kctx; | |
299 | } | |
645328ae | 300 | |
df3c77c8 JG |
301 | /* |
302 | * Allocate and init a kernel context object from an existing kernel context | |
303 | * object. | |
304 | * | |
305 | * Return the allocated object or NULL on error. | |
306 | */ | |
307 | struct ltt_kernel_context *trace_kernel_copy_context( | |
308 | struct ltt_kernel_context *kctx) | |
309 | { | |
310 | struct ltt_kernel_context *kctx_copy; | |
311 | ||
a0377dfe | 312 | LTTNG_ASSERT(kctx); |
7966af57 | 313 | kctx_copy = (ltt_kernel_context *) zmalloc(sizeof(*kctx_copy)); |
df3c77c8 JG |
314 | if (!kctx_copy) { |
315 | PERROR("zmalloc ltt_kernel_context"); | |
316 | goto error; | |
317 | } | |
318 | ||
319 | memcpy(kctx_copy, kctx, sizeof(*kctx_copy)); | |
320 | memset(&kctx_copy->list, 0, sizeof(kctx_copy->list)); | |
7b9445b3 | 321 | |
645328ae | 322 | error: |
df3c77c8 | 323 | return kctx_copy; |
645328ae DG |
324 | } |
325 | ||
54012638 | 326 | /* |
050349bb | 327 | * Allocate and initialize a kernel event. Set name and event type. |
a969e101 | 328 | * We own filter_expression, and filter. |
54012638 | 329 | * |
050349bb | 330 | * Return pointer to structure or NULL. |
54012638 | 331 | */ |
71a3bb01 FD |
332 | enum lttng_error_code trace_kernel_create_event( |
333 | struct lttng_event *ev, char *filter_expression, | |
2b00d462 | 334 | struct lttng_bytecode *filter, |
71a3bb01 | 335 | struct ltt_kernel_event **kernel_event) |
54012638 | 336 | { |
71a3bb01 | 337 | enum lttng_error_code ret; |
b8e2fb80 | 338 | struct lttng_kernel_abi_event *attr; |
71a3bb01 | 339 | struct ltt_kernel_event *local_kernel_event; |
dcabc190 | 340 | struct lttng_userspace_probe_location *userspace_probe_location = NULL; |
54012638 | 341 | |
a0377dfe | 342 | LTTNG_ASSERT(ev); |
0525e9ae | 343 | |
7966af57 SM |
344 | local_kernel_event = (ltt_kernel_event *) zmalloc(sizeof(struct ltt_kernel_event)); |
345 | attr = (lttng_kernel_abi_event *) zmalloc(sizeof(struct lttng_kernel_abi_event)); | |
71a3bb01 | 346 | if (local_kernel_event == NULL || attr == NULL) { |
df0f840b | 347 | PERROR("kernel event zmalloc"); |
71a3bb01 | 348 | ret = LTTNG_ERR_NOMEM; |
54012638 DG |
349 | goto error; |
350 | } | |
351 | ||
f3ed775e | 352 | switch (ev->type) { |
7d29a247 | 353 | case LTTNG_EVENT_PROBE: |
b8e2fb80 | 354 | attr->instrumentation = LTTNG_KERNEL_ABI_KPROBE; |
7d29a247 DG |
355 | attr->u.kprobe.addr = ev->attr.probe.addr; |
356 | attr->u.kprobe.offset = ev->attr.probe.offset; | |
f3ed775e | 357 | strncpy(attr->u.kprobe.symbol_name, |
b8e2fb80 FD |
358 | ev->attr.probe.symbol_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN); |
359 | attr->u.kprobe.symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0'; | |
f3ed775e | 360 | break; |
dcabc190 FD |
361 | case LTTNG_EVENT_USERSPACE_PROBE: |
362 | { | |
87597c2c JG |
363 | const struct lttng_userspace_probe_location* location = NULL; |
364 | const struct lttng_userspace_probe_location_lookup_method *lookup = NULL; | |
dcabc190 FD |
365 | |
366 | location = lttng_event_get_userspace_probe_location(ev); | |
367 | if (!location) { | |
368 | ret = LTTNG_ERR_PROBE_LOCATION_INVAL; | |
369 | goto error; | |
370 | } | |
371 | ||
372 | /* | |
373 | * From this point on, the specific term 'uprobe' is used | |
374 | * instead of the generic 'userspace probe' because it's the | |
375 | * technology used at the moment for this instrumentation. | |
376 | * LTTng currently implements userspace probes using uprobes. | |
377 | * In the interactions with the kernel tracer, we use the | |
378 | * uprobe term. | |
379 | */ | |
b8e2fb80 | 380 | attr->instrumentation = LTTNG_KERNEL_ABI_UPROBE; |
dcabc190 | 381 | |
dcabc190 FD |
382 | lookup = lttng_userspace_probe_location_get_lookup_method( |
383 | location); | |
384 | if (!lookup) { | |
385 | ret = LTTNG_ERR_PROBE_LOCATION_INVAL; | |
386 | goto error; | |
387 | } | |
388 | ||
389 | /* | |
390 | * From the kernel tracer's perspective, all userspace probe | |
391 | * event types are all the same: a file and an offset. | |
392 | */ | |
393 | switch (lttng_userspace_probe_location_lookup_method_get_type(lookup)) { | |
394 | case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF: | |
395 | /* Get the file descriptor on the target binary. */ | |
396 | attr->u.uprobe.fd = | |
397 | lttng_userspace_probe_location_function_get_binary_fd(location); | |
398 | ||
399 | /* | |
400 | * Save a reference to the probe location used during | |
e368fb43 | 401 | * the listing of events. |
dcabc190 FD |
402 | */ |
403 | userspace_probe_location = | |
404 | lttng_userspace_probe_location_copy(location); | |
dcabc190 FD |
405 | break; |
406 | case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT: | |
407 | /* Get the file descriptor on the target binary. */ | |
408 | attr->u.uprobe.fd = | |
409 | lttng_userspace_probe_location_tracepoint_get_binary_fd(location); | |
410 | ||
411 | /* | |
412 | * Save a reference to the probe location used during the listing of | |
e368fb43 | 413 | * events. |
dcabc190 FD |
414 | */ |
415 | userspace_probe_location = | |
416 | lttng_userspace_probe_location_copy(location); | |
dcabc190 FD |
417 | break; |
418 | default: | |
419 | DBG("Unsupported lookup method type"); | |
420 | ret = LTTNG_ERR_PROBE_LOCATION_INVAL; | |
421 | goto error; | |
422 | } | |
423 | break; | |
424 | } | |
f3ed775e | 425 | case LTTNG_EVENT_FUNCTION: |
b8e2fb80 | 426 | attr->instrumentation = LTTNG_KERNEL_ABI_KRETPROBE; |
8f0d098b MD |
427 | attr->u.kretprobe.addr = ev->attr.probe.addr; |
428 | attr->u.kretprobe.offset = ev->attr.probe.offset; | |
8f0d098b | 429 | strncpy(attr->u.kretprobe.symbol_name, |
b8e2fb80 FD |
430 | ev->attr.probe.symbol_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN); |
431 | attr->u.kretprobe.symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0'; | |
8f0d098b MD |
432 | break; |
433 | case LTTNG_EVENT_FUNCTION_ENTRY: | |
b8e2fb80 | 434 | attr->instrumentation = LTTNG_KERNEL_ABI_FUNCTION; |
f3ed775e | 435 | strncpy(attr->u.ftrace.symbol_name, |
b8e2fb80 FD |
436 | ev->attr.ftrace.symbol_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN); |
437 | attr->u.ftrace.symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0'; | |
f3ed775e | 438 | break; |
e6ddca71 | 439 | case LTTNG_EVENT_TRACEPOINT: |
b8e2fb80 | 440 | attr->instrumentation = LTTNG_KERNEL_ABI_TRACEPOINT; |
f3ed775e | 441 | break; |
a54bd42d | 442 | case LTTNG_EVENT_SYSCALL: |
b8e2fb80 FD |
443 | attr->instrumentation = LTTNG_KERNEL_ABI_SYSCALL; |
444 | attr->u.syscall.abi = LTTNG_KERNEL_ABI_SYSCALL_ABI_ALL; | |
445 | attr->u.syscall.entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT; | |
446 | attr->u.syscall.match = LTTNG_KERNEL_ABI_SYSCALL_MATCH_NAME; | |
0133c199 | 447 | break; |
7a3d1328 | 448 | case LTTNG_EVENT_ALL: |
b8e2fb80 | 449 | attr->instrumentation = LTTNG_KERNEL_ABI_ALL; |
7a3d1328 | 450 | break; |
f3ed775e DG |
451 | default: |
452 | ERR("Unknown kernel instrumentation type (%d)", ev->type); | |
71a3bb01 | 453 | ret = LTTNG_ERR_INVALID; |
f3ed775e DG |
454 | goto error; |
455 | } | |
456 | ||
457 | /* Copy event name */ | |
b8e2fb80 FD |
458 | strncpy(attr->name, ev->name, LTTNG_KERNEL_ABI_SYM_NAME_LEN); |
459 | attr->name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0'; | |
f3ed775e | 460 | |
54012638 | 461 | /* Setting up a kernel event */ |
71a3bb01 FD |
462 | local_kernel_event->fd = -1; |
463 | local_kernel_event->event = attr; | |
464 | local_kernel_event->enabled = 1; | |
465 | local_kernel_event->filter_expression = filter_expression; | |
466 | local_kernel_event->filter = filter; | |
dcabc190 | 467 | local_kernel_event->userspace_probe_location = userspace_probe_location; |
54012638 | 468 | |
71a3bb01 FD |
469 | *kernel_event = local_kernel_event; |
470 | ||
471 | return LTTNG_OK; | |
54012638 DG |
472 | |
473 | error: | |
a969e101 MD |
474 | free(filter_expression); |
475 | free(filter); | |
71a3bb01 | 476 | free(local_kernel_event); |
a2c0da86 | 477 | free(attr); |
71a3bb01 | 478 | return ret; |
54012638 DG |
479 | } |
480 | ||
352b58f5 JR |
481 | /* |
482 | * Allocate and initialize a kernel token event rule. | |
483 | * | |
484 | * Return pointer to structure or NULL. | |
485 | */ | |
486 | enum lttng_error_code trace_kernel_create_event_notifier_rule( | |
487 | struct lttng_trigger *trigger, | |
488 | uint64_t token, | |
90aa04a1 | 489 | uint64_t error_counter_index, |
352b58f5 JR |
490 | struct ltt_kernel_event_notifier_rule **event_notifier_rule) |
491 | { | |
492 | enum lttng_error_code ret = LTTNG_OK; | |
493 | enum lttng_condition_type condition_type; | |
494 | enum lttng_event_rule_type event_rule_type; | |
495 | enum lttng_condition_status condition_status; | |
496 | struct ltt_kernel_event_notifier_rule *local_kernel_token_event_rule; | |
497 | const struct lttng_condition *condition = NULL; | |
498 | const struct lttng_event_rule *event_rule = NULL; | |
499 | ||
a0377dfe | 500 | LTTNG_ASSERT(event_notifier_rule); |
352b58f5 | 501 | |
7c1f6da2 | 502 | condition = lttng_trigger_get_const_condition(trigger); |
a0377dfe | 503 | LTTNG_ASSERT(condition); |
352b58f5 JR |
504 | |
505 | condition_type = lttng_condition_get_type(condition); | |
a0377dfe | 506 | LTTNG_ASSERT(condition_type == LTTNG_CONDITION_TYPE_EVENT_RULE_MATCHES); |
352b58f5 | 507 | |
8dbb86b8 | 508 | condition_status = lttng_condition_event_rule_matches_get_rule( |
352b58f5 | 509 | condition, &event_rule); |
a0377dfe FD |
510 | LTTNG_ASSERT(condition_status == LTTNG_CONDITION_STATUS_OK); |
511 | LTTNG_ASSERT(event_rule); | |
352b58f5 JR |
512 | |
513 | event_rule_type = lttng_event_rule_get_type(event_rule); | |
a0377dfe | 514 | LTTNG_ASSERT(event_rule_type != LTTNG_EVENT_RULE_TYPE_UNKNOWN); |
352b58f5 JR |
515 | |
516 | local_kernel_token_event_rule = | |
7966af57 | 517 | (ltt_kernel_event_notifier_rule *) zmalloc(sizeof(struct ltt_kernel_event_notifier_rule)); |
352b58f5 JR |
518 | if (local_kernel_token_event_rule == NULL) { |
519 | PERROR("Failed to allocate ltt_kernel_token_event_rule structure"); | |
520 | ret = LTTNG_ERR_NOMEM; | |
521 | goto error; | |
522 | } | |
523 | ||
524 | local_kernel_token_event_rule->fd = -1; | |
525 | local_kernel_token_event_rule->enabled = 1; | |
526 | local_kernel_token_event_rule->token = token; | |
90aa04a1 | 527 | local_kernel_token_event_rule->error_counter_index = error_counter_index; |
352b58f5 JR |
528 | |
529 | /* Get the reference of the event rule. */ | |
530 | lttng_trigger_get(trigger); | |
531 | ||
532 | local_kernel_token_event_rule->trigger = trigger; | |
533 | /* The event rule still owns the filter and bytecode. */ | |
534 | local_kernel_token_event_rule->filter = | |
535 | lttng_event_rule_get_filter_bytecode(event_rule); | |
536 | ||
537 | DBG3("Created kernel event notifier rule: token = %" PRIu64, | |
538 | local_kernel_token_event_rule->token); | |
539 | error: | |
540 | *event_notifier_rule = local_kernel_token_event_rule; | |
541 | return ret; | |
542 | } | |
543 | ||
544 | /* | |
545 | * Initialize a kernel trigger from an event rule. | |
546 | */ | |
547 | enum lttng_error_code trace_kernel_init_event_notifier_from_event_rule( | |
548 | const struct lttng_event_rule *rule, | |
b8e2fb80 | 549 | struct lttng_kernel_abi_event_notifier *kernel_event_notifier) |
352b58f5 | 550 | { |
366a83b3 | 551 | enum lttng_error_code ret_code; |
352b58f5 | 552 | const char *name; |
366a83b3 | 553 | int strncpy_ret; |
352b58f5 JR |
554 | |
555 | switch (lttng_event_rule_get_type(rule)) { | |
85522de5 | 556 | case LTTNG_EVENT_RULE_TYPE_KERNEL_KPROBE: |
352b58f5 JR |
557 | { |
558 | uint64_t address = 0, offset = 0; | |
559 | const char *symbol_name = NULL; | |
560 | const struct lttng_kernel_probe_location *location = NULL; | |
561 | enum lttng_kernel_probe_location_status k_status; | |
562 | enum lttng_event_rule_status status; | |
563 | ||
85522de5 | 564 | status = lttng_event_rule_kernel_kprobe_get_location(rule, &location); |
352b58f5 | 565 | if (status != LTTNG_EVENT_RULE_STATUS_OK) { |
366a83b3 | 566 | ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL; |
352b58f5 JR |
567 | goto error; |
568 | } | |
569 | ||
570 | switch (lttng_kernel_probe_location_get_type(location)) { | |
571 | case LTTNG_KERNEL_PROBE_LOCATION_TYPE_ADDRESS: | |
572 | { | |
573 | k_status = lttng_kernel_probe_location_address_get_address( | |
574 | location, &address); | |
a0377dfe | 575 | LTTNG_ASSERT(k_status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK); |
352b58f5 JR |
576 | break; |
577 | } | |
578 | case LTTNG_KERNEL_PROBE_LOCATION_TYPE_SYMBOL_OFFSET: | |
579 | { | |
580 | k_status = lttng_kernel_probe_location_symbol_get_offset( | |
581 | location, &offset); | |
a0377dfe | 582 | LTTNG_ASSERT(k_status == LTTNG_KERNEL_PROBE_LOCATION_STATUS_OK); |
352b58f5 JR |
583 | symbol_name = lttng_kernel_probe_location_symbol_get_name( |
584 | location); | |
585 | break; | |
586 | } | |
587 | default: | |
588 | abort(); | |
589 | } | |
590 | ||
b8e2fb80 | 591 | kernel_event_notifier->event.instrumentation = LTTNG_KERNEL_ABI_KPROBE; |
352b58f5 JR |
592 | kernel_event_notifier->event.u.kprobe.addr = address; |
593 | kernel_event_notifier->event.u.kprobe.offset = offset; | |
594 | if (symbol_name) { | |
366a83b3 | 595 | strncpy_ret = lttng_strncpy( |
352b58f5 | 596 | kernel_event_notifier->event.u.kprobe.symbol_name, |
b8e2fb80 | 597 | symbol_name, LTTNG_KERNEL_ABI_SYM_NAME_LEN); |
352b58f5 | 598 | |
366a83b3 JG |
599 | if (strncpy_ret) { |
600 | ret_code = LTTNG_ERR_INVALID; | |
352b58f5 JR |
601 | goto error; |
602 | } | |
603 | } | |
604 | ||
b8e2fb80 | 605 | kernel_event_notifier->event.u.kprobe.symbol_name[LTTNG_KERNEL_ABI_SYM_NAME_LEN - 1] = '\0'; |
f2791161 | 606 | |
85522de5 | 607 | status = lttng_event_rule_kernel_kprobe_get_event_name(rule, &name); |
a0377dfe | 608 | LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK); |
366a83b3 | 609 | ret_code = LTTNG_OK; |
352b58f5 JR |
610 | break; |
611 | } | |
46fd07ac | 612 | case LTTNG_EVENT_RULE_TYPE_KERNEL_UPROBE: |
352b58f5 JR |
613 | { |
614 | const struct lttng_userspace_probe_location* location = NULL; | |
615 | const struct lttng_userspace_probe_location_lookup_method *lookup = NULL; | |
616 | enum lttng_event_rule_status status; | |
617 | ||
46fd07ac | 618 | status = lttng_event_rule_kernel_uprobe_get_location(rule, &location); |
352b58f5 | 619 | if (status != LTTNG_EVENT_RULE_STATUS_OK) { |
366a83b3 | 620 | ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL; |
352b58f5 JR |
621 | goto error; |
622 | } | |
623 | ||
b8e2fb80 | 624 | kernel_event_notifier->event.instrumentation = LTTNG_KERNEL_ABI_UPROBE; |
352b58f5 JR |
625 | |
626 | lookup = lttng_userspace_probe_location_get_lookup_method( | |
627 | location); | |
628 | if (!lookup) { | |
366a83b3 | 629 | ret_code = LTTNG_ERR_PROBE_LOCATION_INVAL; |
352b58f5 JR |
630 | goto error; |
631 | } | |
632 | ||
633 | /* | |
634 | * From the kernel tracer's perspective, all userspace probe | |
635 | * event types are all the same: a file and an offset. | |
636 | */ | |
637 | switch (lttng_userspace_probe_location_lookup_method_get_type(lookup)) { | |
638 | case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_FUNCTION_ELF: | |
639 | /* Get the file descriptor on the target binary. */ | |
640 | kernel_event_notifier->event.u.uprobe.fd = | |
641 | lttng_userspace_probe_location_function_get_binary_fd(location); | |
642 | ||
643 | break; | |
644 | case LTTNG_USERSPACE_PROBE_LOCATION_LOOKUP_METHOD_TYPE_TRACEPOINT_SDT: | |
645 | /* Get the file descriptor on the target binary. */ | |
646 | kernel_event_notifier->event.u.uprobe.fd = | |
647 | lttng_userspace_probe_location_tracepoint_get_binary_fd(location); | |
648 | break; | |
649 | default: | |
650 | abort(); | |
651 | } | |
652 | ||
46fd07ac | 653 | status = lttng_event_rule_kernel_uprobe_get_event_name( |
405f9e7d | 654 | rule, &name); |
a0377dfe | 655 | LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK); |
366a83b3 | 656 | ret_code = LTTNG_OK; |
352b58f5 JR |
657 | break; |
658 | } | |
695f7044 | 659 | case LTTNG_EVENT_RULE_TYPE_KERNEL_TRACEPOINT: |
352b58f5 | 660 | { |
352b58f5 | 661 | const enum lttng_event_rule_status status = |
695f7044 | 662 | lttng_event_rule_kernel_tracepoint_get_name_pattern( |
352b58f5 JR |
663 | rule, &name); |
664 | ||
a0377dfe | 665 | LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK); |
352b58f5 | 666 | kernel_event_notifier->event.instrumentation = |
b8e2fb80 | 667 | LTTNG_KERNEL_ABI_TRACEPOINT; |
352b58f5 | 668 | |
366a83b3 | 669 | ret_code = LTTNG_OK; |
352b58f5 JR |
670 | break; |
671 | } | |
4f7da553 | 672 | case LTTNG_EVENT_RULE_TYPE_KERNEL_SYSCALL: |
352b58f5 JR |
673 | { |
674 | const enum lttng_event_rule_status status = | |
4f7da553 | 675 | lttng_event_rule_kernel_syscall_get_name_pattern( |
352b58f5 | 676 | rule, &name); |
4f7da553 | 677 | const enum lttng_event_rule_kernel_syscall_emission_site |
f6a5af19 | 678 | emission_site = |
4f7da553 | 679 | lttng_event_rule_kernel_syscall_get_emission_site(rule); |
b8e2fb80 | 680 | enum lttng_kernel_abi_syscall_entryexit entryexit; |
352b58f5 | 681 | |
a0377dfe FD |
682 | LTTNG_ASSERT(status == LTTNG_EVENT_RULE_STATUS_OK); |
683 | LTTNG_ASSERT(emission_site != LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_UNKNOWN); | |
57739a6b | 684 | |
f6a5af19 | 685 | switch(emission_site) { |
4f7da553 | 686 | case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY: |
b8e2fb80 | 687 | entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRY; |
57739a6b | 688 | break; |
4f7da553 | 689 | case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_EXIT: |
b8e2fb80 | 690 | entryexit = LTTNG_KERNEL_ABI_SYSCALL_EXIT; |
57739a6b | 691 | break; |
4f7da553 | 692 | case LTTNG_EVENT_RULE_KERNEL_SYSCALL_EMISSION_SITE_ENTRY_EXIT: |
b8e2fb80 | 693 | entryexit = LTTNG_KERNEL_ABI_SYSCALL_ENTRYEXIT; |
57739a6b JR |
694 | break; |
695 | default: | |
696 | abort(); | |
697 | break; | |
698 | } | |
352b58f5 JR |
699 | |
700 | kernel_event_notifier->event.instrumentation = | |
b8e2fb80 | 701 | LTTNG_KERNEL_ABI_SYSCALL; |
352b58f5 | 702 | kernel_event_notifier->event.u.syscall.abi = |
b8e2fb80 | 703 | LTTNG_KERNEL_ABI_SYSCALL_ABI_ALL; |
352b58f5 | 704 | kernel_event_notifier->event.u.syscall.entryexit = |
57739a6b | 705 | entryexit; |
352b58f5 | 706 | kernel_event_notifier->event.u.syscall.match = |
b8e2fb80 | 707 | LTTNG_KERNEL_ABI_SYSCALL_MATCH_NAME; |
366a83b3 | 708 | ret_code = LTTNG_OK; |
352b58f5 JR |
709 | break; |
710 | } | |
352b58f5 JR |
711 | default: |
712 | abort(); | |
713 | break; | |
714 | } | |
715 | ||
366a83b3 | 716 | strncpy_ret = lttng_strncpy(kernel_event_notifier->event.name, name, |
b8e2fb80 | 717 | LTTNG_KERNEL_ABI_SYM_NAME_LEN); |
366a83b3 JG |
718 | if (strncpy_ret) { |
719 | ret_code = LTTNG_ERR_INVALID; | |
352b58f5 JR |
720 | goto error; |
721 | } | |
722 | ||
723 | error: | |
366a83b3 | 724 | return ret_code; |
352b58f5 | 725 | } |
54012638 | 726 | /* |
050349bb | 727 | * Allocate and initialize a kernel metadata. |
54012638 | 728 | * |
050349bb | 729 | * Return pointer to structure or NULL. |
54012638 | 730 | */ |
a4b92340 | 731 | struct ltt_kernel_metadata *trace_kernel_create_metadata(void) |
54012638 | 732 | { |
d42266a4 | 733 | int ret; |
54012638 | 734 | struct ltt_kernel_metadata *lkm; |
f3ed775e | 735 | struct lttng_channel *chan; |
54012638 | 736 | |
7966af57 SM |
737 | lkm = (ltt_kernel_metadata *) zmalloc(sizeof(struct ltt_kernel_metadata)); |
738 | chan = (lttng_channel *) zmalloc(sizeof(struct lttng_channel)); | |
f3ed775e | 739 | if (lkm == NULL || chan == NULL) { |
df0f840b | 740 | PERROR("kernel metadata zmalloc"); |
54012638 DG |
741 | goto error; |
742 | } | |
743 | ||
d42266a4 JG |
744 | ret = lttng_strncpy( |
745 | chan->name, DEFAULT_METADATA_NAME, sizeof(chan->name)); | |
746 | if (ret) { | |
747 | ERR("Failed to initialize metadata channel name to `%s`", | |
748 | DEFAULT_METADATA_NAME); | |
749 | goto error; | |
750 | } | |
751 | ||
54012638 | 752 | /* Set default attributes */ |
d42266a4 | 753 | chan->attr.overwrite = DEFAULT_METADATA_OVERWRITE; |
3e230f92 | 754 | chan->attr.subbuf_size = default_get_metadata_subbuf_size(); |
b389abbe | 755 | chan->attr.num_subbuf = DEFAULT_METADATA_SUBBUF_NUM; |
d42266a4 JG |
756 | chan->attr.switch_timer_interval = DEFAULT_METADATA_SWITCH_TIMER; |
757 | chan->attr.read_timer_interval = DEFAULT_METADATA_READ_TIMER;; | |
758 | ||
759 | ||
760 | /* | |
761 | * The metadata channel of kernel sessions must use the "mmap" | |
762 | * back-end since the consumer daemon accumulates complete | |
763 | * metadata units before sending them to the relay daemon in | |
764 | * live mode. The consumer daemon also needs to extract the contents | |
765 | * of the metadata cache when computing a rotation position. | |
766 | * | |
767 | * In both cases, it is not possible to rely on the splice | |
768 | * back-end as the consumer daemon may need to accumulate more | |
769 | * content than can be backed by the ring buffer's underlying | |
770 | * pages. | |
771 | */ | |
772 | chan->attr.output = LTTNG_EVENT_MMAP; | |
773 | chan->attr.tracefile_size = 0; | |
774 | chan->attr.tracefile_count = 0; | |
775 | chan->attr.live_timer_interval = 0; | |
54012638 DG |
776 | |
777 | /* Init metadata */ | |
03550b58 | 778 | lkm->fd = -1; |
f3ed775e | 779 | lkm->conf = chan; |
54012638 DG |
780 | |
781 | return lkm; | |
782 | ||
783 | error: | |
a2c0da86 MD |
784 | free(lkm); |
785 | free(chan); | |
54012638 DG |
786 | return NULL; |
787 | } | |
788 | ||
789 | /* | |
050349bb DG |
790 | * Allocate and initialize a kernel stream. The stream is set to ACTIVE_FD by |
791 | * default. | |
54012638 | 792 | * |
050349bb | 793 | * Return pointer to structure or NULL. |
54012638 | 794 | */ |
00e2e675 DG |
795 | struct ltt_kernel_stream *trace_kernel_create_stream(const char *name, |
796 | unsigned int count) | |
54012638 | 797 | { |
00e2e675 | 798 | int ret; |
54012638 DG |
799 | struct ltt_kernel_stream *lks; |
800 | ||
a0377dfe | 801 | LTTNG_ASSERT(name); |
0525e9ae | 802 | |
7966af57 | 803 | lks = (ltt_kernel_stream *) zmalloc(sizeof(struct ltt_kernel_stream)); |
54012638 | 804 | if (lks == NULL) { |
df0f840b | 805 | PERROR("kernel stream zmalloc"); |
54012638 DG |
806 | goto error; |
807 | } | |
808 | ||
00e2e675 | 809 | /* Set name */ |
535b8ff4 | 810 | ret = snprintf(lks->name, sizeof(lks->name), "%s_%u", name, count); |
00e2e675 DG |
811 | if (ret < 0) { |
812 | PERROR("snprintf stream name"); | |
813 | goto error; | |
814 | } | |
815 | lks->name[sizeof(lks->name) - 1] = '\0'; | |
816 | ||
54012638 | 817 | /* Init stream */ |
03550b58 | 818 | lks->fd = -1; |
54012638 | 819 | lks->state = 0; |
ffe60014 | 820 | lks->cpu = count; |
54012638 DG |
821 | |
822 | return lks; | |
823 | ||
824 | error: | |
825 | return NULL; | |
826 | } | |
c363b55d | 827 | |
050349bb DG |
828 | /* |
829 | * Cleanup kernel stream structure. | |
830 | */ | |
62499ad6 | 831 | void trace_kernel_destroy_stream(struct ltt_kernel_stream *stream) |
c363b55d | 832 | { |
a0377dfe | 833 | LTTNG_ASSERT(stream); |
0525e9ae | 834 | |
33a2b854 | 835 | DBG("[trace] Closing stream fd %d", stream->fd); |
c363b55d | 836 | /* Close kernel fd */ |
03550b58 | 837 | if (stream->fd >= 0) { |
c617c0c6 MD |
838 | int ret; |
839 | ||
03550b58 MD |
840 | ret = close(stream->fd); |
841 | if (ret) { | |
842 | PERROR("close"); | |
843 | } | |
799e2c4f | 844 | } |
c363b55d DG |
845 | /* Remove from stream list */ |
846 | cds_list_del(&stream->list); | |
f9815039 | 847 | |
c363b55d DG |
848 | free(stream); |
849 | } | |
850 | ||
050349bb DG |
851 | /* |
852 | * Cleanup kernel event structure. | |
853 | */ | |
62499ad6 | 854 | void trace_kernel_destroy_event(struct ltt_kernel_event *event) |
c363b55d | 855 | { |
a0377dfe | 856 | LTTNG_ASSERT(event); |
0525e9ae | 857 | |
87eb4ab8 | 858 | if (event->fd >= 0) { |
c617c0c6 MD |
859 | int ret; |
860 | ||
87eb4ab8 MD |
861 | DBG("[trace] Closing event fd %d", event->fd); |
862 | /* Close kernel fd */ | |
799e2c4f MD |
863 | ret = close(event->fd); |
864 | if (ret) { | |
865 | PERROR("close"); | |
866 | } | |
87eb4ab8 | 867 | } else { |
352b58f5 | 868 | DBG("[trace] Tearing down event (no associated file descriptor)"); |
87eb4ab8 | 869 | } |
c363b55d DG |
870 | |
871 | /* Remove from event list */ | |
872 | cds_list_del(&event->list); | |
f9815039 | 873 | |
00a62084 MD |
874 | free(event->filter_expression); |
875 | free(event->filter); | |
876 | ||
f9815039 | 877 | free(event->event); |
c363b55d DG |
878 | free(event); |
879 | } | |
880 | ||
352b58f5 JR |
881 | /* |
882 | * Cleanup kernel event structure. | |
883 | */ | |
884 | static void free_token_event_rule_rcu(struct rcu_head *rcu_node) | |
885 | { | |
886 | struct ltt_kernel_event_notifier_rule *rule = caa_container_of(rcu_node, | |
887 | struct ltt_kernel_event_notifier_rule, rcu_node); | |
888 | ||
889 | free(rule); | |
890 | } | |
891 | ||
892 | void trace_kernel_destroy_event_notifier_rule( | |
893 | struct ltt_kernel_event_notifier_rule *event) | |
894 | { | |
a0377dfe | 895 | LTTNG_ASSERT(event); |
352b58f5 JR |
896 | |
897 | if (event->fd >= 0) { | |
898 | const int ret = close(event->fd); | |
899 | ||
900 | DBG("Closing kernel event notifier rule file descriptor: fd = %d", | |
901 | event->fd); | |
902 | if (ret) { | |
903 | PERROR("Failed to close kernel event notifier file descriptor: fd = %d", | |
904 | event->fd); | |
905 | } | |
906 | } else { | |
907 | DBG("Destroying kernel event notifier rule (no associated file descriptor)"); | |
908 | } | |
909 | ||
910 | lttng_trigger_put(event->trigger); | |
911 | call_rcu(&event->rcu_node, free_token_event_rule_rcu); | |
912 | } | |
645328ae DG |
913 | /* |
914 | * Cleanup kernel context structure. | |
915 | */ | |
916 | void trace_kernel_destroy_context(struct ltt_kernel_context *ctx) | |
917 | { | |
a0377dfe | 918 | LTTNG_ASSERT(ctx); |
645328ae | 919 | |
ba985c3a JG |
920 | if (ctx->in_list) { |
921 | cds_list_del(&ctx->list); | |
922 | } | |
645328ae DG |
923 | free(ctx); |
924 | } | |
925 | ||
050349bb DG |
926 | /* |
927 | * Cleanup kernel channel structure. | |
928 | */ | |
62499ad6 | 929 | void trace_kernel_destroy_channel(struct ltt_kernel_channel *channel) |
c363b55d | 930 | { |
af9737e9 DG |
931 | struct ltt_kernel_stream *stream, *stmp; |
932 | struct ltt_kernel_event *event, *etmp; | |
645328ae | 933 | struct ltt_kernel_context *ctx, *ctmp; |
799e2c4f | 934 | int ret; |
e9404c27 | 935 | enum lttng_error_code status; |
c363b55d | 936 | |
a0377dfe | 937 | LTTNG_ASSERT(channel); |
0525e9ae | 938 | |
33a2b854 | 939 | DBG("[trace] Closing channel fd %d", channel->fd); |
c363b55d | 940 | /* Close kernel fd */ |
03550b58 MD |
941 | if (channel->fd >= 0) { |
942 | ret = close(channel->fd); | |
943 | if (ret) { | |
944 | PERROR("close"); | |
945 | } | |
799e2c4f | 946 | } |
c363b55d DG |
947 | |
948 | /* For each stream in the channel list */ | |
af9737e9 | 949 | cds_list_for_each_entry_safe(stream, stmp, &channel->stream_list.head, list) { |
62499ad6 | 950 | trace_kernel_destroy_stream(stream); |
c363b55d DG |
951 | } |
952 | ||
953 | /* For each event in the channel list */ | |
af9737e9 | 954 | cds_list_for_each_entry_safe(event, etmp, &channel->events_list.head, list) { |
62499ad6 | 955 | trace_kernel_destroy_event(event); |
c363b55d DG |
956 | } |
957 | ||
645328ae DG |
958 | /* For each context in the channel list */ |
959 | cds_list_for_each_entry_safe(ctx, ctmp, &channel->ctx_list, list) { | |
960 | trace_kernel_destroy_context(ctx); | |
961 | } | |
962 | ||
c363b55d DG |
963 | /* Remove from channel list */ |
964 | cds_list_del(&channel->list); | |
f9815039 | 965 | |
412d7227 SM |
966 | if (the_notification_thread_handle && |
967 | channel->published_to_notification_thread) { | |
63aaa3dc | 968 | status = notification_thread_command_remove_channel( |
412d7227 SM |
969 | the_notification_thread_handle, channel->key, |
970 | LTTNG_DOMAIN_KERNEL); | |
a0377dfe | 971 | LTTNG_ASSERT(status == LTTNG_OK); |
63aaa3dc | 972 | } |
e9404c27 | 973 | free(channel->channel->attr.extended.ptr); |
f9815039 | 974 | free(channel->channel); |
c363b55d DG |
975 | free(channel); |
976 | } | |
977 | ||
050349bb DG |
978 | /* |
979 | * Cleanup kernel metadata structure. | |
980 | */ | |
62499ad6 | 981 | void trace_kernel_destroy_metadata(struct ltt_kernel_metadata *metadata) |
c363b55d | 982 | { |
a0377dfe | 983 | LTTNG_ASSERT(metadata); |
0525e9ae | 984 | |
33a2b854 | 985 | DBG("[trace] Closing metadata fd %d", metadata->fd); |
c363b55d | 986 | /* Close kernel fd */ |
03550b58 | 987 | if (metadata->fd >= 0) { |
c617c0c6 MD |
988 | int ret; |
989 | ||
03550b58 MD |
990 | ret = close(metadata->fd); |
991 | if (ret) { | |
992 | PERROR("close"); | |
993 | } | |
799e2c4f | 994 | } |
c363b55d | 995 | |
f9815039 | 996 | free(metadata->conf); |
c363b55d DG |
997 | free(metadata); |
998 | } | |
999 | ||
050349bb | 1000 | /* |
62499ad6 | 1001 | * Cleanup kernel session structure |
36b588ed MD |
1002 | * |
1003 | * Should *NOT* be called with RCU read-side lock held. | |
050349bb | 1004 | */ |
62499ad6 | 1005 | void trace_kernel_destroy_session(struct ltt_kernel_session *session) |
c363b55d | 1006 | { |
af9737e9 | 1007 | struct ltt_kernel_channel *channel, *ctmp; |
799e2c4f | 1008 | int ret; |
c363b55d | 1009 | |
a0377dfe | 1010 | LTTNG_ASSERT(session); |
0525e9ae | 1011 | |
33a2b854 | 1012 | DBG("[trace] Closing session fd %d", session->fd); |
c363b55d | 1013 | /* Close kernel fds */ |
03550b58 MD |
1014 | if (session->fd >= 0) { |
1015 | ret = close(session->fd); | |
1016 | if (ret) { | |
1017 | PERROR("close"); | |
1018 | } | |
799e2c4f | 1019 | } |
f9815039 | 1020 | |
03550b58 | 1021 | if (session->metadata_stream_fd >= 0) { |
70dc1c34 | 1022 | DBG("[trace] Closing metadata stream fd %d", session->metadata_stream_fd); |
799e2c4f MD |
1023 | ret = close(session->metadata_stream_fd); |
1024 | if (ret) { | |
1025 | PERROR("close"); | |
1026 | } | |
70dc1c34 | 1027 | } |
c363b55d | 1028 | |
d36b8583 | 1029 | if (session->metadata != NULL) { |
62499ad6 | 1030 | trace_kernel_destroy_metadata(session->metadata); |
d36b8583 | 1031 | } |
c363b55d | 1032 | |
af9737e9 | 1033 | cds_list_for_each_entry_safe(channel, ctmp, &session->channel_list.head, list) { |
62499ad6 | 1034 | trace_kernel_destroy_channel(channel); |
c363b55d | 1035 | } |
d070c424 | 1036 | } |
c363b55d | 1037 | |
d070c424 MD |
1038 | /* Free elements needed by destroy notifiers. */ |
1039 | void trace_kernel_free_session(struct ltt_kernel_session *session) | |
1040 | { | |
00e2e675 | 1041 | /* Wipe consumer output object */ |
6addfa37 | 1042 | consumer_output_put(session->consumer); |
00e2e675 | 1043 | |
159b042f JG |
1044 | process_attr_tracker_destroy(session->tracker_pid); |
1045 | process_attr_tracker_destroy(session->tracker_vpid); | |
1046 | process_attr_tracker_destroy(session->tracker_uid); | |
1047 | process_attr_tracker_destroy(session->tracker_vuid); | |
1048 | process_attr_tracker_destroy(session->tracker_gid); | |
1049 | process_attr_tracker_destroy(session->tracker_vgid); | |
55c9e7ca | 1050 | |
c363b55d DG |
1051 | free(session); |
1052 | } |