Clean-up: sessiond: cmd_enable_channel_internal
[lttng-tools.git] / src / bin / lttng-sessiond / channel.cpp
... / ...
CommitLineData
1/*
2 * Copyright (C) 2011 EfficiOS Inc.
3 * Copyright (C) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
4 *
5 * SPDX-License-Identifier: GPL-2.0-only
6 *
7 */
8
9#define _LGPL_SOURCE
10#include <inttypes.h>
11#include <string.h>
12#include <unistd.h>
13
14#include <common/common.h>
15#include <common/defaults.h>
16#include <common/sessiond-comm/sessiond-comm.h>
17
18#include "channel.h"
19#include "lttng-sessiond.h"
20#include "kernel.h"
21#include "lttng-ust-ctl.h"
22#include "lttng-ust-error.h"
23#include "utils.h"
24#include "ust-app.h"
25#include "agent.h"
26
27/*
28 * Return allocated channel attributes.
29 */
30struct lttng_channel *channel_new_default_attr(int dom,
31 enum lttng_buffer_type type)
32{
33 struct lttng_channel *chan;
34 const char *channel_name = DEFAULT_CHANNEL_NAME;
35 struct lttng_channel_extended *extended_attr = NULL;
36
37 chan = (lttng_channel *) zmalloc(sizeof(struct lttng_channel));
38 if (chan == NULL) {
39 PERROR("zmalloc channel init");
40 goto error_alloc;
41 }
42
43 extended_attr = (lttng_channel_extended *) zmalloc(sizeof(struct lttng_channel_extended));
44 if (!extended_attr) {
45 PERROR("zmalloc channel extended init");
46 goto error;
47 }
48
49 chan->attr.extended.ptr = extended_attr;
50
51 /* Same for all domains. */
52 chan->attr.overwrite = DEFAULT_CHANNEL_OVERWRITE;
53 chan->attr.tracefile_size = DEFAULT_CHANNEL_TRACEFILE_SIZE;
54 chan->attr.tracefile_count = DEFAULT_CHANNEL_TRACEFILE_COUNT;
55
56 switch (dom) {
57 case LTTNG_DOMAIN_KERNEL:
58 LTTNG_ASSERT(type == LTTNG_BUFFER_GLOBAL);
59 chan->attr.subbuf_size =
60 default_get_kernel_channel_subbuf_size();
61 chan->attr.num_subbuf = DEFAULT_KERNEL_CHANNEL_SUBBUF_NUM;
62 chan->attr.output = DEFAULT_KERNEL_CHANNEL_OUTPUT;
63 chan->attr.switch_timer_interval = DEFAULT_KERNEL_CHANNEL_SWITCH_TIMER;
64 chan->attr.read_timer_interval = DEFAULT_KERNEL_CHANNEL_READ_TIMER;
65 chan->attr.live_timer_interval = DEFAULT_KERNEL_CHANNEL_LIVE_TIMER;
66 extended_attr->blocking_timeout = DEFAULT_KERNEL_CHANNEL_BLOCKING_TIMEOUT;
67 extended_attr->monitor_timer_interval =
68 DEFAULT_KERNEL_CHANNEL_MONITOR_TIMER;
69 break;
70 case LTTNG_DOMAIN_JUL:
71 channel_name = DEFAULT_JUL_CHANNEL_NAME;
72 goto common_ust;
73 case LTTNG_DOMAIN_LOG4J:
74 channel_name = DEFAULT_LOG4J_CHANNEL_NAME;
75 goto common_ust;
76 case LTTNG_DOMAIN_PYTHON:
77 channel_name = DEFAULT_PYTHON_CHANNEL_NAME;
78 goto common_ust;
79 case LTTNG_DOMAIN_UST:
80common_ust:
81 switch (type) {
82 case LTTNG_BUFFER_PER_UID:
83 chan->attr.subbuf_size = default_get_ust_uid_channel_subbuf_size();
84 chan->attr.num_subbuf = DEFAULT_UST_UID_CHANNEL_SUBBUF_NUM;
85 chan->attr.output = DEFAULT_UST_UID_CHANNEL_OUTPUT;
86 chan->attr.switch_timer_interval =
87 DEFAULT_UST_UID_CHANNEL_SWITCH_TIMER;
88 chan->attr.read_timer_interval =
89 DEFAULT_UST_UID_CHANNEL_READ_TIMER;
90 chan->attr.live_timer_interval =
91 DEFAULT_UST_UID_CHANNEL_LIVE_TIMER;
92 extended_attr->blocking_timeout = DEFAULT_UST_UID_CHANNEL_BLOCKING_TIMEOUT;
93 extended_attr->monitor_timer_interval =
94 DEFAULT_UST_UID_CHANNEL_MONITOR_TIMER;
95 break;
96 case LTTNG_BUFFER_PER_PID:
97 default:
98 chan->attr.subbuf_size = default_get_ust_pid_channel_subbuf_size();
99 chan->attr.num_subbuf = DEFAULT_UST_PID_CHANNEL_SUBBUF_NUM;
100 chan->attr.output = DEFAULT_UST_PID_CHANNEL_OUTPUT;
101 chan->attr.switch_timer_interval =
102 DEFAULT_UST_PID_CHANNEL_SWITCH_TIMER;
103 chan->attr.read_timer_interval =
104 DEFAULT_UST_PID_CHANNEL_READ_TIMER;
105 chan->attr.live_timer_interval =
106 DEFAULT_UST_PID_CHANNEL_LIVE_TIMER;
107 extended_attr->blocking_timeout = DEFAULT_UST_PID_CHANNEL_BLOCKING_TIMEOUT;
108 extended_attr->monitor_timer_interval =
109 DEFAULT_UST_PID_CHANNEL_MONITOR_TIMER;
110 break;
111 }
112 break;
113 default:
114 goto error; /* Not implemented */
115 }
116
117 if (snprintf(chan->name, sizeof(chan->name), "%s",
118 channel_name) < 0) {
119 PERROR("snprintf default channel name");
120 goto error;
121 }
122 return chan;
123
124error:
125 free(extended_attr);
126 free(chan);
127error_alloc:
128 return NULL;
129}
130
131void channel_attr_destroy(struct lttng_channel *channel)
132{
133 if (!channel) {
134 return;
135 }
136 free(channel->attr.extended.ptr);
137 free(channel);
138}
139
140/*
141 * Disable kernel channel of the kernel session.
142 */
143int channel_kernel_disable(struct ltt_kernel_session *ksession,
144 char *channel_name)
145{
146 int ret;
147 struct ltt_kernel_channel *kchan;
148
149 LTTNG_ASSERT(ksession);
150 LTTNG_ASSERT(channel_name);
151
152 kchan = trace_kernel_get_channel_by_name(channel_name, ksession);
153 if (kchan == NULL) {
154 ret = LTTNG_ERR_KERN_CHAN_NOT_FOUND;
155 goto error;
156 }
157
158 /* Only if channel is enabled disable it. */
159 if (kchan->enabled == 1) {
160 ret = kernel_disable_channel(kchan);
161 if (ret < 0 && ret != -EEXIST) {
162 ret = LTTNG_ERR_KERN_CHAN_DISABLE_FAIL;
163 goto error;
164 }
165 }
166
167 ret = LTTNG_OK;
168
169error:
170 return ret;
171}
172
173/*
174 * Enable kernel channel of the kernel session.
175 */
176enum lttng_error_code channel_kernel_enable(struct ltt_kernel_session *ksession,
177 struct ltt_kernel_channel *kchan)
178{
179 enum lttng_error_code ret_code;
180
181 LTTNG_ASSERT(ksession);
182 LTTNG_ASSERT(kchan);
183
184 if (kchan->enabled == 0) {
185 if (kernel_enable_channel(kchan) < 0) {
186 ret_code = LTTNG_ERR_KERN_CHAN_ENABLE_FAIL;
187 goto error;
188 }
189 } else {
190 ret_code = LTTNG_ERR_KERN_CHAN_EXIST;
191 goto error;
192 }
193
194 ret_code = LTTNG_OK;
195
196error:
197 return ret_code;
198}
199
200static int channel_validate(struct lttng_channel *attr)
201{
202 /*
203 * The ringbuffer (both in user space and kernel) behaves badly
204 * in overwrite mode and with less than 2 subbuffers so block it
205 * right away and send back an invalid attribute error.
206 */
207 if (attr->attr.overwrite && attr->attr.num_subbuf < 2) {
208 return -1;
209 }
210 return 0;
211}
212
213static int channel_validate_kernel(struct lttng_channel *attr)
214{
215 /* Kernel channels do not support blocking timeout. */
216 if (((struct lttng_channel_extended *)attr->attr.extended.ptr)->blocking_timeout) {
217 return -1;
218 }
219 return 0;
220}
221
222/*
223 * Create kernel channel of the kernel session and notify kernel thread.
224 */
225enum lttng_error_code channel_kernel_create(struct ltt_kernel_session *ksession,
226 struct lttng_channel *attr, int kernel_pipe)
227{
228 enum lttng_error_code ret_code;
229 struct lttng_channel *defattr = NULL;
230
231 LTTNG_ASSERT(ksession);
232
233 /* Creating channel attributes if needed */
234 if (attr == NULL) {
235 defattr = channel_new_default_attr(LTTNG_DOMAIN_KERNEL,
236 LTTNG_BUFFER_GLOBAL);
237 if (defattr == NULL) {
238 ret_code = LTTNG_ERR_FATAL;
239 goto error;
240 }
241 attr = defattr;
242 }
243
244 /*
245 * Set the overwrite mode for this channel based on the session
246 * type unless the client explicitly overrides the channel mode.
247 */
248 if (attr->attr.overwrite == DEFAULT_CHANNEL_OVERWRITE) {
249 attr->attr.overwrite = !!ksession->snapshot_mode;
250 }
251
252 /* Validate common channel properties. */
253 if (channel_validate(attr) < 0) {
254 ret_code = LTTNG_ERR_INVALID;
255 goto error;
256 }
257
258 if (channel_validate_kernel(attr) < 0) {
259 ret_code = LTTNG_ERR_INVALID;
260 goto error;
261 }
262
263 /* Channel not found, creating it. */
264 if (kernel_create_channel(ksession, attr) < 0) {
265 ret_code = LTTNG_ERR_KERN_CHAN_FAIL;
266 goto error;
267 }
268
269 /* Notify kernel thread that there is a new channel */
270 if (notify_thread_pipe(kernel_pipe) < 0) {
271 ret_code = LTTNG_ERR_FATAL;
272 goto error;
273 }
274
275 ret_code = LTTNG_OK;
276error:
277 channel_attr_destroy(defattr);
278 return ret_code;
279}
280
281/*
282 * Enable UST channel for session and domain.
283 */
284enum lttng_error_code channel_ust_enable(struct ltt_ust_session *usess,
285 struct ltt_ust_channel *uchan)
286{
287 enum lttng_error_code ret_code = LTTNG_OK;
288
289 LTTNG_ASSERT(usess);
290 LTTNG_ASSERT(uchan);
291
292 /* If already enabled, everything is OK */
293 if (uchan->enabled) {
294 DBG3("Channel %s already enabled. Skipping", uchan->name);
295 ret_code = LTTNG_ERR_UST_CHAN_EXIST;
296 goto end;
297 } else {
298 uchan->enabled = 1;
299 DBG2("Channel %s enabled successfully", uchan->name);
300 }
301
302 if (!usess->active) {
303 /*
304 * The channel will be activated against the apps
305 * when the session is started as part of the
306 * application channel "synchronize" operation.
307 */
308 goto end;
309 }
310
311 DBG2("Channel %s being enabled in UST domain", uchan->name);
312
313 /*
314 * Enable channel for UST global domain on all applications. Ignore return
315 * value here since whatever error we got, it means that the channel was
316 * not created on one or many registered applications and we can not report
317 * this to the user yet. However, at this stage, the channel was
318 * successfully created on the session daemon side so the enable-channel
319 * command is a success.
320 */
321 (void) ust_app_enable_channel_glb(usess, uchan);
322
323
324end:
325 return ret_code;
326}
327
328/*
329 * Create UST channel for session and domain.
330 */
331enum lttng_error_code channel_ust_create(struct ltt_ust_session *usess,
332 struct lttng_channel *attr, enum lttng_buffer_type type)
333{
334 enum lttng_error_code ret_code = LTTNG_OK;
335 struct ltt_ust_channel *uchan = NULL;
336 struct lttng_channel *defattr = NULL;
337 enum lttng_domain_type domain = LTTNG_DOMAIN_UST;
338 bool chan_published = false;
339
340 LTTNG_ASSERT(usess);
341
342 /* Creating channel attributes if needed */
343 if (attr == NULL) {
344 defattr = channel_new_default_attr(LTTNG_DOMAIN_UST, type);
345 if (defattr == NULL) {
346 ret_code = LTTNG_ERR_FATAL;
347 goto error;
348 }
349 attr = defattr;
350 } else {
351 /*
352 * HACK: Set the channel's subdomain (JUL, Log4j, Python, etc.)
353 * based on the default name.
354 */
355 if (!strcmp(attr->name, DEFAULT_JUL_CHANNEL_NAME)) {
356 domain = LTTNG_DOMAIN_JUL;
357 } else if (!strcmp(attr->name, DEFAULT_LOG4J_CHANNEL_NAME)) {
358 domain = LTTNG_DOMAIN_LOG4J;
359 } else if (!strcmp(attr->name, DEFAULT_PYTHON_CHANNEL_NAME)) {
360 domain = LTTNG_DOMAIN_PYTHON;
361 }
362 }
363
364 /*
365 * Set the overwrite mode for this channel based on the session
366 * type unless the client explicitly overrides the channel mode.
367 */
368 if (attr->attr.overwrite == DEFAULT_CHANNEL_OVERWRITE) {
369 attr->attr.overwrite = !!usess->snapshot_mode;
370 }
371
372 /* Enforce mmap output for snapshot sessions. */
373 if (usess->snapshot_mode) {
374 attr->attr.output = LTTNG_EVENT_MMAP;
375 }
376
377 /* Validate common channel properties. */
378 if (channel_validate(attr) < 0) {
379 ret_code = LTTNG_ERR_INVALID;
380 goto error;
381 }
382
383 /*
384 * Validate UST buffer size and number of buffers: must both be power of 2
385 * and nonzero. We validate right here for UST, because applications will
386 * not report the error to the user (unlike kernel tracing).
387 */
388 if (!attr->attr.subbuf_size ||
389 (attr->attr.subbuf_size & (attr->attr.subbuf_size - 1))) {
390 ret_code = LTTNG_ERR_INVALID;
391 goto error;
392 }
393
394 /*
395 * Invalid subbuffer size if it's lower then the page size.
396 */
397 if (attr->attr.subbuf_size < the_page_size) {
398 ret_code = LTTNG_ERR_INVALID;
399 goto error;
400 }
401
402 if (!attr->attr.num_subbuf ||
403 (attr->attr.num_subbuf & (attr->attr.num_subbuf - 1))) {
404 ret_code = LTTNG_ERR_INVALID;
405 goto error;
406 }
407
408 if (attr->attr.output != LTTNG_EVENT_MMAP) {
409 ret_code = LTTNG_ERR_NOT_SUPPORTED;
410 goto error;
411 }
412
413 /*
414 * The tracefile_size should not be < to the subbuf_size, otherwise
415 * we won't be able to write the packets on disk
416 */
417 if ((attr->attr.tracefile_size > 0) &&
418 (attr->attr.tracefile_size < attr->attr.subbuf_size)) {
419 ret_code = LTTNG_ERR_INVALID;
420 goto error;
421 }
422
423 /* Validate buffer type. */
424 switch (type) {
425 case LTTNG_BUFFER_PER_PID:
426 break;
427 case LTTNG_BUFFER_PER_UID:
428 break;
429 default:
430 ret_code = LTTNG_ERR_BUFFER_NOT_SUPPORTED;
431 goto error;
432 }
433
434 /* Create UST channel */
435 uchan = trace_ust_create_channel(attr, domain);
436 if (uchan == NULL) {
437 ret_code = LTTNG_ERR_FATAL;
438 goto error;
439 }
440
441 uchan->enabled = 1;
442 if (trace_ust_is_max_id(usess->used_channel_id)) {
443 ret_code = LTTNG_ERR_UST_CHAN_FAIL;
444 goto error;
445 }
446 uchan->id = trace_ust_get_next_chan_id(usess);
447
448 DBG2("Channel %s is being created for UST with buffer %d and id %" PRIu64,
449 uchan->name, type, uchan->id);
450
451 /* Flag session buffer type. */
452 if (!usess->buffer_type_changed) {
453 usess->buffer_type = type;
454 usess->buffer_type_changed = 1;
455 } else if (usess->buffer_type != type) {
456 /* Buffer type was already set. Refuse to create channel. */
457 ret_code = LTTNG_ERR_BUFFER_TYPE_MISMATCH;
458 goto error_free_chan;
459 }
460
461 /* Adding the channel to the channel hash table. */
462 rcu_read_lock();
463 if (strncmp(uchan->name, DEFAULT_METADATA_NAME,
464 sizeof(uchan->name))) {
465 lttng_ht_add_unique_str(usess->domain_global.channels, &uchan->node);
466 chan_published = true;
467 } else {
468 /*
469 * Copy channel attribute to session if this is metadata so if NO
470 * application exists we can access that data in the shadow copy during
471 * the global update of newly registered application.
472 */
473 memcpy(&usess->metadata_attr, &uchan->attr,
474 sizeof(usess->metadata_attr));
475 }
476 rcu_read_unlock();
477
478 DBG2("Channel %s created successfully", uchan->name);
479 if (domain != LTTNG_DOMAIN_UST) {
480 struct agent *agt = trace_ust_find_agent(usess, domain);
481
482 if (!agt) {
483 agt = agent_create(domain);
484 if (!agt) {
485 ret_code = LTTNG_ERR_NOMEM;
486 goto error_remove_chan;
487 }
488 agent_add(agt, usess->agents);
489 }
490 }
491
492 channel_attr_destroy(defattr);
493 return LTTNG_OK;
494
495error_remove_chan:
496 if (chan_published) {
497 trace_ust_delete_channel(usess->domain_global.channels, uchan);
498 }
499error_free_chan:
500 trace_ust_destroy_channel(uchan);
501error:
502 channel_attr_destroy(defattr);
503 return ret_code;
504}
505
506/*
507 * Disable UST channel for session and domain.
508 */
509int channel_ust_disable(struct ltt_ust_session *usess,
510 struct ltt_ust_channel *uchan)
511{
512 int ret = LTTNG_OK;
513
514 LTTNG_ASSERT(usess);
515 LTTNG_ASSERT(uchan);
516
517 /* Already disabled */
518 if (uchan->enabled == 0) {
519 DBG2("Channel UST %s already disabled", uchan->name);
520 goto end;
521 }
522
523 uchan->enabled = 0;
524
525 /*
526 * If session is inactive we don't notify the tracer right away. We
527 * wait for the next synchronization.
528 */
529 if (!usess->active) {
530 goto end;
531 }
532
533 DBG2("Channel %s being disabled in UST global domain", uchan->name);
534 /* Disable channel for global domain */
535 ret = ust_app_disable_channel_glb(usess, uchan);
536 if (ret < 0 && ret != -LTTNG_UST_ERR_EXIST) {
537 ret = LTTNG_ERR_UST_CHAN_DISABLE_FAIL;
538 goto error;
539 }
540
541 DBG2("Channel %s disabled successfully", uchan->name);
542
543 return LTTNG_OK;
544
545end:
546error:
547 return ret;
548}
549
550struct lttng_channel *trace_ust_channel_to_lttng_channel(
551 const struct ltt_ust_channel *uchan)
552{
553 struct lttng_channel *channel = NULL, *ret = NULL;
554
555 channel = lttng_channel_create_internal();
556 if (!channel) {
557 ERR("Failed to create lttng_channel during conversion from ltt_ust_channel to lttng_channel");
558 goto end;
559 }
560
561 if (lttng_strncpy(channel->name, uchan->name, LTTNG_SYMBOL_NAME_LEN)) {
562 ERR("Failed to set channel name during conversion from ltt_ust_channel to lttng_channel");
563 goto end;
564 }
565
566 channel->attr.overwrite = uchan->attr.overwrite;
567 channel->attr.subbuf_size = uchan->attr.subbuf_size;
568 channel->attr.num_subbuf = uchan->attr.num_subbuf;
569 channel->attr.switch_timer_interval = uchan->attr.switch_timer_interval;
570 channel->attr.read_timer_interval = uchan->attr.read_timer_interval;
571 channel->enabled = uchan->enabled;
572 channel->attr.tracefile_size = uchan->tracefile_size;
573 channel->attr.tracefile_count = uchan->tracefile_count;
574
575 /*
576 * Map enum lttng_ust_output to enum lttng_event_output.
577 */
578 switch (uchan->attr.output) {
579 case LTTNG_UST_ABI_MMAP:
580 channel->attr.output = LTTNG_EVENT_MMAP;
581 break;
582 default:
583 /*
584 * LTTNG_UST_MMAP is the only supported UST
585 * output mode.
586 */
587 abort();
588 break;
589 }
590
591 lttng_channel_set_blocking_timeout(
592 channel, uchan->attr.u.s.blocking_timeout);
593 lttng_channel_set_monitor_timer_interval(
594 channel, uchan->monitor_timer_interval);
595
596 ret = channel;
597 channel = NULL;
598
599end:
600 lttng_channel_destroy(channel);
601 return ret;
602}
This page took 0.025459 seconds and 4 git commands to generate.