notification: transmit originating trigger as part of evaluation
[lttng-tools.git] / src / bin / lttng-sessiond / notification-thread-events.c
1 /*
2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 */
7
8 #include "lttng/action/action.h"
9 #include "lttng/trigger/trigger-internal.h"
10 #define _LGPL_SOURCE
11 #include <urcu.h>
12 #include <urcu/rculfhash.h>
13
14 #include <common/defaults.h>
15 #include <common/error.h>
16 #include <common/futex.h>
17 #include <common/unix.h>
18 #include <common/dynamic-buffer.h>
19 #include <common/hashtable/utils.h>
20 #include <common/sessiond-comm/sessiond-comm.h>
21 #include <common/macros.h>
22 #include <lttng/condition/condition.h>
23 #include <lttng/action/action-internal.h>
24 #include <lttng/action/group-internal.h>
25 #include <lttng/domain-internal.h>
26 #include <lttng/notification/notification-internal.h>
27 #include <lttng/condition/condition-internal.h>
28 #include <lttng/condition/buffer-usage-internal.h>
29 #include <lttng/condition/session-consumed-size-internal.h>
30 #include <lttng/condition/session-rotation-internal.h>
31 #include <lttng/condition/on-event-internal.h>
32 #include <lttng/domain-internal.h>
33 #include <lttng/notification/channel-internal.h>
34 #include <lttng/trigger/trigger-internal.h>
35 #include <lttng/event-rule/event-rule-internal.h>
36
37 #include <time.h>
38 #include <unistd.h>
39 #include <assert.h>
40 #include <inttypes.h>
41 #include <fcntl.h>
42
43 #include "condition-internal.h"
44 #include "event-notifier-error-accounting.h"
45 #include "notification-thread.h"
46 #include "notification-thread-events.h"
47 #include "notification-thread-commands.h"
48 #include "lttng-sessiond.h"
49 #include "kernel.h"
50
51 #define CLIENT_POLL_MASK_IN (LPOLLIN | LPOLLERR | LPOLLHUP | LPOLLRDHUP)
52 #define CLIENT_POLL_MASK_IN_OUT (CLIENT_POLL_MASK_IN | LPOLLOUT)
53
54 /* The tracers currently limit the capture size to PIPE_BUF (4kb on linux). */
55 #define MAX_CAPTURE_SIZE (PIPE_BUF)
56
57 enum lttng_object_type {
58 LTTNG_OBJECT_TYPE_UNKNOWN,
59 LTTNG_OBJECT_TYPE_NONE,
60 LTTNG_OBJECT_TYPE_CHANNEL,
61 LTTNG_OBJECT_TYPE_SESSION,
62 };
63
64 struct lttng_trigger_list_element {
65 /* No ownership of the trigger object is assumed. */
66 struct lttng_trigger *trigger;
67 struct cds_list_head node;
68 };
69
70 struct lttng_channel_trigger_list {
71 struct channel_key channel_key;
72 /* List of struct lttng_trigger_list_element. */
73 struct cds_list_head list;
74 /* Node in the channel_triggers_ht */
75 struct cds_lfht_node channel_triggers_ht_node;
76 /* call_rcu delayed reclaim. */
77 struct rcu_head rcu_node;
78 };
79
80 /*
81 * List of triggers applying to a given session.
82 *
83 * See:
84 * - lttng_session_trigger_list_create()
85 * - lttng_session_trigger_list_build()
86 * - lttng_session_trigger_list_destroy()
87 * - lttng_session_trigger_list_add()
88 */
89 struct lttng_session_trigger_list {
90 /*
91 * Not owned by this; points to the session_info structure's
92 * session name.
93 */
94 const char *session_name;
95 /* List of struct lttng_trigger_list_element. */
96 struct cds_list_head list;
97 /* Node in the session_triggers_ht */
98 struct cds_lfht_node session_triggers_ht_node;
99 /*
100 * Weak reference to the notification system's session triggers
101 * hashtable.
102 *
103 * The session trigger list structure structure is owned by
104 * the session's session_info.
105 *
106 * The session_info is kept alive the the channel_infos holding a
107 * reference to it (reference counting). When those channels are
108 * destroyed (at runtime or on teardown), the reference they hold
109 * to the session_info are released. On destruction of session_info,
110 * session_info_destroy() will remove the list of triggers applying
111 * to this session from the notification system's state.
112 *
113 * This implies that the session_triggers_ht must be destroyed
114 * after the channels.
115 */
116 struct cds_lfht *session_triggers_ht;
117 /* Used for delayed RCU reclaim. */
118 struct rcu_head rcu_node;
119 };
120
121 struct lttng_trigger_ht_element {
122 struct lttng_trigger *trigger;
123 struct cds_lfht_node node;
124 struct cds_lfht_node node_by_name_uid;
125 struct cds_list_head client_list_trigger_node;
126 /* call_rcu delayed reclaim. */
127 struct rcu_head rcu_node;
128 };
129
130 struct lttng_condition_list_element {
131 struct lttng_condition *condition;
132 struct cds_list_head node;
133 };
134
135 struct channel_state_sample {
136 struct channel_key key;
137 struct cds_lfht_node channel_state_ht_node;
138 uint64_t highest_usage;
139 uint64_t lowest_usage;
140 uint64_t channel_total_consumed;
141 /* call_rcu delayed reclaim. */
142 struct rcu_head rcu_node;
143 };
144
145 static unsigned long hash_channel_key(struct channel_key *key);
146 static int evaluate_buffer_condition(const struct lttng_condition *condition,
147 struct lttng_evaluation **evaluation,
148 const struct notification_thread_state *state,
149 const struct channel_state_sample *previous_sample,
150 const struct channel_state_sample *latest_sample,
151 uint64_t previous_session_consumed_total,
152 uint64_t latest_session_consumed_total,
153 struct channel_info *channel_info);
154 static
155 int send_evaluation_to_clients(const struct lttng_trigger *trigger,
156 const struct lttng_evaluation *evaluation,
157 struct notification_client_list *client_list,
158 struct notification_thread_state *state,
159 uid_t channel_uid, gid_t channel_gid);
160
161
162 /* session_info API */
163 static
164 void session_info_destroy(void *_data);
165 static
166 void session_info_get(struct session_info *session_info);
167 static
168 void session_info_put(struct session_info *session_info);
169 static
170 struct session_info *session_info_create(const char *name,
171 uid_t uid, gid_t gid,
172 struct lttng_session_trigger_list *trigger_list,
173 struct cds_lfht *sessions_ht);
174 static
175 void session_info_add_channel(struct session_info *session_info,
176 struct channel_info *channel_info);
177 static
178 void session_info_remove_channel(struct session_info *session_info,
179 struct channel_info *channel_info);
180
181 /* lttng_session_trigger_list API */
182 static
183 struct lttng_session_trigger_list *lttng_session_trigger_list_create(
184 const char *session_name,
185 struct cds_lfht *session_triggers_ht);
186 static
187 struct lttng_session_trigger_list *lttng_session_trigger_list_build(
188 const struct notification_thread_state *state,
189 const char *session_name);
190 static
191 void lttng_session_trigger_list_destroy(
192 struct lttng_session_trigger_list *list);
193 static
194 int lttng_session_trigger_list_add(struct lttng_session_trigger_list *list,
195 struct lttng_trigger *trigger);
196
197 static
198 int client_handle_transmission_status(
199 struct notification_client *client,
200 enum client_transmission_status transmission_status,
201 struct notification_thread_state *state);
202
203 static
204 int handle_one_event_notifier_notification(
205 struct notification_thread_state *state,
206 int pipe, enum lttng_domain_type domain);
207
208 static
209 void free_lttng_trigger_ht_element_rcu(struct rcu_head *node);
210
211 static
212 int match_client_socket(struct cds_lfht_node *node, const void *key)
213 {
214 /* This double-cast is intended to supress pointer-to-cast warning. */
215 const int socket = (int) (intptr_t) key;
216 const struct notification_client *client = caa_container_of(node,
217 struct notification_client, client_socket_ht_node);
218
219 return client->socket == socket;
220 }
221
222 static
223 int match_client_id(struct cds_lfht_node *node, const void *key)
224 {
225 /* This double-cast is intended to supress pointer-to-cast warning. */
226 const notification_client_id id = *((notification_client_id *) key);
227 const struct notification_client *client = caa_container_of(
228 node, struct notification_client, client_id_ht_node);
229
230 return client->id == id;
231 }
232
233 static
234 int match_channel_trigger_list(struct cds_lfht_node *node, const void *key)
235 {
236 struct channel_key *channel_key = (struct channel_key *) key;
237 struct lttng_channel_trigger_list *trigger_list;
238
239 trigger_list = caa_container_of(node, struct lttng_channel_trigger_list,
240 channel_triggers_ht_node);
241
242 return !!((channel_key->key == trigger_list->channel_key.key) &&
243 (channel_key->domain == trigger_list->channel_key.domain));
244 }
245
246 static
247 int match_session_trigger_list(struct cds_lfht_node *node, const void *key)
248 {
249 const char *session_name = (const char *) key;
250 struct lttng_session_trigger_list *trigger_list;
251
252 trigger_list = caa_container_of(node, struct lttng_session_trigger_list,
253 session_triggers_ht_node);
254
255 return !!(strcmp(trigger_list->session_name, session_name) == 0);
256 }
257
258 static
259 int match_channel_state_sample(struct cds_lfht_node *node, const void *key)
260 {
261 struct channel_key *channel_key = (struct channel_key *) key;
262 struct channel_state_sample *sample;
263
264 sample = caa_container_of(node, struct channel_state_sample,
265 channel_state_ht_node);
266
267 return !!((channel_key->key == sample->key.key) &&
268 (channel_key->domain == sample->key.domain));
269 }
270
271 static
272 int match_channel_info(struct cds_lfht_node *node, const void *key)
273 {
274 struct channel_key *channel_key = (struct channel_key *) key;
275 struct channel_info *channel_info;
276
277 channel_info = caa_container_of(node, struct channel_info,
278 channels_ht_node);
279
280 return !!((channel_key->key == channel_info->key.key) &&
281 (channel_key->domain == channel_info->key.domain));
282 }
283
284 static
285 int match_trigger(struct cds_lfht_node *node, const void *key)
286 {
287 struct lttng_trigger *trigger_key = (struct lttng_trigger *) key;
288 struct lttng_trigger_ht_element *trigger_ht_element;
289
290 trigger_ht_element = caa_container_of(node, struct lttng_trigger_ht_element,
291 node);
292
293 return !!lttng_trigger_is_equal(trigger_key, trigger_ht_element->trigger);
294 }
295
296 static
297 int match_trigger_token(struct cds_lfht_node *node, const void *key)
298 {
299 const uint64_t *_key = key;
300 struct notification_trigger_tokens_ht_element *element;
301
302 element = caa_container_of(node,
303 struct notification_trigger_tokens_ht_element, node);
304 return *_key == element->token;
305 }
306
307 static
308 int match_client_list_condition(struct cds_lfht_node *node, const void *key)
309 {
310 struct lttng_condition *condition_key = (struct lttng_condition *) key;
311 struct notification_client_list *client_list;
312 const struct lttng_condition *condition;
313
314 assert(condition_key);
315
316 client_list = caa_container_of(node, struct notification_client_list,
317 notification_trigger_clients_ht_node);
318 condition = client_list->condition;
319
320 return !!lttng_condition_is_equal(condition_key, condition);
321 }
322
323 static
324 int match_session(struct cds_lfht_node *node, const void *key)
325 {
326 const char *name = key;
327 struct session_info *session_info = caa_container_of(
328 node, struct session_info, sessions_ht_node);
329
330 return !strcmp(session_info->name, name);
331 }
332
333 static
334 const char *notification_command_type_str(
335 enum notification_thread_command_type type)
336 {
337 switch (type) {
338 case NOTIFICATION_COMMAND_TYPE_REGISTER_TRIGGER:
339 return "REGISTER_TRIGGER";
340 case NOTIFICATION_COMMAND_TYPE_UNREGISTER_TRIGGER:
341 return "UNREGISTER_TRIGGER";
342 case NOTIFICATION_COMMAND_TYPE_ADD_CHANNEL:
343 return "ADD_CHANNEL";
344 case NOTIFICATION_COMMAND_TYPE_REMOVE_CHANNEL:
345 return "REMOVE_CHANNEL";
346 case NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_ONGOING:
347 return "SESSION_ROTATION_ONGOING";
348 case NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_COMPLETED:
349 return "SESSION_ROTATION_COMPLETED";
350 case NOTIFICATION_COMMAND_TYPE_ADD_TRACER_EVENT_SOURCE:
351 return "ADD_TRACER_EVENT_SOURCE";
352 case NOTIFICATION_COMMAND_TYPE_REMOVE_TRACER_EVENT_SOURCE:
353 return "REMOVE_TRACER_EVENT_SOURCE";
354 case NOTIFICATION_COMMAND_TYPE_LIST_TRIGGERS:
355 return "LIST_TRIGGERS";
356 case NOTIFICATION_COMMAND_TYPE_QUIT:
357 return "QUIT";
358 case NOTIFICATION_COMMAND_TYPE_CLIENT_COMMUNICATION_UPDATE:
359 return "CLIENT_COMMUNICATION_UPDATE";
360 default:
361 abort();
362 }
363 }
364
365 /*
366 * Match trigger based on name and credentials only.
367 * Name duplication is NOT allowed for the same uid.
368 */
369 static
370 int match_trigger_by_name_uid(struct cds_lfht_node *node,
371 const void *key)
372 {
373 bool match = false;
374 const char *name;
375 const char *key_name;
376 enum lttng_trigger_status status;
377 const struct lttng_credentials *key_creds;
378 const struct lttng_credentials *node_creds;
379 const struct lttng_trigger *trigger_key =
380 (const struct lttng_trigger *) key;
381 const struct lttng_trigger_ht_element *trigger_ht_element =
382 caa_container_of(node,
383 struct lttng_trigger_ht_element,
384 node_by_name_uid);
385
386 status = lttng_trigger_get_name(trigger_ht_element->trigger, &name);
387 assert(status == LTTNG_TRIGGER_STATUS_OK);
388
389 status = lttng_trigger_get_name(trigger_key, &key_name);
390 assert(status == LTTNG_TRIGGER_STATUS_OK);
391
392 /* Compare the names. */
393 if (strcmp(name, key_name) != 0) {
394 goto end;
395 }
396
397 /* Compare the owners' UIDs. */
398 key_creds = lttng_trigger_get_credentials(trigger_key);
399 node_creds = lttng_trigger_get_credentials(trigger_ht_element->trigger);
400
401 match = lttng_credentials_is_equal_uid(key_creds, node_creds);
402
403 end:
404 return match;
405 }
406
407 /*
408 * Hash trigger based on name and credentials only.
409 */
410 static
411 unsigned long hash_trigger_by_name_uid(const struct lttng_trigger *trigger)
412 {
413 unsigned long hash = 0;
414 const struct lttng_credentials *trigger_creds;
415 const char *trigger_name;
416 enum lttng_trigger_status status;
417
418 status = lttng_trigger_get_name(trigger, &trigger_name);
419 if (status == LTTNG_TRIGGER_STATUS_OK) {
420 hash = hash_key_str(trigger_name, lttng_ht_seed);
421 }
422
423 trigger_creds = lttng_trigger_get_credentials(trigger);
424 hash ^= hash_key_ulong((void *) (unsigned long) LTTNG_OPTIONAL_GET(trigger_creds->uid),
425 lttng_ht_seed);
426
427 return hash;
428 }
429
430 static
431 unsigned long hash_channel_key(struct channel_key *key)
432 {
433 unsigned long key_hash = hash_key_u64(&key->key, lttng_ht_seed);
434 unsigned long domain_hash = hash_key_ulong(
435 (void *) (unsigned long) key->domain, lttng_ht_seed);
436
437 return key_hash ^ domain_hash;
438 }
439
440 static
441 unsigned long hash_client_socket(int socket)
442 {
443 return hash_key_ulong((void *) (unsigned long) socket, lttng_ht_seed);
444 }
445
446 static
447 unsigned long hash_client_id(notification_client_id id)
448 {
449 return hash_key_u64(&id, lttng_ht_seed);
450 }
451
452 /*
453 * Get the type of object to which a given condition applies. Bindings let
454 * the notification system evaluate a trigger's condition when a given
455 * object's state is updated.
456 *
457 * For instance, a condition bound to a channel will be evaluated everytime
458 * the channel's state is changed by a channel monitoring sample.
459 */
460 static
461 enum lttng_object_type get_condition_binding_object(
462 const struct lttng_condition *condition)
463 {
464 switch (lttng_condition_get_type(condition)) {
465 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
466 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
467 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE:
468 return LTTNG_OBJECT_TYPE_CHANNEL;
469 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
470 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
471 return LTTNG_OBJECT_TYPE_SESSION;
472 case LTTNG_CONDITION_TYPE_ON_EVENT:
473 return LTTNG_OBJECT_TYPE_NONE;
474 default:
475 return LTTNG_OBJECT_TYPE_UNKNOWN;
476 }
477 }
478
479 static
480 void free_channel_info_rcu(struct rcu_head *node)
481 {
482 free(caa_container_of(node, struct channel_info, rcu_node));
483 }
484
485 static
486 void channel_info_destroy(struct channel_info *channel_info)
487 {
488 if (!channel_info) {
489 return;
490 }
491
492 if (channel_info->session_info) {
493 session_info_remove_channel(channel_info->session_info,
494 channel_info);
495 session_info_put(channel_info->session_info);
496 }
497 if (channel_info->name) {
498 free(channel_info->name);
499 }
500 call_rcu(&channel_info->rcu_node, free_channel_info_rcu);
501 }
502
503 static
504 void free_session_info_rcu(struct rcu_head *node)
505 {
506 free(caa_container_of(node, struct session_info, rcu_node));
507 }
508
509 /* Don't call directly, use the ref-counting mechanism. */
510 static
511 void session_info_destroy(void *_data)
512 {
513 struct session_info *session_info = _data;
514 int ret;
515
516 assert(session_info);
517 if (session_info->channel_infos_ht) {
518 ret = cds_lfht_destroy(session_info->channel_infos_ht, NULL);
519 if (ret) {
520 ERR("[notification-thread] Failed to destroy channel information hash table");
521 }
522 }
523 lttng_session_trigger_list_destroy(session_info->trigger_list);
524
525 rcu_read_lock();
526 cds_lfht_del(session_info->sessions_ht,
527 &session_info->sessions_ht_node);
528 rcu_read_unlock();
529 free(session_info->name);
530 call_rcu(&session_info->rcu_node, free_session_info_rcu);
531 }
532
533 static
534 void session_info_get(struct session_info *session_info)
535 {
536 if (!session_info) {
537 return;
538 }
539 lttng_ref_get(&session_info->ref);
540 }
541
542 static
543 void session_info_put(struct session_info *session_info)
544 {
545 if (!session_info) {
546 return;
547 }
548 lttng_ref_put(&session_info->ref);
549 }
550
551 static
552 struct session_info *session_info_create(const char *name, uid_t uid, gid_t gid,
553 struct lttng_session_trigger_list *trigger_list,
554 struct cds_lfht *sessions_ht)
555 {
556 struct session_info *session_info;
557
558 assert(name);
559
560 session_info = zmalloc(sizeof(*session_info));
561 if (!session_info) {
562 goto end;
563 }
564 lttng_ref_init(&session_info->ref, session_info_destroy);
565
566 session_info->channel_infos_ht = cds_lfht_new(DEFAULT_HT_SIZE,
567 1, 0, CDS_LFHT_AUTO_RESIZE | CDS_LFHT_ACCOUNTING, NULL);
568 if (!session_info->channel_infos_ht) {
569 goto error;
570 }
571
572 cds_lfht_node_init(&session_info->sessions_ht_node);
573 session_info->name = strdup(name);
574 if (!session_info->name) {
575 goto error;
576 }
577 session_info->uid = uid;
578 session_info->gid = gid;
579 session_info->trigger_list = trigger_list;
580 session_info->sessions_ht = sessions_ht;
581 end:
582 return session_info;
583 error:
584 session_info_put(session_info);
585 return NULL;
586 }
587
588 static
589 void session_info_add_channel(struct session_info *session_info,
590 struct channel_info *channel_info)
591 {
592 rcu_read_lock();
593 cds_lfht_add(session_info->channel_infos_ht,
594 hash_channel_key(&channel_info->key),
595 &channel_info->session_info_channels_ht_node);
596 rcu_read_unlock();
597 }
598
599 static
600 void session_info_remove_channel(struct session_info *session_info,
601 struct channel_info *channel_info)
602 {
603 rcu_read_lock();
604 cds_lfht_del(session_info->channel_infos_ht,
605 &channel_info->session_info_channels_ht_node);
606 rcu_read_unlock();
607 }
608
609 static
610 struct channel_info *channel_info_create(const char *channel_name,
611 struct channel_key *channel_key, uint64_t channel_capacity,
612 struct session_info *session_info)
613 {
614 struct channel_info *channel_info = zmalloc(sizeof(*channel_info));
615
616 if (!channel_info) {
617 goto end;
618 }
619
620 cds_lfht_node_init(&channel_info->channels_ht_node);
621 cds_lfht_node_init(&channel_info->session_info_channels_ht_node);
622 memcpy(&channel_info->key, channel_key, sizeof(*channel_key));
623 channel_info->capacity = channel_capacity;
624
625 channel_info->name = strdup(channel_name);
626 if (!channel_info->name) {
627 goto error;
628 }
629
630 /*
631 * Set the references between session and channel infos:
632 * - channel_info holds a strong reference to session_info
633 * - session_info holds a weak reference to channel_info
634 */
635 session_info_get(session_info);
636 session_info_add_channel(session_info, channel_info);
637 channel_info->session_info = session_info;
638 end:
639 return channel_info;
640 error:
641 channel_info_destroy(channel_info);
642 return NULL;
643 }
644
645 LTTNG_HIDDEN
646 bool notification_client_list_get(struct notification_client_list *list)
647 {
648 return urcu_ref_get_unless_zero(&list->ref);
649 }
650
651 static
652 void free_notification_client_list_rcu(struct rcu_head *node)
653 {
654 free(caa_container_of(node, struct notification_client_list,
655 rcu_node));
656 }
657
658 static
659 void notification_client_list_release(struct urcu_ref *list_ref)
660 {
661 struct notification_client_list *list =
662 container_of(list_ref, typeof(*list), ref);
663 struct notification_client_list_element *client_list_element, *tmp;
664
665 lttng_condition_put(list->condition);
666
667 if (list->notification_trigger_clients_ht) {
668 rcu_read_lock();
669
670 cds_lfht_del(list->notification_trigger_clients_ht,
671 &list->notification_trigger_clients_ht_node);
672 rcu_read_unlock();
673 list->notification_trigger_clients_ht = NULL;
674 }
675 cds_list_for_each_entry_safe(client_list_element, tmp,
676 &list->clients_list, node) {
677 free(client_list_element);
678 }
679
680 assert(cds_list_empty(&list->triggers_list));
681
682 pthread_mutex_destroy(&list->lock);
683 call_rcu(&list->rcu_node, free_notification_client_list_rcu);
684 }
685
686 static
687 bool condition_applies_to_client(const struct lttng_condition *condition,
688 struct notification_client *client)
689 {
690 bool applies = false;
691 struct lttng_condition_list_element *condition_list_element;
692
693 cds_list_for_each_entry(condition_list_element, &client->condition_list,
694 node) {
695 applies = lttng_condition_is_equal(
696 condition_list_element->condition,
697 condition);
698 if (applies) {
699 break;
700 }
701 }
702
703 return applies;
704 }
705
706 static
707 struct notification_client_list *notification_client_list_create(
708 struct notification_thread_state *state,
709 const struct lttng_condition *condition)
710 {
711 struct notification_client *client;
712 struct cds_lfht_iter iter;
713 struct notification_client_list *client_list;
714
715 client_list = zmalloc(sizeof(*client_list));
716 if (!client_list) {
717 PERROR("Failed to allocate notification client list");
718 goto end;
719 }
720
721 pthread_mutex_init(&client_list->lock, NULL);
722 /*
723 * The trigger that owns the condition has the first reference to this
724 * client list.
725 */
726 urcu_ref_init(&client_list->ref);
727 cds_lfht_node_init(&client_list->notification_trigger_clients_ht_node);
728 CDS_INIT_LIST_HEAD(&client_list->clients_list);
729 CDS_INIT_LIST_HEAD(&client_list->triggers_list);
730
731 /*
732 * Create a copy of the condition so that it's independent of any
733 * trigger. The client list may outlive the trigger object (which owns
734 * the condition) that is used to create it.
735 */
736 client_list->condition = lttng_condition_copy(condition);
737
738 /* Build a list of clients to which this new condition applies. */
739 cds_lfht_for_each_entry (state->client_socket_ht, &iter, client,
740 client_socket_ht_node) {
741 struct notification_client_list_element *client_list_element;
742
743 if (!condition_applies_to_client(condition, client)) {
744 continue;
745 }
746
747 client_list_element = zmalloc(sizeof(*client_list_element));
748 if (!client_list_element) {
749 goto error_put_client_list;
750 }
751
752 CDS_INIT_LIST_HEAD(&client_list_element->node);
753 client_list_element->client = client;
754 cds_list_add(&client_list_element->node, &client_list->clients_list);
755 }
756
757 client_list->notification_trigger_clients_ht =
758 state->notification_trigger_clients_ht;
759
760 rcu_read_lock();
761 /*
762 * Add the client list to the global list of client list.
763 */
764 cds_lfht_add_unique(state->notification_trigger_clients_ht,
765 lttng_condition_hash(client_list->condition),
766 match_client_list_condition,
767 client_list->condition,
768 &client_list->notification_trigger_clients_ht_node);
769 rcu_read_unlock();
770 goto end;
771
772 error_put_client_list:
773 notification_client_list_put(client_list);
774 client_list = NULL;
775
776 end:
777 return client_list;
778 }
779
780 void notification_client_list_put(struct notification_client_list *list)
781 {
782 if (!list) {
783 return;
784 }
785 return urcu_ref_put(&list->ref, notification_client_list_release);
786 }
787
788 /* Provides a reference to the returned list. */
789 static
790 struct notification_client_list *get_client_list_from_condition(
791 struct notification_thread_state *state,
792 const struct lttng_condition *condition)
793 {
794 struct cds_lfht_node *node;
795 struct cds_lfht_iter iter;
796 struct notification_client_list *list = NULL;
797
798 rcu_read_lock();
799 cds_lfht_lookup(state->notification_trigger_clients_ht,
800 lttng_condition_hash(condition),
801 match_client_list_condition,
802 condition,
803 &iter);
804 node = cds_lfht_iter_get_node(&iter);
805 if (node) {
806 list = container_of(node, struct notification_client_list,
807 notification_trigger_clients_ht_node);
808 list = notification_client_list_get(list) ? list : NULL;
809 }
810
811 rcu_read_unlock();
812 return list;
813 }
814
815 static
816 int evaluate_channel_condition_for_client(
817 const struct lttng_condition *condition,
818 struct notification_thread_state *state,
819 struct lttng_evaluation **evaluation,
820 uid_t *session_uid, gid_t *session_gid)
821 {
822 int ret;
823 struct cds_lfht_iter iter;
824 struct cds_lfht_node *node;
825 struct channel_info *channel_info = NULL;
826 struct channel_key *channel_key = NULL;
827 struct channel_state_sample *last_sample = NULL;
828 struct lttng_channel_trigger_list *channel_trigger_list = NULL;
829
830 rcu_read_lock();
831
832 /* Find the channel associated with the condition. */
833 cds_lfht_for_each_entry(state->channel_triggers_ht, &iter,
834 channel_trigger_list, channel_triggers_ht_node) {
835 struct lttng_trigger_list_element *element;
836
837 cds_list_for_each_entry(element, &channel_trigger_list->list, node) {
838 const struct lttng_condition *current_condition =
839 lttng_trigger_get_const_condition(
840 element->trigger);
841
842 assert(current_condition);
843 if (!lttng_condition_is_equal(condition,
844 current_condition)) {
845 continue;
846 }
847
848 /* Found the trigger, save the channel key. */
849 channel_key = &channel_trigger_list->channel_key;
850 break;
851 }
852 if (channel_key) {
853 /* The channel key was found stop iteration. */
854 break;
855 }
856 }
857
858 if (!channel_key){
859 /* No channel found; normal exit. */
860 DBG("[notification-thread] No known channel associated with newly subscribed-to condition");
861 ret = 0;
862 goto end;
863 }
864
865 /* Fetch channel info for the matching channel. */
866 cds_lfht_lookup(state->channels_ht,
867 hash_channel_key(channel_key),
868 match_channel_info,
869 channel_key,
870 &iter);
871 node = cds_lfht_iter_get_node(&iter);
872 assert(node);
873 channel_info = caa_container_of(node, struct channel_info,
874 channels_ht_node);
875
876 /* Retrieve the channel's last sample, if it exists. */
877 cds_lfht_lookup(state->channel_state_ht,
878 hash_channel_key(channel_key),
879 match_channel_state_sample,
880 channel_key,
881 &iter);
882 node = cds_lfht_iter_get_node(&iter);
883 if (node) {
884 last_sample = caa_container_of(node,
885 struct channel_state_sample,
886 channel_state_ht_node);
887 } else {
888 /* Nothing to evaluate, no sample was ever taken. Normal exit */
889 DBG("[notification-thread] No channel sample associated with newly subscribed-to condition");
890 ret = 0;
891 goto end;
892 }
893
894 ret = evaluate_buffer_condition(condition, evaluation, state,
895 NULL, last_sample,
896 0, channel_info->session_info->consumed_data_size,
897 channel_info);
898 if (ret) {
899 WARN("[notification-thread] Fatal error occurred while evaluating a newly subscribed-to condition");
900 goto end;
901 }
902
903 *session_uid = channel_info->session_info->uid;
904 *session_gid = channel_info->session_info->gid;
905 end:
906 rcu_read_unlock();
907 return ret;
908 }
909
910 static
911 const char *get_condition_session_name(const struct lttng_condition *condition)
912 {
913 const char *session_name = NULL;
914 enum lttng_condition_status status;
915
916 switch (lttng_condition_get_type(condition)) {
917 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
918 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
919 status = lttng_condition_buffer_usage_get_session_name(
920 condition, &session_name);
921 break;
922 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE:
923 status = lttng_condition_session_consumed_size_get_session_name(
924 condition, &session_name);
925 break;
926 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
927 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
928 status = lttng_condition_session_rotation_get_session_name(
929 condition, &session_name);
930 break;
931 default:
932 abort();
933 }
934 if (status != LTTNG_CONDITION_STATUS_OK) {
935 ERR("[notification-thread] Failed to retrieve session rotation condition's session name");
936 goto end;
937 }
938 end:
939 return session_name;
940 }
941
942 static
943 int evaluate_session_condition_for_client(
944 const struct lttng_condition *condition,
945 struct notification_thread_state *state,
946 struct lttng_evaluation **evaluation,
947 uid_t *session_uid, gid_t *session_gid)
948 {
949 int ret;
950 struct cds_lfht_iter iter;
951 struct cds_lfht_node *node;
952 const char *session_name;
953 struct session_info *session_info = NULL;
954
955 rcu_read_lock();
956 session_name = get_condition_session_name(condition);
957
958 /* Find the session associated with the trigger. */
959 cds_lfht_lookup(state->sessions_ht,
960 hash_key_str(session_name, lttng_ht_seed),
961 match_session,
962 session_name,
963 &iter);
964 node = cds_lfht_iter_get_node(&iter);
965 if (!node) {
966 DBG("[notification-thread] No known session matching name \"%s\"",
967 session_name);
968 ret = 0;
969 goto end;
970 }
971
972 session_info = caa_container_of(node, struct session_info,
973 sessions_ht_node);
974 session_info_get(session_info);
975
976 /*
977 * Evaluation is performed in-line here since only one type of
978 * session-bound condition is handled for the moment.
979 */
980 switch (lttng_condition_get_type(condition)) {
981 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
982 if (!session_info->rotation.ongoing) {
983 ret = 0;
984 goto end_session_put;
985 }
986
987 *evaluation = lttng_evaluation_session_rotation_ongoing_create(
988 session_info->rotation.id);
989 if (!*evaluation) {
990 /* Fatal error. */
991 ERR("[notification-thread] Failed to create session rotation ongoing evaluation for session \"%s\"",
992 session_info->name);
993 ret = -1;
994 goto end_session_put;
995 }
996 ret = 0;
997 break;
998 default:
999 ret = 0;
1000 goto end_session_put;
1001 }
1002
1003 *session_uid = session_info->uid;
1004 *session_gid = session_info->gid;
1005
1006 end_session_put:
1007 session_info_put(session_info);
1008 end:
1009 rcu_read_unlock();
1010 return ret;
1011 }
1012
1013 static
1014 int evaluate_condition_for_client(const struct lttng_trigger *trigger,
1015 const struct lttng_condition *condition,
1016 struct notification_client *client,
1017 struct notification_thread_state *state)
1018 {
1019 int ret;
1020 struct lttng_evaluation *evaluation = NULL;
1021 struct notification_client_list client_list = {
1022 .lock = PTHREAD_MUTEX_INITIALIZER,
1023 };
1024 struct notification_client_list_element client_list_element = { 0 };
1025 uid_t object_uid = 0;
1026 gid_t object_gid = 0;
1027
1028 assert(trigger);
1029 assert(condition);
1030 assert(client);
1031 assert(state);
1032
1033 switch (get_condition_binding_object(condition)) {
1034 case LTTNG_OBJECT_TYPE_SESSION:
1035 ret = evaluate_session_condition_for_client(condition, state,
1036 &evaluation, &object_uid, &object_gid);
1037 break;
1038 case LTTNG_OBJECT_TYPE_CHANNEL:
1039 ret = evaluate_channel_condition_for_client(condition, state,
1040 &evaluation, &object_uid, &object_gid);
1041 break;
1042 case LTTNG_OBJECT_TYPE_NONE:
1043 DBG("[notification-thread] Newly subscribed-to condition not bound to object, nothing to evaluate");
1044 ret = 0;
1045 goto end;
1046 case LTTNG_OBJECT_TYPE_UNKNOWN:
1047 default:
1048 ret = -1;
1049 goto end;
1050 }
1051 if (ret) {
1052 /* Fatal error. */
1053 goto end;
1054 }
1055 if (!evaluation) {
1056 /* Evaluation yielded nothing. Normal exit. */
1057 DBG("[notification-thread] Newly subscribed-to condition evaluated to false, nothing to report to client");
1058 ret = 0;
1059 goto end;
1060 }
1061
1062 /*
1063 * Create a temporary client list with the client currently
1064 * subscribing.
1065 */
1066 cds_lfht_node_init(&client_list.notification_trigger_clients_ht_node);
1067 CDS_INIT_LIST_HEAD(&client_list.clients_list);
1068
1069 CDS_INIT_LIST_HEAD(&client_list_element.node);
1070 client_list_element.client = client;
1071 cds_list_add(&client_list_element.node, &client_list.clients_list);
1072
1073 /* Send evaluation result to the newly-subscribed client. */
1074 DBG("[notification-thread] Newly subscribed-to condition evaluated to true, notifying client");
1075 ret = send_evaluation_to_clients(trigger, evaluation, &client_list,
1076 state, object_uid, object_gid);
1077
1078 end:
1079 return ret;
1080 }
1081
1082 static
1083 int notification_thread_client_subscribe(struct notification_client *client,
1084 struct lttng_condition *condition,
1085 struct notification_thread_state *state,
1086 enum lttng_notification_channel_status *_status)
1087 {
1088 int ret = 0;
1089 struct notification_client_list *client_list = NULL;
1090 struct lttng_condition_list_element *condition_list_element = NULL;
1091 struct notification_client_list_element *client_list_element = NULL;
1092 enum lttng_notification_channel_status status =
1093 LTTNG_NOTIFICATION_CHANNEL_STATUS_OK;
1094
1095 /*
1096 * Ensure that the client has not already subscribed to this condition
1097 * before.
1098 */
1099 cds_list_for_each_entry(condition_list_element, &client->condition_list, node) {
1100 if (lttng_condition_is_equal(condition_list_element->condition,
1101 condition)) {
1102 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ALREADY_SUBSCRIBED;
1103 goto end;
1104 }
1105 }
1106
1107 condition_list_element = zmalloc(sizeof(*condition_list_element));
1108 if (!condition_list_element) {
1109 ret = -1;
1110 goto error;
1111 }
1112 client_list_element = zmalloc(sizeof(*client_list_element));
1113 if (!client_list_element) {
1114 ret = -1;
1115 goto error;
1116 }
1117
1118 /*
1119 * Add the newly-subscribed condition to the client's subscription list.
1120 */
1121 CDS_INIT_LIST_HEAD(&condition_list_element->node);
1122 condition_list_element->condition = condition;
1123 cds_list_add(&condition_list_element->node, &client->condition_list);
1124
1125 client_list = get_client_list_from_condition(state, condition);
1126 if (!client_list) {
1127 /*
1128 * No notification-emiting trigger registered with this
1129 * condition. We don't evaluate the condition right away
1130 * since this trigger is not registered yet.
1131 */
1132 free(client_list_element);
1133 goto end;
1134 }
1135
1136 /*
1137 * The condition to which the client just subscribed is evaluated
1138 * at this point so that conditions that are already TRUE result
1139 * in a notification being sent out.
1140 *
1141 * The client_list's trigger is used without locking the list itself.
1142 * This is correct since the list doesn't own the trigger and the
1143 * object is immutable.
1144 */
1145 struct lttng_trigger_ht_element *trigger_ht_element;
1146 pthread_mutex_lock(&client_list->lock);
1147 cds_list_for_each_entry(trigger_ht_element,
1148 &client_list->triggers_list, client_list_trigger_node) {
1149 if (evaluate_condition_for_client(trigger_ht_element->trigger, condition,
1150 client, state)) {
1151 WARN("[notification-thread] Evaluation of a condition on client subscription failed, aborting.");
1152 ret = -1;
1153 free(client_list_element);
1154 goto end;
1155 }
1156 }
1157 pthread_mutex_unlock(&client_list->lock);
1158
1159 /*
1160 * Add the client to the list of clients interested in a given trigger
1161 * if a "notification" trigger with a corresponding condition was
1162 * added prior.
1163 */
1164 client_list_element->client = client;
1165 CDS_INIT_LIST_HEAD(&client_list_element->node);
1166
1167 pthread_mutex_lock(&client_list->lock);
1168 cds_list_add(&client_list_element->node, &client_list->clients_list);
1169 pthread_mutex_unlock(&client_list->lock);
1170 end:
1171 if (_status) {
1172 *_status = status;
1173 }
1174 if (client_list) {
1175 notification_client_list_put(client_list);
1176 }
1177 return ret;
1178 error:
1179 free(condition_list_element);
1180 free(client_list_element);
1181 return ret;
1182 }
1183
1184 static
1185 int notification_thread_client_unsubscribe(
1186 struct notification_client *client,
1187 struct lttng_condition *condition,
1188 struct notification_thread_state *state,
1189 enum lttng_notification_channel_status *_status)
1190 {
1191 struct notification_client_list *client_list;
1192 struct lttng_condition_list_element *condition_list_element,
1193 *condition_tmp;
1194 struct notification_client_list_element *client_list_element,
1195 *client_tmp;
1196 bool condition_found = false;
1197 enum lttng_notification_channel_status status =
1198 LTTNG_NOTIFICATION_CHANNEL_STATUS_OK;
1199
1200 /* Remove the condition from the client's condition list. */
1201 cds_list_for_each_entry_safe(condition_list_element, condition_tmp,
1202 &client->condition_list, node) {
1203 if (!lttng_condition_is_equal(condition_list_element->condition,
1204 condition)) {
1205 continue;
1206 }
1207
1208 cds_list_del(&condition_list_element->node);
1209 /*
1210 * The caller may be iterating on the client's conditions to
1211 * tear down a client's connection. In this case, the condition
1212 * will be destroyed at the end.
1213 */
1214 if (condition != condition_list_element->condition) {
1215 lttng_condition_destroy(
1216 condition_list_element->condition);
1217 }
1218 free(condition_list_element);
1219 condition_found = true;
1220 break;
1221 }
1222
1223 if (!condition_found) {
1224 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_UNKNOWN_CONDITION;
1225 goto end;
1226 }
1227
1228 /*
1229 * Remove the client from the list of clients interested the trigger
1230 * matching the condition.
1231 */
1232 client_list = get_client_list_from_condition(state, condition);
1233 if (!client_list) {
1234 goto end;
1235 }
1236
1237 pthread_mutex_lock(&client_list->lock);
1238 cds_list_for_each_entry_safe(client_list_element, client_tmp,
1239 &client_list->clients_list, node) {
1240 if (client_list_element->client->id != client->id) {
1241 continue;
1242 }
1243 cds_list_del(&client_list_element->node);
1244 free(client_list_element);
1245 break;
1246 }
1247 pthread_mutex_unlock(&client_list->lock);
1248 notification_client_list_put(client_list);
1249 client_list = NULL;
1250 end:
1251 lttng_condition_destroy(condition);
1252 if (_status) {
1253 *_status = status;
1254 }
1255 return 0;
1256 }
1257
1258 static
1259 void free_notification_client_rcu(struct rcu_head *node)
1260 {
1261 free(caa_container_of(node, struct notification_client, rcu_node));
1262 }
1263
1264 static
1265 void notification_client_destroy(struct notification_client *client,
1266 struct notification_thread_state *state)
1267 {
1268 if (!client) {
1269 return;
1270 }
1271
1272 /*
1273 * The client object is not reachable by other threads, no need to lock
1274 * the client here.
1275 */
1276 if (client->socket >= 0) {
1277 (void) lttcomm_close_unix_sock(client->socket);
1278 client->socket = -1;
1279 }
1280 client->communication.active = false;
1281 lttng_payload_reset(&client->communication.inbound.payload);
1282 lttng_payload_reset(&client->communication.outbound.payload);
1283 pthread_mutex_destroy(&client->lock);
1284 call_rcu(&client->rcu_node, free_notification_client_rcu);
1285 }
1286
1287 /*
1288 * Call with rcu_read_lock held (and hold for the lifetime of the returned
1289 * client pointer).
1290 */
1291 static
1292 struct notification_client *get_client_from_socket(int socket,
1293 struct notification_thread_state *state)
1294 {
1295 struct cds_lfht_iter iter;
1296 struct cds_lfht_node *node;
1297 struct notification_client *client = NULL;
1298
1299 cds_lfht_lookup(state->client_socket_ht,
1300 hash_client_socket(socket),
1301 match_client_socket,
1302 (void *) (unsigned long) socket,
1303 &iter);
1304 node = cds_lfht_iter_get_node(&iter);
1305 if (!node) {
1306 goto end;
1307 }
1308
1309 client = caa_container_of(node, struct notification_client,
1310 client_socket_ht_node);
1311 end:
1312 return client;
1313 }
1314
1315 /*
1316 * Call with rcu_read_lock held (and hold for the lifetime of the returned
1317 * client pointer).
1318 */
1319 static
1320 struct notification_client *get_client_from_id(notification_client_id id,
1321 struct notification_thread_state *state)
1322 {
1323 struct cds_lfht_iter iter;
1324 struct cds_lfht_node *node;
1325 struct notification_client *client = NULL;
1326
1327 cds_lfht_lookup(state->client_id_ht,
1328 hash_client_id(id),
1329 match_client_id,
1330 &id,
1331 &iter);
1332 node = cds_lfht_iter_get_node(&iter);
1333 if (!node) {
1334 goto end;
1335 }
1336
1337 client = caa_container_of(node, struct notification_client,
1338 client_id_ht_node);
1339 end:
1340 return client;
1341 }
1342
1343 static
1344 bool buffer_usage_condition_applies_to_channel(
1345 const struct lttng_condition *condition,
1346 const struct channel_info *channel_info)
1347 {
1348 enum lttng_condition_status status;
1349 enum lttng_domain_type condition_domain;
1350 const char *condition_session_name = NULL;
1351 const char *condition_channel_name = NULL;
1352
1353 status = lttng_condition_buffer_usage_get_domain_type(condition,
1354 &condition_domain);
1355 assert(status == LTTNG_CONDITION_STATUS_OK);
1356 if (channel_info->key.domain != condition_domain) {
1357 goto fail;
1358 }
1359
1360 status = lttng_condition_buffer_usage_get_session_name(
1361 condition, &condition_session_name);
1362 assert((status == LTTNG_CONDITION_STATUS_OK) && condition_session_name);
1363
1364 status = lttng_condition_buffer_usage_get_channel_name(
1365 condition, &condition_channel_name);
1366 assert((status == LTTNG_CONDITION_STATUS_OK) && condition_channel_name);
1367
1368 if (strcmp(channel_info->session_info->name, condition_session_name)) {
1369 goto fail;
1370 }
1371 if (strcmp(channel_info->name, condition_channel_name)) {
1372 goto fail;
1373 }
1374
1375 return true;
1376 fail:
1377 return false;
1378 }
1379
1380 static
1381 bool session_consumed_size_condition_applies_to_channel(
1382 const struct lttng_condition *condition,
1383 const struct channel_info *channel_info)
1384 {
1385 enum lttng_condition_status status;
1386 const char *condition_session_name = NULL;
1387
1388 status = lttng_condition_session_consumed_size_get_session_name(
1389 condition, &condition_session_name);
1390 assert((status == LTTNG_CONDITION_STATUS_OK) && condition_session_name);
1391
1392 if (strcmp(channel_info->session_info->name, condition_session_name)) {
1393 goto fail;
1394 }
1395
1396 return true;
1397 fail:
1398 return false;
1399 }
1400
1401 static
1402 bool trigger_applies_to_channel(const struct lttng_trigger *trigger,
1403 const struct channel_info *channel_info)
1404 {
1405 const struct lttng_condition *condition;
1406 bool trigger_applies;
1407
1408 condition = lttng_trigger_get_const_condition(trigger);
1409 if (!condition) {
1410 goto fail;
1411 }
1412
1413 switch (lttng_condition_get_type(condition)) {
1414 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
1415 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
1416 trigger_applies = buffer_usage_condition_applies_to_channel(
1417 condition, channel_info);
1418 break;
1419 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE:
1420 trigger_applies = session_consumed_size_condition_applies_to_channel(
1421 condition, channel_info);
1422 break;
1423 default:
1424 goto fail;
1425 }
1426
1427 return trigger_applies;
1428 fail:
1429 return false;
1430 }
1431
1432 /* Must be called with RCU read lock held. */
1433 static
1434 struct lttng_session_trigger_list *get_session_trigger_list(
1435 struct notification_thread_state *state,
1436 const char *session_name)
1437 {
1438 struct lttng_session_trigger_list *list = NULL;
1439 struct cds_lfht_node *node;
1440 struct cds_lfht_iter iter;
1441
1442 cds_lfht_lookup(state->session_triggers_ht,
1443 hash_key_str(session_name, lttng_ht_seed),
1444 match_session_trigger_list,
1445 session_name,
1446 &iter);
1447 node = cds_lfht_iter_get_node(&iter);
1448 if (!node) {
1449 /*
1450 * Not an error, the list of triggers applying to that session
1451 * will be initialized when the session is created.
1452 */
1453 DBG("[notification-thread] No trigger list found for session \"%s\" as it is not yet known to the notification system",
1454 session_name);
1455 goto end;
1456 }
1457
1458 list = caa_container_of(node,
1459 struct lttng_session_trigger_list,
1460 session_triggers_ht_node);
1461 end:
1462 return list;
1463 }
1464
1465 /*
1466 * Allocate an empty lttng_session_trigger_list for the session named
1467 * 'session_name'.
1468 *
1469 * No ownership of 'session_name' is assumed by the session trigger list.
1470 * It is the caller's responsability to ensure the session name is alive
1471 * for as long as this list is.
1472 */
1473 static
1474 struct lttng_session_trigger_list *lttng_session_trigger_list_create(
1475 const char *session_name,
1476 struct cds_lfht *session_triggers_ht)
1477 {
1478 struct lttng_session_trigger_list *list;
1479
1480 list = zmalloc(sizeof(*list));
1481 if (!list) {
1482 goto end;
1483 }
1484 list->session_name = session_name;
1485 CDS_INIT_LIST_HEAD(&list->list);
1486 cds_lfht_node_init(&list->session_triggers_ht_node);
1487 list->session_triggers_ht = session_triggers_ht;
1488
1489 rcu_read_lock();
1490 /* Publish the list through the session_triggers_ht. */
1491 cds_lfht_add(session_triggers_ht,
1492 hash_key_str(session_name, lttng_ht_seed),
1493 &list->session_triggers_ht_node);
1494 rcu_read_unlock();
1495 end:
1496 return list;
1497 }
1498
1499 static
1500 void free_session_trigger_list_rcu(struct rcu_head *node)
1501 {
1502 free(caa_container_of(node, struct lttng_session_trigger_list,
1503 rcu_node));
1504 }
1505
1506 static
1507 void lttng_session_trigger_list_destroy(struct lttng_session_trigger_list *list)
1508 {
1509 struct lttng_trigger_list_element *trigger_list_element, *tmp;
1510
1511 /* Empty the list element by element, and then free the list itself. */
1512 cds_list_for_each_entry_safe(trigger_list_element, tmp,
1513 &list->list, node) {
1514 cds_list_del(&trigger_list_element->node);
1515 free(trigger_list_element);
1516 }
1517 rcu_read_lock();
1518 /* Unpublish the list from the session_triggers_ht. */
1519 cds_lfht_del(list->session_triggers_ht,
1520 &list->session_triggers_ht_node);
1521 rcu_read_unlock();
1522 call_rcu(&list->rcu_node, free_session_trigger_list_rcu);
1523 }
1524
1525 static
1526 int lttng_session_trigger_list_add(struct lttng_session_trigger_list *list,
1527 struct lttng_trigger *trigger)
1528 {
1529 int ret = 0;
1530 struct lttng_trigger_list_element *new_element =
1531 zmalloc(sizeof(*new_element));
1532
1533 if (!new_element) {
1534 ret = -1;
1535 goto end;
1536 }
1537 CDS_INIT_LIST_HEAD(&new_element->node);
1538 new_element->trigger = trigger;
1539 cds_list_add(&new_element->node, &list->list);
1540 end:
1541 return ret;
1542 }
1543
1544 static
1545 bool trigger_applies_to_session(const struct lttng_trigger *trigger,
1546 const char *session_name)
1547 {
1548 bool applies = false;
1549 const struct lttng_condition *condition;
1550
1551 condition = lttng_trigger_get_const_condition(trigger);
1552 switch (lttng_condition_get_type(condition)) {
1553 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
1554 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
1555 {
1556 enum lttng_condition_status condition_status;
1557 const char *condition_session_name;
1558
1559 condition_status = lttng_condition_session_rotation_get_session_name(
1560 condition, &condition_session_name);
1561 if (condition_status != LTTNG_CONDITION_STATUS_OK) {
1562 ERR("[notification-thread] Failed to retrieve session rotation condition's session name");
1563 goto end;
1564 }
1565
1566 assert(condition_session_name);
1567 applies = !strcmp(condition_session_name, session_name);
1568 break;
1569 }
1570 default:
1571 goto end;
1572 }
1573 end:
1574 return applies;
1575 }
1576
1577 /*
1578 * Allocate and initialize an lttng_session_trigger_list which contains
1579 * all triggers that apply to the session named 'session_name'.
1580 *
1581 * No ownership of 'session_name' is assumed by the session trigger list.
1582 * It is the caller's responsability to ensure the session name is alive
1583 * for as long as this list is.
1584 */
1585 static
1586 struct lttng_session_trigger_list *lttng_session_trigger_list_build(
1587 const struct notification_thread_state *state,
1588 const char *session_name)
1589 {
1590 int trigger_count = 0;
1591 struct lttng_session_trigger_list *session_trigger_list = NULL;
1592 struct lttng_trigger_ht_element *trigger_ht_element = NULL;
1593 struct cds_lfht_iter iter;
1594
1595 session_trigger_list = lttng_session_trigger_list_create(session_name,
1596 state->session_triggers_ht);
1597
1598 /* Add all triggers applying to the session named 'session_name'. */
1599 cds_lfht_for_each_entry(state->triggers_ht, &iter, trigger_ht_element,
1600 node) {
1601 int ret;
1602
1603 if (!trigger_applies_to_session(trigger_ht_element->trigger,
1604 session_name)) {
1605 continue;
1606 }
1607
1608 ret = lttng_session_trigger_list_add(session_trigger_list,
1609 trigger_ht_element->trigger);
1610 if (ret) {
1611 goto error;
1612 }
1613
1614 trigger_count++;
1615 }
1616
1617 DBG("[notification-thread] Found %i triggers that apply to newly created session",
1618 trigger_count);
1619 return session_trigger_list;
1620 error:
1621 lttng_session_trigger_list_destroy(session_trigger_list);
1622 return NULL;
1623 }
1624
1625 static
1626 struct session_info *find_or_create_session_info(
1627 struct notification_thread_state *state,
1628 const char *name, uid_t uid, gid_t gid)
1629 {
1630 struct session_info *session = NULL;
1631 struct cds_lfht_node *node;
1632 struct cds_lfht_iter iter;
1633 struct lttng_session_trigger_list *trigger_list;
1634
1635 rcu_read_lock();
1636 cds_lfht_lookup(state->sessions_ht,
1637 hash_key_str(name, lttng_ht_seed),
1638 match_session,
1639 name,
1640 &iter);
1641 node = cds_lfht_iter_get_node(&iter);
1642 if (node) {
1643 DBG("[notification-thread] Found session info of session \"%s\" (uid = %i, gid = %i)",
1644 name, uid, gid);
1645 session = caa_container_of(node, struct session_info,
1646 sessions_ht_node);
1647 assert(session->uid == uid);
1648 assert(session->gid == gid);
1649 session_info_get(session);
1650 goto end;
1651 }
1652
1653 trigger_list = lttng_session_trigger_list_build(state, name);
1654 if (!trigger_list) {
1655 goto error;
1656 }
1657
1658 session = session_info_create(name, uid, gid, trigger_list,
1659 state->sessions_ht);
1660 if (!session) {
1661 ERR("[notification-thread] Failed to allocation session info for session \"%s\" (uid = %i, gid = %i)",
1662 name, uid, gid);
1663 lttng_session_trigger_list_destroy(trigger_list);
1664 goto error;
1665 }
1666 trigger_list = NULL;
1667
1668 cds_lfht_add(state->sessions_ht, hash_key_str(name, lttng_ht_seed),
1669 &session->sessions_ht_node);
1670 end:
1671 rcu_read_unlock();
1672 return session;
1673 error:
1674 rcu_read_unlock();
1675 session_info_put(session);
1676 return NULL;
1677 }
1678
1679 static
1680 int handle_notification_thread_command_add_channel(
1681 struct notification_thread_state *state,
1682 const char *session_name, uid_t session_uid, gid_t session_gid,
1683 const char *channel_name, enum lttng_domain_type channel_domain,
1684 uint64_t channel_key_int, uint64_t channel_capacity,
1685 enum lttng_error_code *cmd_result)
1686 {
1687 struct cds_list_head trigger_list;
1688 struct channel_info *new_channel_info = NULL;
1689 struct channel_key channel_key = {
1690 .key = channel_key_int,
1691 .domain = channel_domain,
1692 };
1693 struct lttng_channel_trigger_list *channel_trigger_list = NULL;
1694 struct lttng_trigger_ht_element *trigger_ht_element = NULL;
1695 int trigger_count = 0;
1696 struct cds_lfht_iter iter;
1697 struct session_info *session_info = NULL;
1698
1699 DBG("[notification-thread] Adding channel %s from session %s, channel key = %" PRIu64 " in %s domain",
1700 channel_name, session_name, channel_key_int,
1701 lttng_domain_type_str(channel_domain));
1702
1703 CDS_INIT_LIST_HEAD(&trigger_list);
1704
1705 session_info = find_or_create_session_info(state, session_name,
1706 session_uid, session_gid);
1707 if (!session_info) {
1708 /* Allocation error or an internal error occurred. */
1709 goto error;
1710 }
1711
1712 new_channel_info = channel_info_create(channel_name, &channel_key,
1713 channel_capacity, session_info);
1714 if (!new_channel_info) {
1715 goto error;
1716 }
1717
1718 rcu_read_lock();
1719 /* Build a list of all triggers applying to the new channel. */
1720 cds_lfht_for_each_entry(state->triggers_ht, &iter, trigger_ht_element,
1721 node) {
1722 struct lttng_trigger_list_element *new_element;
1723
1724 if (!trigger_applies_to_channel(trigger_ht_element->trigger,
1725 new_channel_info)) {
1726 continue;
1727 }
1728
1729 new_element = zmalloc(sizeof(*new_element));
1730 if (!new_element) {
1731 rcu_read_unlock();
1732 goto error;
1733 }
1734 CDS_INIT_LIST_HEAD(&new_element->node);
1735 new_element->trigger = trigger_ht_element->trigger;
1736 cds_list_add(&new_element->node, &trigger_list);
1737 trigger_count++;
1738 }
1739 rcu_read_unlock();
1740
1741 DBG("[notification-thread] Found %i triggers that apply to newly added channel",
1742 trigger_count);
1743 channel_trigger_list = zmalloc(sizeof(*channel_trigger_list));
1744 if (!channel_trigger_list) {
1745 goto error;
1746 }
1747 channel_trigger_list->channel_key = new_channel_info->key;
1748 CDS_INIT_LIST_HEAD(&channel_trigger_list->list);
1749 cds_lfht_node_init(&channel_trigger_list->channel_triggers_ht_node);
1750 cds_list_splice(&trigger_list, &channel_trigger_list->list);
1751
1752 rcu_read_lock();
1753 /* Add channel to the channel_ht which owns the channel_infos. */
1754 cds_lfht_add(state->channels_ht,
1755 hash_channel_key(&new_channel_info->key),
1756 &new_channel_info->channels_ht_node);
1757 /*
1758 * Add the list of triggers associated with this channel to the
1759 * channel_triggers_ht.
1760 */
1761 cds_lfht_add(state->channel_triggers_ht,
1762 hash_channel_key(&new_channel_info->key),
1763 &channel_trigger_list->channel_triggers_ht_node);
1764 rcu_read_unlock();
1765 session_info_put(session_info);
1766 *cmd_result = LTTNG_OK;
1767 return 0;
1768 error:
1769 channel_info_destroy(new_channel_info);
1770 session_info_put(session_info);
1771 return 1;
1772 }
1773
1774 static
1775 void free_channel_trigger_list_rcu(struct rcu_head *node)
1776 {
1777 free(caa_container_of(node, struct lttng_channel_trigger_list,
1778 rcu_node));
1779 }
1780
1781 static
1782 void free_channel_state_sample_rcu(struct rcu_head *node)
1783 {
1784 free(caa_container_of(node, struct channel_state_sample,
1785 rcu_node));
1786 }
1787
1788 static
1789 int handle_notification_thread_command_remove_channel(
1790 struct notification_thread_state *state,
1791 uint64_t channel_key, enum lttng_domain_type domain,
1792 enum lttng_error_code *cmd_result)
1793 {
1794 struct cds_lfht_node *node;
1795 struct cds_lfht_iter iter;
1796 struct lttng_channel_trigger_list *trigger_list;
1797 struct lttng_trigger_list_element *trigger_list_element, *tmp;
1798 struct channel_key key = { .key = channel_key, .domain = domain };
1799 struct channel_info *channel_info;
1800
1801 DBG("[notification-thread] Removing channel key = %" PRIu64 " in %s domain",
1802 channel_key, lttng_domain_type_str(domain));
1803
1804 rcu_read_lock();
1805
1806 cds_lfht_lookup(state->channel_triggers_ht,
1807 hash_channel_key(&key),
1808 match_channel_trigger_list,
1809 &key,
1810 &iter);
1811 node = cds_lfht_iter_get_node(&iter);
1812 /*
1813 * There is a severe internal error if we are being asked to remove a
1814 * channel that doesn't exist.
1815 */
1816 if (!node) {
1817 ERR("[notification-thread] Channel being removed is unknown to the notification thread");
1818 goto end;
1819 }
1820
1821 /* Free the list of triggers associated with this channel. */
1822 trigger_list = caa_container_of(node, struct lttng_channel_trigger_list,
1823 channel_triggers_ht_node);
1824 cds_list_for_each_entry_safe(trigger_list_element, tmp,
1825 &trigger_list->list, node) {
1826 cds_list_del(&trigger_list_element->node);
1827 free(trigger_list_element);
1828 }
1829 cds_lfht_del(state->channel_triggers_ht, node);
1830 call_rcu(&trigger_list->rcu_node, free_channel_trigger_list_rcu);
1831
1832 /* Free sampled channel state. */
1833 cds_lfht_lookup(state->channel_state_ht,
1834 hash_channel_key(&key),
1835 match_channel_state_sample,
1836 &key,
1837 &iter);
1838 node = cds_lfht_iter_get_node(&iter);
1839 /*
1840 * This is expected to be NULL if the channel is destroyed before we
1841 * received a sample.
1842 */
1843 if (node) {
1844 struct channel_state_sample *sample = caa_container_of(node,
1845 struct channel_state_sample,
1846 channel_state_ht_node);
1847
1848 cds_lfht_del(state->channel_state_ht, node);
1849 call_rcu(&sample->rcu_node, free_channel_state_sample_rcu);
1850 }
1851
1852 /* Remove the channel from the channels_ht and free it. */
1853 cds_lfht_lookup(state->channels_ht,
1854 hash_channel_key(&key),
1855 match_channel_info,
1856 &key,
1857 &iter);
1858 node = cds_lfht_iter_get_node(&iter);
1859 assert(node);
1860 channel_info = caa_container_of(node, struct channel_info,
1861 channels_ht_node);
1862 cds_lfht_del(state->channels_ht, node);
1863 channel_info_destroy(channel_info);
1864 end:
1865 rcu_read_unlock();
1866 *cmd_result = LTTNG_OK;
1867 return 0;
1868 }
1869
1870 static
1871 int handle_notification_thread_command_session_rotation(
1872 struct notification_thread_state *state,
1873 enum notification_thread_command_type cmd_type,
1874 const char *session_name, uid_t session_uid, gid_t session_gid,
1875 uint64_t trace_archive_chunk_id,
1876 struct lttng_trace_archive_location *location,
1877 enum lttng_error_code *_cmd_result)
1878 {
1879 int ret = 0;
1880 enum lttng_error_code cmd_result = LTTNG_OK;
1881 struct lttng_session_trigger_list *trigger_list;
1882 struct lttng_trigger_list_element *trigger_list_element;
1883 struct session_info *session_info;
1884 const struct lttng_credentials session_creds = {
1885 .uid = LTTNG_OPTIONAL_INIT_VALUE(session_uid),
1886 .gid = LTTNG_OPTIONAL_INIT_VALUE(session_gid),
1887 };
1888
1889 rcu_read_lock();
1890
1891 session_info = find_or_create_session_info(state, session_name,
1892 session_uid, session_gid);
1893 if (!session_info) {
1894 /* Allocation error or an internal error occurred. */
1895 ret = -1;
1896 cmd_result = LTTNG_ERR_NOMEM;
1897 goto end;
1898 }
1899
1900 session_info->rotation.ongoing =
1901 cmd_type == NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_ONGOING;
1902 session_info->rotation.id = trace_archive_chunk_id;
1903 trigger_list = get_session_trigger_list(state, session_name);
1904 if (!trigger_list) {
1905 DBG("[notification-thread] No triggers applying to session \"%s\" found",
1906 session_name);
1907 goto end;
1908 }
1909
1910 cds_list_for_each_entry(trigger_list_element, &trigger_list->list,
1911 node) {
1912 const struct lttng_condition *condition;
1913 struct lttng_trigger *trigger;
1914 struct notification_client_list *client_list;
1915 struct lttng_evaluation *evaluation = NULL;
1916 enum lttng_condition_type condition_type;
1917 enum action_executor_status executor_status;
1918
1919 trigger = trigger_list_element->trigger;
1920 condition = lttng_trigger_get_const_condition(trigger);
1921 assert(condition);
1922 condition_type = lttng_condition_get_type(condition);
1923
1924 if (condition_type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING &&
1925 cmd_type != NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_ONGOING) {
1926 continue;
1927 } else if (condition_type == LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED &&
1928 cmd_type != NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_COMPLETED) {
1929 continue;
1930 }
1931
1932 client_list = get_client_list_from_condition(state, condition);
1933 if (cmd_type == NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_ONGOING) {
1934 evaluation = lttng_evaluation_session_rotation_ongoing_create(
1935 trace_archive_chunk_id);
1936 } else {
1937 evaluation = lttng_evaluation_session_rotation_completed_create(
1938 trace_archive_chunk_id, location);
1939 }
1940
1941 if (!evaluation) {
1942 /* Internal error */
1943 ret = -1;
1944 cmd_result = LTTNG_ERR_UNK;
1945 goto put_list;
1946 }
1947
1948 /*
1949 * Ownership of `evaluation` transferred to the action executor
1950 * no matter the result.
1951 */
1952 executor_status = action_executor_enqueue(state->executor,
1953 trigger, evaluation, &session_creds,
1954 client_list);
1955 evaluation = NULL;
1956 switch (executor_status) {
1957 case ACTION_EXECUTOR_STATUS_OK:
1958 break;
1959 case ACTION_EXECUTOR_STATUS_ERROR:
1960 case ACTION_EXECUTOR_STATUS_INVALID:
1961 /*
1962 * TODO Add trigger identification (name/id) when
1963 * it is added to the API.
1964 */
1965 ERR("Fatal error occurred while enqueuing action associated with session rotation trigger");
1966 ret = -1;
1967 goto put_list;
1968 case ACTION_EXECUTOR_STATUS_OVERFLOW:
1969 /*
1970 * TODO Add trigger identification (name/id) when
1971 * it is added to the API.
1972 *
1973 * Not a fatal error.
1974 */
1975 WARN("No space left when enqueuing action associated with session rotation trigger");
1976 ret = 0;
1977 goto put_list;
1978 default:
1979 abort();
1980 }
1981
1982 put_list:
1983 notification_client_list_put(client_list);
1984 if (caa_unlikely(ret)) {
1985 break;
1986 }
1987 }
1988 end:
1989 session_info_put(session_info);
1990 *_cmd_result = cmd_result;
1991 rcu_read_unlock();
1992 return ret;
1993 }
1994
1995 static
1996 int handle_notification_thread_command_add_tracer_event_source(
1997 struct notification_thread_state *state,
1998 int tracer_event_source_fd,
1999 enum lttng_domain_type domain_type,
2000 enum lttng_error_code *_cmd_result)
2001 {
2002 int ret = 0;
2003 enum lttng_error_code cmd_result = LTTNG_OK;
2004 struct notification_event_tracer_event_source_element *element = NULL;
2005
2006 element = zmalloc(sizeof(*element));
2007 if (!element) {
2008 cmd_result = LTTNG_ERR_NOMEM;
2009 ret = -1;
2010 goto end;
2011 }
2012
2013 element->fd = tracer_event_source_fd;
2014 element->domain = domain_type;
2015
2016 cds_list_add(&element->node, &state->tracer_event_sources_list);
2017
2018 DBG3("[notification-thread] Adding tracer event source fd to poll set: tracer_event_source_fd = %d, domain = '%s'",
2019 tracer_event_source_fd,
2020 lttng_domain_type_str(domain_type));
2021
2022 /* Adding the read side pipe to the event poll. */
2023 ret = lttng_poll_add(&state->events, tracer_event_source_fd, LPOLLIN | LPOLLERR);
2024 if (ret < 0) {
2025 ERR("[notification-thread] Failed to add tracer event source to poll set: tracer_event_source_fd = %d, domain = '%s'",
2026 tracer_event_source_fd,
2027 lttng_domain_type_str(element->domain));
2028 cds_list_del(&element->node);
2029 free(element);
2030 goto end;
2031 }
2032
2033 element->is_fd_in_poll_set = true;
2034
2035 end:
2036 *_cmd_result = cmd_result;
2037 return ret;
2038 }
2039
2040 static
2041 int drain_event_notifier_notification_pipe(
2042 struct notification_thread_state *state,
2043 int pipe, enum lttng_domain_type domain)
2044 {
2045 struct lttng_poll_event events = {0};
2046 int ret;
2047
2048 ret = lttng_poll_create(&events, 1, LTTNG_CLOEXEC);
2049 if (ret < 0) {
2050 ERR("[notification-thread] Error creating lttng_poll_event");
2051 goto end;
2052 }
2053
2054 ret = lttng_poll_add(&events, pipe, LPOLLIN);
2055 if (ret < 0) {
2056 ERR("[notification-thread] Error adding fd event notifier notification pipe to lttng_poll_event: fd = %d",
2057 pipe);
2058 goto end;
2059 }
2060
2061 while (true) {
2062 /*
2063 * Continue to consume notifications as long as there are new
2064 * ones coming in. The tracer has been asked to stop producing
2065 * them.
2066 *
2067 * LPOLLIN is explicitly checked since LPOLLHUP is implicitly
2068 * monitored (on Linux, at least) and will be returned when
2069 * the pipe is closed but empty.
2070 */
2071 ret = lttng_poll_wait_interruptible(&events, 0);
2072 if (ret == 0 || (LTTNG_POLL_GETEV(&events, 0) & LPOLLIN) == 0) {
2073 /* No more notification to be read on this pipe. */
2074 ret = 0;
2075 goto end;
2076 } else if (ret < 0) {
2077 PERROR("Failed on lttng_poll_wait_interruptible() call");
2078 ret = -1;
2079 goto end;
2080 }
2081
2082 ret = handle_one_event_notifier_notification(state, pipe, domain);
2083 if (ret) {
2084 ERR("[notification-thread] Error consuming an event notifier notification from pipe: fd = %d",
2085 pipe);
2086 }
2087 }
2088 end:
2089 lttng_poll_clean(&events);
2090 return ret;
2091 }
2092
2093 static
2094 int handle_notification_thread_command_remove_tracer_event_source(
2095 struct notification_thread_state *state,
2096 int tracer_event_source_fd,
2097 enum lttng_error_code *_cmd_result)
2098 {
2099 int ret = 0;
2100 bool found = false;
2101 enum lttng_error_code cmd_result = LTTNG_OK;
2102 struct notification_event_tracer_event_source_element *source_element = NULL, *tmp;
2103
2104 cds_list_for_each_entry_safe(source_element, tmp,
2105 &state->tracer_event_sources_list, node) {
2106 if (source_element->fd != tracer_event_source_fd) {
2107 continue;
2108 }
2109
2110 DBG("[notification-thread] Removed tracer event source from poll set: tracer_event_source_fd = %d, domain = '%s'",
2111 tracer_event_source_fd,
2112 lttng_domain_type_str(source_element->domain));
2113 cds_list_del(&source_element->node);
2114 found = true;
2115 break;
2116 }
2117
2118 if (!found) {
2119 /*
2120 * This is temporarily allowed since the poll activity set is
2121 * not properly cleaned-up for the moment. This is adressed in
2122 * an upcoming fix.
2123 */
2124 source_element = NULL;
2125 goto end;
2126 }
2127
2128 if (!source_element->is_fd_in_poll_set) {
2129 /* Skip the poll set removal. */
2130 goto end;
2131 }
2132
2133 DBG3("[notification-thread] Removing tracer event source from poll set: tracer_event_source_fd = %d, domain = '%s'",
2134 tracer_event_source_fd,
2135 lttng_domain_type_str(source_element->domain));
2136
2137 /* Removing the fd from the event poll set. */
2138 ret = lttng_poll_del(&state->events, tracer_event_source_fd);
2139 if (ret < 0) {
2140 ERR("[notification-thread] Failed to remove tracer event source from poll set: tracer_event_source_fd = %d, domain = '%s'",
2141 tracer_event_source_fd,
2142 lttng_domain_type_str(source_element->domain));
2143 cmd_result = LTTNG_ERR_FATAL;
2144 goto end;
2145 }
2146
2147 source_element->is_fd_in_poll_set = false;
2148
2149 ret = drain_event_notifier_notification_pipe(state, tracer_event_source_fd,
2150 source_element->domain);
2151 if (ret) {
2152 ERR("[notification-thread] Error draining event notifier notification: tracer_event_source_fd = %d, domain = %s",
2153 tracer_event_source_fd,
2154 lttng_domain_type_str(source_element->domain));
2155 cmd_result = LTTNG_ERR_FATAL;
2156 goto end;
2157 }
2158
2159 /*
2160 * The drain_event_notifier_notification_pipe() call might have read
2161 * data from an fd that we received in event in the latest _poll_wait()
2162 * call. Make sure the thread call poll_wait() again to ensure we have
2163 * a clean state.
2164 */
2165 state->restart_poll = true;
2166
2167 end:
2168 free(source_element);
2169 *_cmd_result = cmd_result;
2170 return ret;
2171 }
2172
2173 static
2174 int condition_on_event_update_error_count(struct lttng_trigger *trigger)
2175 {
2176 int ret = 0;
2177 uint64_t error_count = 0;
2178 struct lttng_condition *condition;
2179 enum event_notifier_error_accounting_status status;
2180
2181 condition = lttng_trigger_get_condition(trigger);
2182 assert(lttng_condition_get_type(condition) ==
2183 LTTNG_CONDITION_TYPE_ON_EVENT);
2184
2185 status = event_notifier_error_accounting_get_count(trigger, &error_count);
2186 if (status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
2187 uid_t trigger_owner_uid;
2188 const char *trigger_name;
2189 const enum lttng_trigger_status trigger_status =
2190 lttng_trigger_get_owner_uid(
2191 trigger, &trigger_owner_uid);
2192
2193 assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
2194 if (lttng_trigger_get_name(trigger, &trigger_name) != LTTNG_TRIGGER_STATUS_OK) {
2195 trigger_name = "(unnamed)";
2196 }
2197
2198 ERR("Failed to get event notifier error count of trigger for update: trigger owner = %d, trigger name = '%s'",
2199 trigger_owner_uid, trigger_name);
2200 ret = -1;
2201 }
2202
2203 lttng_condition_on_event_set_error_count(condition, error_count);
2204 return ret;
2205 }
2206
2207 int handle_notification_thread_remove_tracer_event_source_no_result(
2208 struct notification_thread_state *state,
2209 int tracer_event_source_fd)
2210 {
2211 int ret;
2212 enum lttng_error_code cmd_result;
2213
2214 ret = handle_notification_thread_command_remove_tracer_event_source(
2215 state, tracer_event_source_fd, &cmd_result);
2216 (void) cmd_result;
2217 return ret;
2218 }
2219
2220 static int handle_notification_thread_command_list_triggers(
2221 struct notification_thread_handle *handle,
2222 struct notification_thread_state *state,
2223 uid_t client_uid,
2224 struct lttng_triggers **triggers,
2225 enum lttng_error_code *_cmd_result)
2226 {
2227 int ret = 0;
2228 enum lttng_error_code cmd_result = LTTNG_OK;
2229 struct cds_lfht_iter iter;
2230 struct lttng_trigger_ht_element *trigger_ht_element;
2231 struct lttng_triggers *local_triggers = NULL;
2232 const struct lttng_credentials *creds;
2233
2234 rcu_read_lock();
2235
2236 local_triggers = lttng_triggers_create();
2237 if (!local_triggers) {
2238 /* Not a fatal error. */
2239 cmd_result = LTTNG_ERR_NOMEM;
2240 goto end;
2241 }
2242
2243 cds_lfht_for_each_entry(state->triggers_ht, &iter,
2244 trigger_ht_element, node) {
2245 /*
2246 * Only return the triggers to which the client has access.
2247 * The root user has visibility over all triggers.
2248 */
2249 creds = lttng_trigger_get_credentials(trigger_ht_element->trigger);
2250 if (client_uid != lttng_credentials_get_uid(creds) && client_uid != 0) {
2251 continue;
2252 }
2253
2254 if (lttng_trigger_needs_tracer_notifier(trigger_ht_element->trigger)) {
2255 ret = condition_on_event_update_error_count(
2256 trigger_ht_element->trigger);
2257 assert(!ret);
2258 }
2259
2260 ret = lttng_triggers_add(local_triggers,
2261 trigger_ht_element->trigger);
2262 if (ret < 0) {
2263 /* Not a fatal error. */
2264 ret = 0;
2265 cmd_result = LTTNG_ERR_NOMEM;
2266 goto end;
2267 }
2268 }
2269
2270 /* Transferring ownership to the caller. */
2271 *triggers = local_triggers;
2272 local_triggers = NULL;
2273
2274 end:
2275 rcu_read_unlock();
2276 lttng_triggers_destroy(local_triggers);
2277 *_cmd_result = cmd_result;
2278 return ret;
2279 }
2280
2281 static
2282 bool condition_is_supported(struct lttng_condition *condition)
2283 {
2284 bool is_supported;
2285
2286 switch (lttng_condition_get_type(condition)) {
2287 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
2288 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
2289 {
2290 int ret;
2291 enum lttng_domain_type domain;
2292
2293 ret = lttng_condition_buffer_usage_get_domain_type(condition,
2294 &domain);
2295 assert(ret == 0);
2296
2297 if (domain != LTTNG_DOMAIN_KERNEL) {
2298 is_supported = true;
2299 goto end;
2300 }
2301
2302 /*
2303 * Older kernel tracers don't expose the API to monitor their
2304 * buffers. Therefore, we reject triggers that require that
2305 * mechanism to be available to be evaluated.
2306 *
2307 * Assume unsupported on error.
2308 */
2309 is_supported = kernel_supports_ring_buffer_snapshot_sample_positions() == 1;
2310 break;
2311 }
2312 case LTTNG_CONDITION_TYPE_ON_EVENT:
2313 {
2314 const struct lttng_event_rule *event_rule;
2315 enum lttng_domain_type domain;
2316 const enum lttng_condition_status status =
2317 lttng_condition_on_event_get_rule(
2318 condition, &event_rule);
2319
2320 assert(status == LTTNG_CONDITION_STATUS_OK);
2321
2322 domain = lttng_event_rule_get_domain_type(event_rule);
2323 if (domain != LTTNG_DOMAIN_KERNEL) {
2324 is_supported = true;
2325 goto end;
2326 }
2327
2328 /*
2329 * Older kernel tracers can't emit notification. Therefore, we
2330 * reject triggers that require that mechanism to be available
2331 * to be evaluated.
2332 *
2333 * Assume unsupported on error.
2334 */
2335 is_supported = kernel_supports_event_notifiers() == 1;
2336 break;
2337 }
2338 default:
2339 is_supported = true;
2340 }
2341 end:
2342 return is_supported;
2343 }
2344
2345 /* Must be called with RCU read lock held. */
2346 static
2347 int bind_trigger_to_matching_session(struct lttng_trigger *trigger,
2348 struct notification_thread_state *state)
2349 {
2350 int ret = 0;
2351 const struct lttng_condition *condition;
2352 const char *session_name;
2353 struct lttng_session_trigger_list *trigger_list;
2354
2355 condition = lttng_trigger_get_const_condition(trigger);
2356 switch (lttng_condition_get_type(condition)) {
2357 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
2358 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
2359 {
2360 enum lttng_condition_status status;
2361
2362 status = lttng_condition_session_rotation_get_session_name(
2363 condition, &session_name);
2364 if (status != LTTNG_CONDITION_STATUS_OK) {
2365 ERR("[notification-thread] Failed to bind trigger to session: unable to get 'session_rotation' condition's session name");
2366 ret = -1;
2367 goto end;
2368 }
2369 break;
2370 }
2371 default:
2372 ret = -1;
2373 goto end;
2374 }
2375
2376 trigger_list = get_session_trigger_list(state, session_name);
2377 if (!trigger_list) {
2378 DBG("[notification-thread] Unable to bind trigger applying to session \"%s\" as it is not yet known to the notification system",
2379 session_name);
2380 goto end;
2381
2382 }
2383
2384 DBG("[notification-thread] Newly registered trigger bound to session \"%s\"",
2385 session_name);
2386 ret = lttng_session_trigger_list_add(trigger_list, trigger);
2387 end:
2388 return ret;
2389 }
2390
2391 /* Must be called with RCU read lock held. */
2392 static
2393 int bind_trigger_to_matching_channels(struct lttng_trigger *trigger,
2394 struct notification_thread_state *state)
2395 {
2396 int ret = 0;
2397 struct cds_lfht_node *node;
2398 struct cds_lfht_iter iter;
2399 struct channel_info *channel;
2400
2401 cds_lfht_for_each_entry(state->channels_ht, &iter, channel,
2402 channels_ht_node) {
2403 struct lttng_trigger_list_element *trigger_list_element;
2404 struct lttng_channel_trigger_list *trigger_list;
2405 struct cds_lfht_iter lookup_iter;
2406
2407 if (!trigger_applies_to_channel(trigger, channel)) {
2408 continue;
2409 }
2410
2411 cds_lfht_lookup(state->channel_triggers_ht,
2412 hash_channel_key(&channel->key),
2413 match_channel_trigger_list,
2414 &channel->key,
2415 &lookup_iter);
2416 node = cds_lfht_iter_get_node(&lookup_iter);
2417 assert(node);
2418 trigger_list = caa_container_of(node,
2419 struct lttng_channel_trigger_list,
2420 channel_triggers_ht_node);
2421
2422 trigger_list_element = zmalloc(sizeof(*trigger_list_element));
2423 if (!trigger_list_element) {
2424 ret = -1;
2425 goto end;
2426 }
2427 CDS_INIT_LIST_HEAD(&trigger_list_element->node);
2428 trigger_list_element->trigger = trigger;
2429 cds_list_add(&trigger_list_element->node, &trigger_list->list);
2430 DBG("[notification-thread] Newly registered trigger bound to channel \"%s\"",
2431 channel->name);
2432 }
2433 end:
2434 return ret;
2435 }
2436
2437 static
2438 bool is_trigger_action_notify(const struct lttng_trigger *trigger)
2439 {
2440 bool is_notify = false;
2441 unsigned int i, count;
2442 enum lttng_action_status action_status;
2443 const struct lttng_action *action =
2444 lttng_trigger_get_const_action(trigger);
2445 enum lttng_action_type action_type;
2446
2447 assert(action);
2448 action_type = lttng_action_get_type(action);
2449 if (action_type == LTTNG_ACTION_TYPE_NOTIFY) {
2450 is_notify = true;
2451 goto end;
2452 } else if (action_type != LTTNG_ACTION_TYPE_GROUP) {
2453 goto end;
2454 }
2455
2456 action_status = lttng_action_group_get_count(action, &count);
2457 assert(action_status == LTTNG_ACTION_STATUS_OK);
2458
2459 for (i = 0; i < count; i++) {
2460 const struct lttng_action *inner_action =
2461 lttng_action_group_get_at_index(
2462 action, i);
2463
2464 action_type = lttng_action_get_type(inner_action);
2465 if (action_type == LTTNG_ACTION_TYPE_NOTIFY) {
2466 is_notify = true;
2467 goto end;
2468 }
2469 }
2470
2471 end:
2472 return is_notify;
2473 }
2474
2475 static bool trigger_name_taken(struct notification_thread_state *state,
2476 const struct lttng_trigger *trigger)
2477 {
2478 struct cds_lfht_iter iter;
2479
2480 /*
2481 * No duplicata is allowed in the triggers_by_name_uid_ht.
2482 * The match is done against the trigger name and uid.
2483 */
2484 cds_lfht_lookup(state->triggers_by_name_uid_ht,
2485 hash_trigger_by_name_uid(trigger),
2486 match_trigger_by_name_uid,
2487 trigger,
2488 &iter);
2489 return !!cds_lfht_iter_get_node(&iter);
2490 }
2491
2492 static
2493 enum lttng_error_code generate_trigger_name(
2494 struct notification_thread_state *state,
2495 struct lttng_trigger *trigger, const char **name)
2496 {
2497 enum lttng_error_code ret_code = LTTNG_OK;
2498 bool taken = false;
2499 enum lttng_trigger_status status;
2500
2501 do {
2502 const int ret = lttng_trigger_generate_name(trigger,
2503 state->trigger_id.name_offset++);
2504 if (ret) {
2505 /* The only reason this can fail right now. */
2506 ret_code = LTTNG_ERR_NOMEM;
2507 break;
2508 }
2509
2510 status = lttng_trigger_get_name(trigger, name);
2511 assert(status == LTTNG_TRIGGER_STATUS_OK);
2512
2513 taken = trigger_name_taken(state, trigger);
2514 } while (taken || state->trigger_id.name_offset == UINT64_MAX);
2515
2516 return ret_code;
2517 }
2518
2519 static inline
2520 void notif_thread_state_remove_trigger_ht_elem(
2521 struct notification_thread_state *state,
2522 struct lttng_trigger_ht_element *trigger_ht_element)
2523 {
2524 assert(state);
2525 assert(trigger_ht_element);
2526
2527 cds_lfht_del(state->triggers_ht, &trigger_ht_element->node);
2528 cds_lfht_del(state->triggers_by_name_uid_ht, &trigger_ht_element->node_by_name_uid);
2529 }
2530
2531 static
2532 enum lttng_error_code setup_tracer_notifier(
2533 struct notification_thread_state *state,
2534 struct lttng_trigger *trigger)
2535 {
2536 enum lttng_error_code ret;
2537 enum event_notifier_error_accounting_status error_accounting_status;
2538 struct cds_lfht_node *node;
2539 uint64_t error_counter_index = 0;
2540 struct lttng_condition *condition = lttng_trigger_get_condition(trigger);
2541 struct notification_trigger_tokens_ht_element *trigger_tokens_ht_element = NULL;
2542
2543 trigger_tokens_ht_element = zmalloc(sizeof(*trigger_tokens_ht_element));
2544 if (!trigger_tokens_ht_element) {
2545 ret = LTTNG_ERR_NOMEM;
2546 goto end;
2547 }
2548
2549 /* Add trigger token to the trigger_tokens_ht. */
2550 cds_lfht_node_init(&trigger_tokens_ht_element->node);
2551 trigger_tokens_ht_element->token = LTTNG_OPTIONAL_GET(trigger->tracer_token);
2552 trigger_tokens_ht_element->trigger = trigger;
2553
2554 node = cds_lfht_add_unique(state->trigger_tokens_ht,
2555 hash_key_u64(&trigger_tokens_ht_element->token, lttng_ht_seed),
2556 match_trigger_token,
2557 &trigger_tokens_ht_element->token,
2558 &trigger_tokens_ht_element->node);
2559 if (node != &trigger_tokens_ht_element->node) {
2560 ret = LTTNG_ERR_TRIGGER_EXISTS;
2561 goto error_free_ht_element;
2562 }
2563
2564 error_accounting_status = event_notifier_error_accounting_register_event_notifier(
2565 trigger, &error_counter_index);
2566 if (error_accounting_status != EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_OK) {
2567 if (error_accounting_status == EVENT_NOTIFIER_ERROR_ACCOUNTING_STATUS_NO_INDEX_AVAILABLE) {
2568 DBG("Trigger group error accounting counter full.");
2569 ret = LTTNG_ERR_EVENT_NOTIFIER_ERROR_ACCOUNTING_FULL;
2570 } else {
2571 ERR("Error registering trigger for error accounting");
2572 ret = LTTNG_ERR_EVENT_NOTIFIER_REGISTRATION;
2573 }
2574
2575 goto error_remove_ht_element;
2576 }
2577
2578 lttng_condition_on_event_set_error_counter_index(
2579 condition, error_counter_index);
2580
2581 ret = LTTNG_OK;
2582 goto end;
2583
2584 error_remove_ht_element:
2585 cds_lfht_del(state->trigger_tokens_ht, &trigger_tokens_ht_element->node);
2586 error_free_ht_element:
2587 free(trigger_tokens_ht_element);
2588 end:
2589 return ret;
2590 }
2591
2592 /*
2593 * FIXME A client's credentials are not checked when registering a trigger.
2594 *
2595 * The effects of this are benign since:
2596 * - The client will succeed in registering the trigger, as it is valid,
2597 * - The trigger will, internally, be bound to the channel/session,
2598 * - The notifications will not be sent since the client's credentials
2599 * are checked against the channel at that moment.
2600 *
2601 * If this function returns a non-zero value, it means something is
2602 * fundamentally broken and the whole subsystem/thread will be torn down.
2603 *
2604 * If a non-fatal error occurs, just set the cmd_result to the appropriate
2605 * error code.
2606 */
2607 static
2608 int handle_notification_thread_command_register_trigger(
2609 struct notification_thread_state *state,
2610 struct lttng_trigger *trigger,
2611 enum lttng_error_code *cmd_result)
2612 {
2613 int ret = 0;
2614 struct lttng_condition *condition;
2615 struct notification_client_list *client_list = NULL;
2616 struct lttng_trigger_ht_element *trigger_ht_element = NULL;
2617 struct cds_lfht_node *node;
2618 const char* trigger_name;
2619 bool free_trigger = true;
2620 struct lttng_evaluation *evaluation = NULL;
2621 struct lttng_credentials object_creds;
2622 uid_t object_uid;
2623 gid_t object_gid;
2624 enum action_executor_status executor_status;
2625 const uint64_t trigger_tracer_token =
2626 state->trigger_id.next_tracer_token++;
2627
2628 rcu_read_lock();
2629
2630 /* Set the trigger's tracer token. */
2631 lttng_trigger_set_tracer_token(trigger, trigger_tracer_token);
2632
2633 if (lttng_trigger_get_name(trigger, &trigger_name) ==
2634 LTTNG_TRIGGER_STATUS_UNSET) {
2635 const enum lttng_error_code ret_code = generate_trigger_name(
2636 state, trigger, &trigger_name);
2637
2638 if (ret_code != LTTNG_OK) {
2639 /* Fatal error. */
2640 ret = -1;
2641 *cmd_result = ret_code;
2642 goto error;
2643 }
2644 } else if (trigger_name_taken(state, trigger)) {
2645 /* Not a fatal error. */
2646 *cmd_result = LTTNG_ERR_TRIGGER_EXISTS;
2647 ret = 0;
2648 goto error;
2649 }
2650
2651 condition = lttng_trigger_get_condition(trigger);
2652 assert(condition);
2653
2654 /* Some conditions require tracers to implement a minimal ABI version. */
2655 if (!condition_is_supported(condition)) {
2656 *cmd_result = LTTNG_ERR_NOT_SUPPORTED;
2657 goto error;
2658 }
2659
2660 trigger_ht_element = zmalloc(sizeof(*trigger_ht_element));
2661 if (!trigger_ht_element) {
2662 ret = -1;
2663 goto error;
2664 }
2665
2666 /* Add trigger to the trigger_ht. */
2667 cds_lfht_node_init(&trigger_ht_element->node);
2668 cds_lfht_node_init(&trigger_ht_element->node_by_name_uid);
2669 trigger_ht_element->trigger = trigger;
2670
2671 node = cds_lfht_add_unique(state->triggers_ht,
2672 lttng_condition_hash(condition),
2673 match_trigger,
2674 trigger,
2675 &trigger_ht_element->node);
2676 if (node != &trigger_ht_element->node) {
2677 /* Not a fatal error, simply report it to the client. */
2678 *cmd_result = LTTNG_ERR_TRIGGER_EXISTS;
2679 goto error_free_ht_element;
2680 }
2681
2682 node = cds_lfht_add_unique(state->triggers_by_name_uid_ht,
2683 hash_trigger_by_name_uid(trigger),
2684 match_trigger_by_name_uid,
2685 trigger,
2686 &trigger_ht_element->node_by_name_uid);
2687 if (node != &trigger_ht_element->node_by_name_uid) {
2688 /* Not a fatal error, simply report it to the client. */
2689 cds_lfht_del(state->triggers_ht, &trigger_ht_element->node);
2690 *cmd_result = LTTNG_ERR_TRIGGER_EXISTS;
2691 goto error_free_ht_element;
2692 }
2693
2694 /*
2695 * Some triggers might need a tracer notifier depending on its
2696 * condition and actions.
2697 */
2698 if (lttng_trigger_needs_tracer_notifier(trigger)) {
2699 enum lttng_error_code error_code;
2700
2701 error_code = setup_tracer_notifier(state, trigger);
2702 if (error_code != LTTNG_OK) {
2703 notif_thread_state_remove_trigger_ht_elem(state,
2704 trigger_ht_element);
2705 if (error_code == LTTNG_ERR_NOMEM) {
2706 ret = -1;
2707 } else {
2708 *cmd_result = error_code;
2709 ret = 0;
2710 }
2711
2712 goto error_free_ht_element;
2713 }
2714 }
2715
2716 /*
2717 * The rest only applies to triggers that have a "notify" action.
2718 * It is not skipped as this is the only action type currently
2719 * supported.
2720 */
2721 if (is_trigger_action_notify(trigger)) {
2722 /*
2723 * Find or create the client list of this condition. It may
2724 * already be present if another trigger is already registered
2725 * with the same condition.
2726 */
2727 client_list = get_client_list_from_condition(state, condition);
2728 if (!client_list) {
2729 /*
2730 * No client list for this condition yet. We create new
2731 * one and build it up.
2732 */
2733 client_list = notification_client_list_create(state, condition);
2734 if (!client_list) {
2735 ERR("Error creating notification client list for trigger %s", trigger->name);
2736 goto error_free_ht_element;
2737 }
2738 }
2739
2740 CDS_INIT_LIST_HEAD(&trigger_ht_element->client_list_trigger_node);
2741
2742 pthread_mutex_lock(&client_list->lock);
2743 cds_list_add(&trigger_ht_element->client_list_trigger_node, &client_list->triggers_list);
2744 pthread_mutex_unlock(&client_list->lock);
2745 }
2746
2747 /*
2748 * Ownership of the trigger and of its wrapper was transfered to
2749 * the triggers_ht. Same for token ht element if necessary.
2750 */
2751 trigger_ht_element = NULL;
2752 free_trigger = false;
2753
2754 switch (get_condition_binding_object(condition)) {
2755 case LTTNG_OBJECT_TYPE_SESSION:
2756 /* Add the trigger to the list if it matches a known session. */
2757 ret = bind_trigger_to_matching_session(trigger, state);
2758 if (ret) {
2759 goto error_free_ht_element;
2760 }
2761 break;
2762 case LTTNG_OBJECT_TYPE_CHANNEL:
2763 /*
2764 * Add the trigger to list of triggers bound to the channels
2765 * currently known.
2766 */
2767 ret = bind_trigger_to_matching_channels(trigger, state);
2768 if (ret) {
2769 goto error_free_ht_element;
2770 }
2771 break;
2772 case LTTNG_OBJECT_TYPE_NONE:
2773 break;
2774 default:
2775 ERR("Unknown object type on which to bind a newly registered trigger was encountered");
2776 ret = -1;
2777 goto error_free_ht_element;
2778 }
2779
2780 /*
2781 * The new trigger's condition must be evaluated against the current
2782 * state.
2783 *
2784 * In the case of `notify` action, nothing preventing clients from
2785 * subscribing to a condition before the corresponding trigger is
2786 * registered, we have to evaluate this new condition right away.
2787 *
2788 * At some point, we were waiting for the next "evaluation" (e.g. on
2789 * reception of a channel sample) to evaluate this new condition, but
2790 * that was broken.
2791 *
2792 * The reason it was broken is that waiting for the next sample
2793 * does not allow us to properly handle transitions for edge-triggered
2794 * conditions.
2795 *
2796 * Consider this example: when we handle a new channel sample, we
2797 * evaluate each conditions twice: once with the previous state, and
2798 * again with the newest state. We then use those two results to
2799 * determine whether a state change happened: a condition was false and
2800 * became true. If a state change happened, we have to notify clients.
2801 *
2802 * Now, if a client subscribes to a given notification and registers
2803 * a trigger *after* that subscription, we have to make sure the
2804 * condition is evaluated at this point while considering only the
2805 * current state. Otherwise, the next evaluation cycle may only see
2806 * that the evaluations remain the same (true for samples n-1 and n) and
2807 * the client will never know that the condition has been met.
2808 */
2809 switch (get_condition_binding_object(condition)) {
2810 case LTTNG_OBJECT_TYPE_SESSION:
2811 ret = evaluate_session_condition_for_client(condition, state,
2812 &evaluation, &object_uid,
2813 &object_gid);
2814 LTTNG_OPTIONAL_SET(&object_creds.uid, object_uid);
2815 LTTNG_OPTIONAL_SET(&object_creds.gid, object_gid);
2816 break;
2817 case LTTNG_OBJECT_TYPE_CHANNEL:
2818 ret = evaluate_channel_condition_for_client(condition, state,
2819 &evaluation, &object_uid,
2820 &object_gid);
2821 LTTNG_OPTIONAL_SET(&object_creds.uid, object_uid);
2822 LTTNG_OPTIONAL_SET(&object_creds.gid, object_gid);
2823 break;
2824 case LTTNG_OBJECT_TYPE_NONE:
2825 ret = 0;
2826 break;
2827 case LTTNG_OBJECT_TYPE_UNKNOWN:
2828 default:
2829 ret = -1;
2830 break;
2831 }
2832
2833 if (ret) {
2834 /* Fatal error. */
2835 goto error_free_ht_element;
2836 }
2837
2838 DBG("Newly registered trigger's condition evaluated to %s",
2839 evaluation ? "true" : "false");
2840 if (!evaluation) {
2841 /* Evaluation yielded nothing. Normal exit. */
2842 ret = 0;
2843 goto success;
2844 }
2845
2846 /*
2847 * Ownership of `evaluation` transferred to the action executor
2848 * no matter the result.
2849 */
2850 executor_status = action_executor_enqueue(state->executor, trigger,
2851 evaluation, &object_creds, client_list);
2852 evaluation = NULL;
2853 switch (executor_status) {
2854 case ACTION_EXECUTOR_STATUS_OK:
2855 break;
2856 case ACTION_EXECUTOR_STATUS_ERROR:
2857 case ACTION_EXECUTOR_STATUS_INVALID:
2858 /*
2859 * TODO Add trigger identification (name/id) when
2860 * it is added to the API.
2861 */
2862 ERR("Fatal error occurred while enqueuing action associated to newly registered trigger");
2863 ret = -1;
2864 goto error_free_ht_element;
2865 case ACTION_EXECUTOR_STATUS_OVERFLOW:
2866 /*
2867 * TODO Add trigger identification (name/id) when
2868 * it is added to the API.
2869 *
2870 * Not a fatal error.
2871 */
2872 WARN("No space left when enqueuing action associated to newly registered trigger");
2873 ret = 0;
2874 goto success;
2875 default:
2876 abort();
2877 }
2878
2879 success:
2880 *cmd_result = LTTNG_OK;
2881 DBG("Registered trigger: name = `%s`, tracer token = %" PRIu64,
2882 trigger_name, trigger_tracer_token);
2883 goto end;
2884
2885 error_free_ht_element:
2886 if (trigger_ht_element) {
2887 /* Delayed removal due to RCU constraint on delete. */
2888 call_rcu(&trigger_ht_element->rcu_node,
2889 free_lttng_trigger_ht_element_rcu);
2890 }
2891 error:
2892 if (free_trigger) {
2893 lttng_trigger_destroy(trigger);
2894 }
2895 end:
2896 rcu_read_unlock();
2897 return ret;
2898 }
2899
2900 static
2901 void free_lttng_trigger_ht_element_rcu(struct rcu_head *node)
2902 {
2903 free(caa_container_of(node, struct lttng_trigger_ht_element,
2904 rcu_node));
2905 }
2906
2907 static
2908 void free_notification_trigger_tokens_ht_element_rcu(struct rcu_head *node)
2909 {
2910 free(caa_container_of(node, struct notification_trigger_tokens_ht_element,
2911 rcu_node));
2912 }
2913
2914 static
2915 void teardown_tracer_notifier(struct notification_thread_state *state,
2916 const struct lttng_trigger *trigger)
2917 {
2918 struct cds_lfht_iter iter;
2919 struct notification_trigger_tokens_ht_element *trigger_tokens_ht_element;
2920
2921 cds_lfht_for_each_entry(state->trigger_tokens_ht, &iter,
2922 trigger_tokens_ht_element, node) {
2923
2924 if (!lttng_trigger_is_equal(trigger,
2925 trigger_tokens_ht_element->trigger)) {
2926 continue;
2927 }
2928
2929 event_notifier_error_accounting_unregister_event_notifier(
2930 trigger_tokens_ht_element->trigger);
2931
2932 /* TODO talk to all app and remove it */
2933 DBG("[notification-thread] Removed trigger from tokens_ht");
2934 cds_lfht_del(state->trigger_tokens_ht,
2935 &trigger_tokens_ht_element->node);
2936
2937 call_rcu(&trigger_tokens_ht_element->rcu_node,
2938 free_notification_trigger_tokens_ht_element_rcu);
2939
2940 break;
2941 }
2942 }
2943
2944 static
2945 int handle_notification_thread_command_unregister_trigger(
2946 struct notification_thread_state *state,
2947 const struct lttng_trigger *trigger,
2948 enum lttng_error_code *_cmd_reply)
2949 {
2950 struct cds_lfht_iter iter;
2951 struct cds_lfht_node *triggers_ht_node;
2952 struct lttng_channel_trigger_list *trigger_list;
2953 struct notification_client_list *client_list;
2954 struct lttng_trigger_ht_element *trigger_ht_element = NULL;
2955 const struct lttng_condition *condition = lttng_trigger_get_const_condition(
2956 trigger);
2957 enum lttng_error_code cmd_reply;
2958
2959 rcu_read_lock();
2960
2961 cds_lfht_lookup(state->triggers_ht,
2962 lttng_condition_hash(condition),
2963 match_trigger,
2964 trigger,
2965 &iter);
2966 triggers_ht_node = cds_lfht_iter_get_node(&iter);
2967 if (!triggers_ht_node) {
2968 cmd_reply = LTTNG_ERR_TRIGGER_NOT_FOUND;
2969 goto end;
2970 } else {
2971 cmd_reply = LTTNG_OK;
2972 }
2973
2974 /* Remove trigger from channel_triggers_ht. */
2975 cds_lfht_for_each_entry(state->channel_triggers_ht, &iter, trigger_list,
2976 channel_triggers_ht_node) {
2977 struct lttng_trigger_list_element *trigger_element, *tmp;
2978
2979 cds_list_for_each_entry_safe(trigger_element, tmp,
2980 &trigger_list->list, node) {
2981 if (!lttng_trigger_is_equal(trigger, trigger_element->trigger)) {
2982 continue;
2983 }
2984
2985 DBG("[notification-thread] Removed trigger from channel_triggers_ht");
2986 cds_list_del(&trigger_element->node);
2987 /* A trigger can only appear once per channel */
2988 break;
2989 }
2990 }
2991
2992 if (lttng_trigger_needs_tracer_notifier(trigger)) {
2993 teardown_tracer_notifier(state, trigger);
2994 }
2995
2996 trigger_ht_element = caa_container_of(triggers_ht_node,
2997 struct lttng_trigger_ht_element, node);
2998
2999 if (is_trigger_action_notify(trigger)) {
3000 /*
3001 * Remove and release the client list from
3002 * notification_trigger_clients_ht.
3003 */
3004 client_list = get_client_list_from_condition(state, condition);
3005 assert(client_list);
3006
3007 pthread_mutex_lock(&client_list->lock);
3008 cds_list_del(&trigger_ht_element->client_list_trigger_node);
3009 pthread_mutex_unlock(&client_list->lock);
3010
3011 /* Put new reference and the hashtable's reference. */
3012 notification_client_list_put(client_list);
3013 notification_client_list_put(client_list);
3014 client_list = NULL;
3015 }
3016
3017 /* Remove trigger from triggers_ht. */
3018 notif_thread_state_remove_trigger_ht_elem(state, trigger_ht_element);
3019
3020 /* Release the ownership of the trigger. */
3021 lttng_trigger_destroy(trigger_ht_element->trigger);
3022 call_rcu(&trigger_ht_element->rcu_node, free_lttng_trigger_ht_element_rcu);
3023 end:
3024 rcu_read_unlock();
3025 if (_cmd_reply) {
3026 *_cmd_reply = cmd_reply;
3027 }
3028 return 0;
3029 }
3030
3031 /* Returns 0 on success, 1 on exit requested, negative value on error. */
3032 int handle_notification_thread_command(
3033 struct notification_thread_handle *handle,
3034 struct notification_thread_state *state)
3035 {
3036 int ret;
3037 uint64_t counter;
3038 struct notification_thread_command *cmd;
3039
3040 /* Read the event pipe to put it back into a quiescent state. */
3041 ret = lttng_read(lttng_pipe_get_readfd(handle->cmd_queue.event_pipe), &counter,
3042 sizeof(counter));
3043 if (ret != sizeof(counter)) {
3044 goto error;
3045 }
3046
3047 pthread_mutex_lock(&handle->cmd_queue.lock);
3048 cmd = cds_list_first_entry(&handle->cmd_queue.list,
3049 struct notification_thread_command, cmd_list_node);
3050 cds_list_del(&cmd->cmd_list_node);
3051 pthread_mutex_unlock(&handle->cmd_queue.lock);
3052
3053 DBG("[notification-thread] Received `%s` command",
3054 notification_command_type_str(cmd->type));
3055 switch (cmd->type) {
3056 case NOTIFICATION_COMMAND_TYPE_REGISTER_TRIGGER:
3057 ret = handle_notification_thread_command_register_trigger(state,
3058 cmd->parameters.register_trigger.trigger,
3059 &cmd->reply_code);
3060 break;
3061 case NOTIFICATION_COMMAND_TYPE_UNREGISTER_TRIGGER:
3062 ret = handle_notification_thread_command_unregister_trigger(
3063 state,
3064 cmd->parameters.unregister_trigger.trigger,
3065 &cmd->reply_code);
3066 break;
3067 case NOTIFICATION_COMMAND_TYPE_ADD_CHANNEL:
3068 ret = handle_notification_thread_command_add_channel(
3069 state,
3070 cmd->parameters.add_channel.session.name,
3071 cmd->parameters.add_channel.session.uid,
3072 cmd->parameters.add_channel.session.gid,
3073 cmd->parameters.add_channel.channel.name,
3074 cmd->parameters.add_channel.channel.domain,
3075 cmd->parameters.add_channel.channel.key,
3076 cmd->parameters.add_channel.channel.capacity,
3077 &cmd->reply_code);
3078 break;
3079 case NOTIFICATION_COMMAND_TYPE_REMOVE_CHANNEL:
3080 ret = handle_notification_thread_command_remove_channel(
3081 state, cmd->parameters.remove_channel.key,
3082 cmd->parameters.remove_channel.domain,
3083 &cmd->reply_code);
3084 break;
3085 case NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_ONGOING:
3086 case NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_COMPLETED:
3087 ret = handle_notification_thread_command_session_rotation(
3088 state,
3089 cmd->type,
3090 cmd->parameters.session_rotation.session_name,
3091 cmd->parameters.session_rotation.uid,
3092 cmd->parameters.session_rotation.gid,
3093 cmd->parameters.session_rotation.trace_archive_chunk_id,
3094 cmd->parameters.session_rotation.location,
3095 &cmd->reply_code);
3096 break;
3097 case NOTIFICATION_COMMAND_TYPE_ADD_TRACER_EVENT_SOURCE:
3098 ret = handle_notification_thread_command_add_tracer_event_source(
3099 state,
3100 cmd->parameters.tracer_event_source.tracer_event_source_fd,
3101 cmd->parameters.tracer_event_source.domain,
3102 &cmd->reply_code);
3103 break;
3104 case NOTIFICATION_COMMAND_TYPE_REMOVE_TRACER_EVENT_SOURCE:
3105 ret = handle_notification_thread_command_remove_tracer_event_source(
3106 state,
3107 cmd->parameters.tracer_event_source.tracer_event_source_fd,
3108 &cmd->reply_code);
3109 break;
3110 case NOTIFICATION_COMMAND_TYPE_LIST_TRIGGERS:
3111 {
3112 struct lttng_triggers *triggers = NULL;
3113
3114 ret = handle_notification_thread_command_list_triggers(
3115 handle,
3116 state,
3117 cmd->parameters.list_triggers.uid,
3118 &triggers,
3119 &cmd->reply_code);
3120 cmd->reply.list_triggers.triggers = triggers;
3121 ret = 0;
3122 break;
3123 }
3124 case NOTIFICATION_COMMAND_TYPE_QUIT:
3125 cmd->reply_code = LTTNG_OK;
3126 ret = 1;
3127 goto end;
3128 case NOTIFICATION_COMMAND_TYPE_CLIENT_COMMUNICATION_UPDATE:
3129 {
3130 const enum client_transmission_status client_status =
3131 cmd->parameters.client_communication_update
3132 .status;
3133 const notification_client_id client_id =
3134 cmd->parameters.client_communication_update.id;
3135 struct notification_client *client;
3136
3137 rcu_read_lock();
3138 client = get_client_from_id(client_id, state);
3139
3140 if (!client) {
3141 /*
3142 * Client error was probably already picked-up by the
3143 * notification thread or it has disconnected
3144 * gracefully while this command was queued.
3145 */
3146 DBG("Failed to find notification client to update communication status, client id = %" PRIu64,
3147 client_id);
3148 ret = 0;
3149 } else {
3150 ret = client_handle_transmission_status(
3151 client, client_status, state);
3152 }
3153 rcu_read_unlock();
3154 break;
3155 }
3156 default:
3157 ERR("[notification-thread] Unknown internal command received");
3158 goto error_unlock;
3159 }
3160
3161 if (ret) {
3162 goto error_unlock;
3163 }
3164 end:
3165 if (cmd->is_async) {
3166 free(cmd);
3167 cmd = NULL;
3168 } else {
3169 lttng_waiter_wake_up(&cmd->reply_waiter);
3170 }
3171 return ret;
3172 error_unlock:
3173 /* Wake-up and return a fatal error to the calling thread. */
3174 lttng_waiter_wake_up(&cmd->reply_waiter);
3175 cmd->reply_code = LTTNG_ERR_FATAL;
3176 error:
3177 /* Indicate a fatal error to the caller. */
3178 return -1;
3179 }
3180
3181 static
3182 int socket_set_non_blocking(int socket)
3183 {
3184 int ret, flags;
3185
3186 /* Set the pipe as non-blocking. */
3187 ret = fcntl(socket, F_GETFL, 0);
3188 if (ret == -1) {
3189 PERROR("fcntl get socket flags");
3190 goto end;
3191 }
3192 flags = ret;
3193
3194 ret = fcntl(socket, F_SETFL, flags | O_NONBLOCK);
3195 if (ret == -1) {
3196 PERROR("fcntl set O_NONBLOCK socket flag");
3197 goto end;
3198 }
3199 DBG("Client socket (fd = %i) set as non-blocking", socket);
3200 end:
3201 return ret;
3202 }
3203
3204 static
3205 int client_reset_inbound_state(struct notification_client *client)
3206 {
3207 int ret;
3208
3209
3210 lttng_payload_clear(&client->communication.inbound.payload);
3211
3212 client->communication.inbound.bytes_to_receive =
3213 sizeof(struct lttng_notification_channel_message);
3214 client->communication.inbound.msg_type =
3215 LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNKNOWN;
3216 LTTNG_SOCK_SET_UID_CRED(&client->communication.inbound.creds, -1);
3217 LTTNG_SOCK_SET_GID_CRED(&client->communication.inbound.creds, -1);
3218 ret = lttng_dynamic_buffer_set_size(
3219 &client->communication.inbound.payload.buffer,
3220 client->communication.inbound.bytes_to_receive);
3221
3222 return ret;
3223 }
3224
3225 int handle_notification_thread_client_connect(
3226 struct notification_thread_state *state)
3227 {
3228 int ret;
3229 struct notification_client *client;
3230
3231 DBG("[notification-thread] Handling new notification channel client connection");
3232
3233 client = zmalloc(sizeof(*client));
3234 if (!client) {
3235 /* Fatal error. */
3236 ret = -1;
3237 goto error;
3238 }
3239
3240 pthread_mutex_init(&client->lock, NULL);
3241 client->id = state->next_notification_client_id++;
3242 CDS_INIT_LIST_HEAD(&client->condition_list);
3243 lttng_payload_init(&client->communication.inbound.payload);
3244 lttng_payload_init(&client->communication.outbound.payload);
3245 client->communication.inbound.expect_creds = true;
3246
3247 ret = client_reset_inbound_state(client);
3248 if (ret) {
3249 ERR("[notification-thread] Failed to reset client communication's inbound state");
3250 ret = 0;
3251 goto error;
3252 }
3253
3254 ret = lttcomm_accept_unix_sock(state->notification_channel_socket);
3255 if (ret < 0) {
3256 ERR("[notification-thread] Failed to accept new notification channel client connection");
3257 ret = 0;
3258 goto error;
3259 }
3260
3261 client->socket = ret;
3262
3263 ret = socket_set_non_blocking(client->socket);
3264 if (ret) {
3265 ERR("[notification-thread] Failed to set new notification channel client connection socket as non-blocking");
3266 goto error;
3267 }
3268
3269 ret = lttcomm_setsockopt_creds_unix_sock(client->socket);
3270 if (ret < 0) {
3271 ERR("[notification-thread] Failed to set socket options on new notification channel client socket");
3272 ret = 0;
3273 goto error;
3274 }
3275
3276 ret = lttng_poll_add(&state->events, client->socket,
3277 LPOLLIN | LPOLLERR |
3278 LPOLLHUP | LPOLLRDHUP);
3279 if (ret < 0) {
3280 ERR("[notification-thread] Failed to add notification channel client socket to poll set");
3281 ret = 0;
3282 goto error;
3283 }
3284 DBG("[notification-thread] Added new notification channel client socket (%i) to poll set",
3285 client->socket);
3286
3287 rcu_read_lock();
3288 cds_lfht_add(state->client_socket_ht,
3289 hash_client_socket(client->socket),
3290 &client->client_socket_ht_node);
3291 cds_lfht_add(state->client_id_ht,
3292 hash_client_id(client->id),
3293 &client->client_id_ht_node);
3294 rcu_read_unlock();
3295
3296 return ret;
3297
3298 error:
3299 notification_client_destroy(client, state);
3300 return ret;
3301 }
3302
3303 /*
3304 * RCU read-lock must be held by the caller.
3305 * Client lock must _not_ be held by the caller.
3306 */
3307 static
3308 int notification_thread_client_disconnect(
3309 struct notification_client *client,
3310 struct notification_thread_state *state)
3311 {
3312 int ret;
3313 struct lttng_condition_list_element *condition_list_element, *tmp;
3314
3315 /* Acquire the client lock to disable its communication atomically. */
3316 pthread_mutex_lock(&client->lock);
3317 client->communication.active = false;
3318 cds_lfht_del(state->client_socket_ht, &client->client_socket_ht_node);
3319 cds_lfht_del(state->client_id_ht, &client->client_id_ht_node);
3320 pthread_mutex_unlock(&client->lock);
3321
3322 ret = lttng_poll_del(&state->events, client->socket);
3323 if (ret) {
3324 ERR("[notification-thread] Failed to remove client socket %d from poll set",
3325 client->socket);
3326 }
3327
3328 /* Release all conditions to which the client was subscribed. */
3329 cds_list_for_each_entry_safe(condition_list_element, tmp,
3330 &client->condition_list, node) {
3331 (void) notification_thread_client_unsubscribe(client,
3332 condition_list_element->condition, state, NULL);
3333 }
3334
3335 /*
3336 * Client no longer accessible to other threads (through the
3337 * client lists).
3338 */
3339 notification_client_destroy(client, state);
3340 return ret;
3341 }
3342
3343 int handle_notification_thread_client_disconnect(
3344 int client_socket, struct notification_thread_state *state)
3345 {
3346 int ret = 0;
3347 struct notification_client *client;
3348
3349 rcu_read_lock();
3350 DBG("[notification-thread] Closing client connection (socket fd = %i)",
3351 client_socket);
3352 client = get_client_from_socket(client_socket, state);
3353 if (!client) {
3354 /* Internal state corruption, fatal error. */
3355 ERR("[notification-thread] Unable to find client (socket fd = %i)",
3356 client_socket);
3357 ret = -1;
3358 goto end;
3359 }
3360
3361 ret = notification_thread_client_disconnect(client, state);
3362 end:
3363 rcu_read_unlock();
3364 return ret;
3365 }
3366
3367 int handle_notification_thread_client_disconnect_all(
3368 struct notification_thread_state *state)
3369 {
3370 struct cds_lfht_iter iter;
3371 struct notification_client *client;
3372 bool error_encoutered = false;
3373
3374 rcu_read_lock();
3375 DBG("[notification-thread] Closing all client connections");
3376 cds_lfht_for_each_entry(state->client_socket_ht, &iter, client,
3377 client_socket_ht_node) {
3378 int ret;
3379
3380 ret = notification_thread_client_disconnect(
3381 client, state);
3382 if (ret) {
3383 error_encoutered = true;
3384 }
3385 }
3386 rcu_read_unlock();
3387 return error_encoutered ? 1 : 0;
3388 }
3389
3390 int handle_notification_thread_trigger_unregister_all(
3391 struct notification_thread_state *state)
3392 {
3393 bool error_occurred = false;
3394 struct cds_lfht_iter iter;
3395 struct lttng_trigger_ht_element *trigger_ht_element;
3396
3397 rcu_read_lock();
3398 cds_lfht_for_each_entry(state->triggers_ht, &iter, trigger_ht_element,
3399 node) {
3400 int ret = handle_notification_thread_command_unregister_trigger(
3401 state, trigger_ht_element->trigger, NULL);
3402 if (ret) {
3403 error_occurred = true;
3404 }
3405 }
3406 rcu_read_unlock();
3407 return error_occurred ? -1 : 0;
3408 }
3409
3410 static
3411 int client_handle_transmission_status(
3412 struct notification_client *client,
3413 enum client_transmission_status transmission_status,
3414 struct notification_thread_state *state)
3415 {
3416 int ret = 0;
3417
3418 switch (transmission_status) {
3419 case CLIENT_TRANSMISSION_STATUS_COMPLETE:
3420 ret = lttng_poll_mod(&state->events, client->socket,
3421 CLIENT_POLL_MASK_IN);
3422 if (ret) {
3423 goto end;
3424 }
3425
3426 break;
3427 case CLIENT_TRANSMISSION_STATUS_QUEUED:
3428 /*
3429 * We want to be notified whenever there is buffer space
3430 * available to send the rest of the payload.
3431 */
3432 ret = lttng_poll_mod(&state->events, client->socket,
3433 CLIENT_POLL_MASK_IN_OUT);
3434 if (ret) {
3435 goto end;
3436 }
3437 break;
3438 case CLIENT_TRANSMISSION_STATUS_FAIL:
3439 ret = notification_thread_client_disconnect(client, state);
3440 if (ret) {
3441 goto end;
3442 }
3443 break;
3444 case CLIENT_TRANSMISSION_STATUS_ERROR:
3445 ret = -1;
3446 goto end;
3447 default:
3448 abort();
3449 }
3450 end:
3451 return ret;
3452 }
3453
3454 /* Client lock must be acquired by caller. */
3455 static
3456 enum client_transmission_status client_flush_outgoing_queue(
3457 struct notification_client *client)
3458 {
3459 ssize_t ret;
3460 size_t to_send_count;
3461 enum client_transmission_status status;
3462 struct lttng_payload_view pv = lttng_payload_view_from_payload(
3463 &client->communication.outbound.payload, 0, -1);
3464 const int fds_to_send_count =
3465 lttng_payload_view_get_fd_handle_count(&pv);
3466
3467 ASSERT_LOCKED(client->lock);
3468
3469 if (!client->communication.active) {
3470 status = CLIENT_TRANSMISSION_STATUS_FAIL;
3471 goto end;
3472 }
3473
3474 if (pv.buffer.size == 0) {
3475 /*
3476 * If both data and fds are equal to zero, we are in an invalid
3477 * state.
3478 */
3479 assert(fds_to_send_count != 0);
3480 goto send_fds;
3481 }
3482
3483 /* Send data. */
3484 to_send_count = pv.buffer.size;
3485 DBG("[notification-thread] Flushing client (socket fd = %i) outgoing queue",
3486 client->socket);
3487
3488 ret = lttcomm_send_unix_sock_non_block(client->socket,
3489 pv.buffer.data,
3490 to_send_count);
3491 if ((ret >= 0 && ret < to_send_count)) {
3492 DBG("[notification-thread] Client (socket fd = %i) outgoing queue could not be completely flushed",
3493 client->socket);
3494 to_send_count -= max(ret, 0);
3495
3496 memmove(client->communication.outbound.payload.buffer.data,
3497 pv.buffer.data +
3498 pv.buffer.size - to_send_count,
3499 to_send_count);
3500 ret = lttng_dynamic_buffer_set_size(
3501 &client->communication.outbound.payload.buffer,
3502 to_send_count);
3503 if (ret) {
3504 goto error;
3505 }
3506
3507 status = CLIENT_TRANSMISSION_STATUS_QUEUED;
3508 goto end;
3509 } else if (ret < 0) {
3510 /* Generic error, disable the client's communication. */
3511 ERR("[notification-thread] Failed to flush outgoing queue, disconnecting client (socket fd = %i)",
3512 client->socket);
3513 client->communication.active = false;
3514 status = CLIENT_TRANSMISSION_STATUS_FAIL;
3515 goto end;
3516 } else {
3517 /*
3518 * No error and flushed the queue completely.
3519 *
3520 * The payload buffer size is used later to
3521 * check if there is notifications queued. So albeit that the
3522 * direct caller knows that the transmission is complete, we
3523 * need to set the buffer size to zero.
3524 */
3525 ret = lttng_dynamic_buffer_set_size(
3526 &client->communication.outbound.payload.buffer, 0);
3527 if (ret) {
3528 goto error;
3529 }
3530 }
3531
3532 send_fds:
3533 /* No fds to send, transmission is complete. */
3534 if (fds_to_send_count == 0) {
3535 status = CLIENT_TRANSMISSION_STATUS_COMPLETE;
3536 goto end;
3537 }
3538
3539 ret = lttcomm_send_payload_view_fds_unix_sock_non_block(
3540 client->socket, &pv);
3541 if (ret < 0) {
3542 /* Generic error, disable the client's communication. */
3543 ERR("[notification-thread] Failed to flush outgoing fds queue, disconnecting client (socket fd = %i)",
3544 client->socket);
3545 client->communication.active = false;
3546 status = CLIENT_TRANSMISSION_STATUS_FAIL;
3547 goto end;
3548 } else if (ret == 0) {
3549 /* Nothing could be sent. */
3550 status = CLIENT_TRANSMISSION_STATUS_QUEUED;
3551 } else {
3552 /* Fd passing is an all or nothing kind of thing. */
3553 status = CLIENT_TRANSMISSION_STATUS_COMPLETE;
3554 /*
3555 * The payload _fd_array count is used later to
3556 * check if there is notifications queued. So although the
3557 * direct caller knows that the transmission is complete, we
3558 * need to clear the _fd_array for the queuing check.
3559 */
3560 lttng_dynamic_pointer_array_clear(
3561 &client->communication.outbound.payload
3562 ._fd_handles);
3563 }
3564
3565 end:
3566 if (status == CLIENT_TRANSMISSION_STATUS_COMPLETE) {
3567 client->communication.outbound.queued_command_reply = false;
3568 client->communication.outbound.dropped_notification = false;
3569 lttng_payload_clear(&client->communication.outbound.payload);
3570 }
3571
3572 return status;
3573 error:
3574 return CLIENT_TRANSMISSION_STATUS_ERROR;
3575 }
3576
3577 static
3578 bool client_has_outbound_data_left(
3579 const struct notification_client *client)
3580 {
3581 const struct lttng_payload_view pv = lttng_payload_view_from_payload(
3582 &client->communication.outbound.payload, 0, -1);
3583 const bool has_data = pv.buffer.size != 0;
3584 const bool has_fds = lttng_payload_view_get_fd_handle_count(&pv);
3585
3586 return has_data || has_fds;
3587 }
3588
3589 /* Client lock must _not_ be held by the caller. */
3590 static
3591 int client_send_command_reply(struct notification_client *client,
3592 struct notification_thread_state *state,
3593 enum lttng_notification_channel_status status)
3594 {
3595 int ret;
3596 struct lttng_notification_channel_command_reply reply = {
3597 .status = (int8_t) status,
3598 };
3599 struct lttng_notification_channel_message msg = {
3600 .type = (int8_t) LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_COMMAND_REPLY,
3601 .size = sizeof(reply),
3602 };
3603 char buffer[sizeof(msg) + sizeof(reply)];
3604 enum client_transmission_status transmission_status;
3605
3606 memcpy(buffer, &msg, sizeof(msg));
3607 memcpy(buffer + sizeof(msg), &reply, sizeof(reply));
3608 DBG("[notification-thread] Send command reply (%i)", (int) status);
3609
3610 pthread_mutex_lock(&client->lock);
3611 if (client->communication.outbound.queued_command_reply) {
3612 /* Protocol error. */
3613 goto error_unlock;
3614 }
3615
3616 /* Enqueue buffer to outgoing queue and flush it. */
3617 ret = lttng_dynamic_buffer_append(
3618 &client->communication.outbound.payload.buffer,
3619 buffer, sizeof(buffer));
3620 if (ret) {
3621 goto error_unlock;
3622 }
3623
3624 transmission_status = client_flush_outgoing_queue(client);
3625
3626 if (client_has_outbound_data_left(client)) {
3627 /* Queue could not be emptied. */
3628 client->communication.outbound.queued_command_reply = true;
3629 }
3630
3631 pthread_mutex_unlock(&client->lock);
3632 ret = client_handle_transmission_status(
3633 client, transmission_status, state);
3634 if (ret) {
3635 goto error;
3636 }
3637
3638 return 0;
3639 error_unlock:
3640 pthread_mutex_unlock(&client->lock);
3641 error:
3642 return -1;
3643 }
3644
3645 static
3646 int client_handle_message_unknown(struct notification_client *client,
3647 struct notification_thread_state *state)
3648 {
3649 int ret;
3650 /*
3651 * Receiving message header. The function will be called again
3652 * once the rest of the message as been received and can be
3653 * interpreted.
3654 */
3655 const struct lttng_notification_channel_message *msg;
3656
3657 assert(sizeof(*msg) == client->communication.inbound.payload.buffer.size);
3658 msg = (const struct lttng_notification_channel_message *)
3659 client->communication.inbound.payload.buffer.data;
3660
3661 if (msg->size == 0 ||
3662 msg->size > DEFAULT_MAX_NOTIFICATION_CLIENT_MESSAGE_PAYLOAD_SIZE) {
3663 ERR("[notification-thread] Invalid notification channel message: length = %u",
3664 msg->size);
3665 ret = -1;
3666 goto end;
3667 }
3668
3669 switch (msg->type) {
3670 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_SUBSCRIBE:
3671 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNSUBSCRIBE:
3672 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_HANDSHAKE:
3673 break;
3674 default:
3675 ret = -1;
3676 ERR("[notification-thread] Invalid notification channel message: unexpected message type");
3677 goto end;
3678 }
3679
3680 client->communication.inbound.bytes_to_receive = msg->size;
3681 client->communication.inbound.fds_to_receive = msg->fds;
3682 client->communication.inbound.msg_type =
3683 (enum lttng_notification_channel_message_type) msg->type;
3684 ret = lttng_dynamic_buffer_set_size(
3685 &client->communication.inbound.payload.buffer, msg->size);
3686
3687 /* msg is not valid anymore due to lttng_dynamic_buffer_set_size. */
3688 msg = NULL;
3689 end:
3690 return ret;
3691 }
3692
3693 static
3694 int client_handle_message_handshake(struct notification_client *client,
3695 struct notification_thread_state *state)
3696 {
3697 int ret;
3698 struct lttng_notification_channel_command_handshake *handshake_client;
3699 const struct lttng_notification_channel_command_handshake handshake_reply = {
3700 .major = LTTNG_NOTIFICATION_CHANNEL_VERSION_MAJOR,
3701 .minor = LTTNG_NOTIFICATION_CHANNEL_VERSION_MINOR,
3702 };
3703 const struct lttng_notification_channel_message msg_header = {
3704 .type = LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_HANDSHAKE,
3705 .size = sizeof(handshake_reply),
3706 };
3707 enum lttng_notification_channel_status status =
3708 LTTNG_NOTIFICATION_CHANNEL_STATUS_OK;
3709 char send_buffer[sizeof(msg_header) + sizeof(handshake_reply)];
3710
3711 memcpy(send_buffer, &msg_header, sizeof(msg_header));
3712 memcpy(send_buffer + sizeof(msg_header), &handshake_reply,
3713 sizeof(handshake_reply));
3714
3715 handshake_client =
3716 (struct lttng_notification_channel_command_handshake *)
3717 client->communication.inbound.payload.buffer
3718 .data;
3719 client->major = handshake_client->major;
3720 client->minor = handshake_client->minor;
3721 if (!client->communication.inbound.creds_received) {
3722 ERR("[notification-thread] No credentials received from client");
3723 ret = -1;
3724 goto end;
3725 }
3726
3727 client->uid = LTTNG_SOCK_GET_UID_CRED(
3728 &client->communication.inbound.creds);
3729 client->gid = LTTNG_SOCK_GET_GID_CRED(
3730 &client->communication.inbound.creds);
3731 DBG("[notification-thread] Received handshake from client (uid = %u, gid = %u) with version %i.%i",
3732 client->uid, client->gid, (int) client->major,
3733 (int) client->minor);
3734
3735 if (handshake_client->major !=
3736 LTTNG_NOTIFICATION_CHANNEL_VERSION_MAJOR) {
3737 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_UNSUPPORTED_VERSION;
3738 }
3739
3740 pthread_mutex_lock(&client->lock);
3741 /* Outgoing queue will be flushed when the command reply is sent. */
3742 ret = lttng_dynamic_buffer_append(
3743 &client->communication.outbound.payload.buffer, send_buffer,
3744 sizeof(send_buffer));
3745 if (ret) {
3746 ERR("[notification-thread] Failed to send protocol version to notification channel client");
3747 goto end_unlock;
3748 }
3749
3750 client->validated = true;
3751 client->communication.active = true;
3752 pthread_mutex_unlock(&client->lock);
3753
3754 /* Set reception state to receive the next message header. */
3755 ret = client_reset_inbound_state(client);
3756 if (ret) {
3757 ERR("[notification-thread] Failed to reset client communication's inbound state");
3758 goto end;
3759 }
3760
3761 /* Flushes the outgoing queue. */
3762 ret = client_send_command_reply(client, state, status);
3763 if (ret) {
3764 ERR("[notification-thread] Failed to send reply to notification channel client");
3765 goto end;
3766 }
3767
3768 goto end;
3769 end_unlock:
3770 pthread_mutex_unlock(&client->lock);
3771 end:
3772 return ret;
3773 }
3774
3775 static
3776 int client_handle_message_subscription(
3777 struct notification_client *client,
3778 enum lttng_notification_channel_message_type msg_type,
3779 struct notification_thread_state *state)
3780 {
3781 int ret;
3782 struct lttng_condition *condition;
3783 enum lttng_notification_channel_status status =
3784 LTTNG_NOTIFICATION_CHANNEL_STATUS_OK;
3785 struct lttng_payload_view condition_view =
3786 lttng_payload_view_from_payload(
3787 &client->communication.inbound.payload,
3788 0, -1);
3789 size_t expected_condition_size;
3790
3791 /*
3792 * No need to lock client to sample the inbound state as the only
3793 * other thread accessing clients (action executor) only uses the
3794 * outbound state.
3795 */
3796 expected_condition_size = client->communication.inbound.payload.buffer.size;
3797 ret = lttng_condition_create_from_payload(&condition_view, &condition);
3798 if (ret != expected_condition_size) {
3799 ERR("[notification-thread] Malformed condition received from client");
3800 goto end;
3801 }
3802
3803 if (msg_type == LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_SUBSCRIBE) {
3804 ret = notification_thread_client_subscribe(
3805 client, condition, state, &status);
3806 } else {
3807 ret = notification_thread_client_unsubscribe(
3808 client, condition, state, &status);
3809 }
3810
3811 if (ret) {
3812 goto end;
3813 }
3814
3815 /* Set reception state to receive the next message header. */
3816 ret = client_reset_inbound_state(client);
3817 if (ret) {
3818 ERR("[notification-thread] Failed to reset client communication's inbound state");
3819 goto end;
3820 }
3821
3822 ret = client_send_command_reply(client, state, status);
3823 if (ret) {
3824 ERR("[notification-thread] Failed to send reply to notification channel client");
3825 goto end;
3826 }
3827
3828 end:
3829 return ret;
3830 }
3831
3832 static
3833 int client_dispatch_message(struct notification_client *client,
3834 struct notification_thread_state *state)
3835 {
3836 int ret = 0;
3837
3838 if (client->communication.inbound.msg_type !=
3839 LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_HANDSHAKE &&
3840 client->communication.inbound.msg_type !=
3841 LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNKNOWN &&
3842 !client->validated) {
3843 WARN("[notification-thread] client attempted a command before handshake");
3844 ret = -1;
3845 goto end;
3846 }
3847
3848 switch (client->communication.inbound.msg_type) {
3849 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNKNOWN:
3850 {
3851 ret = client_handle_message_unknown(client, state);
3852 break;
3853 }
3854 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_HANDSHAKE:
3855 {
3856 ret = client_handle_message_handshake(client, state);
3857 break;
3858 }
3859 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_SUBSCRIBE:
3860 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNSUBSCRIBE:
3861 {
3862 ret = client_handle_message_subscription(client,
3863 client->communication.inbound.msg_type, state);
3864 break;
3865 }
3866 default:
3867 abort();
3868 }
3869 end:
3870 return ret;
3871 }
3872
3873 /* Incoming data from client. */
3874 int handle_notification_thread_client_in(
3875 struct notification_thread_state *state, int socket)
3876 {
3877 int ret = 0;
3878 struct notification_client *client;
3879 ssize_t recv_ret;
3880 size_t offset;
3881
3882 rcu_read_lock();
3883 client = get_client_from_socket(socket, state);
3884 if (!client) {
3885 /* Internal error, abort. */
3886 ret = -1;
3887 goto end;
3888 }
3889
3890 offset = client->communication.inbound.payload.buffer.size -
3891 client->communication.inbound.bytes_to_receive;
3892 if (client->communication.inbound.expect_creds) {
3893 recv_ret = lttcomm_recv_creds_unix_sock(socket,
3894 client->communication.inbound.payload.buffer.data + offset,
3895 client->communication.inbound.bytes_to_receive,
3896 &client->communication.inbound.creds);
3897 if (recv_ret > 0) {
3898 client->communication.inbound.expect_creds = false;
3899 client->communication.inbound.creds_received = true;
3900 }
3901 } else {
3902 recv_ret = lttcomm_recv_unix_sock_non_block(socket,
3903 client->communication.inbound.payload.buffer.data + offset,
3904 client->communication.inbound.bytes_to_receive);
3905 }
3906 if (recv_ret >= 0) {
3907 client->communication.inbound.bytes_to_receive -= recv_ret;
3908 } else {
3909 goto error_disconnect_client;
3910 }
3911
3912 if (client->communication.inbound.bytes_to_receive != 0) {
3913 /* Message incomplete wait for more data. */
3914 ret = 0;
3915 goto end;
3916 }
3917
3918 assert(client->communication.inbound.bytes_to_receive == 0);
3919
3920 /* Receive fds. */
3921 if (client->communication.inbound.fds_to_receive != 0) {
3922 ret = lttcomm_recv_payload_fds_unix_sock_non_block(
3923 client->socket,
3924 client->communication.inbound.fds_to_receive,
3925 &client->communication.inbound.payload);
3926 if (ret > 0) {
3927 /*
3928 * Fds received. non blocking fds passing is all
3929 * or nothing.
3930 */
3931 ssize_t expected_size;
3932
3933 expected_size = sizeof(int) *
3934 client->communication.inbound
3935 .fds_to_receive;
3936 assert(ret == expected_size);
3937 client->communication.inbound.fds_to_receive = 0;
3938 } else if (ret == 0) {
3939 /* Received nothing. */
3940 ret = 0;
3941 goto end;
3942 } else {
3943 goto error_disconnect_client;
3944 }
3945 }
3946
3947 /* At this point the message is complete.*/
3948 assert(client->communication.inbound.bytes_to_receive == 0 &&
3949 client->communication.inbound.fds_to_receive == 0);
3950 ret = client_dispatch_message(client, state);
3951 if (ret) {
3952 /*
3953 * Only returns an error if this client must be
3954 * disconnected.
3955 */
3956 goto error_disconnect_client;
3957 }
3958
3959 end:
3960 rcu_read_unlock();
3961 return ret;
3962
3963 error_disconnect_client:
3964 ret = notification_thread_client_disconnect(client, state);
3965 goto end;
3966 }
3967
3968 /* Client ready to receive outgoing data. */
3969 int handle_notification_thread_client_out(
3970 struct notification_thread_state *state, int socket)
3971 {
3972 int ret;
3973 struct notification_client *client;
3974 enum client_transmission_status transmission_status;
3975
3976 rcu_read_lock();
3977 client = get_client_from_socket(socket, state);
3978 if (!client) {
3979 /* Internal error, abort. */
3980 ret = -1;
3981 goto end;
3982 }
3983
3984 pthread_mutex_lock(&client->lock);
3985 transmission_status = client_flush_outgoing_queue(client);
3986 pthread_mutex_unlock(&client->lock);
3987
3988 ret = client_handle_transmission_status(
3989 client, transmission_status, state);
3990 if (ret) {
3991 goto end;
3992 }
3993 end:
3994 rcu_read_unlock();
3995 return ret;
3996 }
3997
3998 static
3999 bool evaluate_buffer_usage_condition(const struct lttng_condition *condition,
4000 const struct channel_state_sample *sample,
4001 uint64_t buffer_capacity)
4002 {
4003 bool result = false;
4004 uint64_t threshold;
4005 enum lttng_condition_type condition_type;
4006 const struct lttng_condition_buffer_usage *use_condition = container_of(
4007 condition, struct lttng_condition_buffer_usage,
4008 parent);
4009
4010 if (use_condition->threshold_bytes.set) {
4011 threshold = use_condition->threshold_bytes.value;
4012 } else {
4013 /*
4014 * Threshold was expressed as a ratio.
4015 *
4016 * TODO the threshold (in bytes) of conditions expressed
4017 * as a ratio of total buffer size could be cached to
4018 * forego this double-multiplication or it could be performed
4019 * as fixed-point math.
4020 *
4021 * Note that caching should accommodates the case where the
4022 * condition applies to multiple channels (i.e. don't assume
4023 * that all channels matching my_chann* have the same size...)
4024 */
4025 threshold = (uint64_t) (use_condition->threshold_ratio.value *
4026 (double) buffer_capacity);
4027 }
4028
4029 condition_type = lttng_condition_get_type(condition);
4030 if (condition_type == LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW) {
4031 DBG("[notification-thread] Low buffer usage condition being evaluated: threshold = %" PRIu64 ", highest usage = %" PRIu64,
4032 threshold, sample->highest_usage);
4033
4034 /*
4035 * The low condition should only be triggered once _all_ of the
4036 * streams in a channel have gone below the "low" threshold.
4037 */
4038 if (sample->highest_usage <= threshold) {
4039 result = true;
4040 }
4041 } else {
4042 DBG("[notification-thread] High buffer usage condition being evaluated: threshold = %" PRIu64 ", highest usage = %" PRIu64,
4043 threshold, sample->highest_usage);
4044
4045 /*
4046 * For high buffer usage scenarios, we want to trigger whenever
4047 * _any_ of the streams has reached the "high" threshold.
4048 */
4049 if (sample->highest_usage >= threshold) {
4050 result = true;
4051 }
4052 }
4053
4054 return result;
4055 }
4056
4057 static
4058 bool evaluate_session_consumed_size_condition(
4059 const struct lttng_condition *condition,
4060 uint64_t session_consumed_size)
4061 {
4062 uint64_t threshold;
4063 const struct lttng_condition_session_consumed_size *size_condition =
4064 container_of(condition,
4065 struct lttng_condition_session_consumed_size,
4066 parent);
4067
4068 threshold = size_condition->consumed_threshold_bytes.value;
4069 DBG("[notification-thread] Session consumed size condition being evaluated: threshold = %" PRIu64 ", current size = %" PRIu64,
4070 threshold, session_consumed_size);
4071 return session_consumed_size >= threshold;
4072 }
4073
4074 static
4075 int evaluate_buffer_condition(const struct lttng_condition *condition,
4076 struct lttng_evaluation **evaluation,
4077 const struct notification_thread_state *state,
4078 const struct channel_state_sample *previous_sample,
4079 const struct channel_state_sample *latest_sample,
4080 uint64_t previous_session_consumed_total,
4081 uint64_t latest_session_consumed_total,
4082 struct channel_info *channel_info)
4083 {
4084 int ret = 0;
4085 enum lttng_condition_type condition_type;
4086 const bool previous_sample_available = !!previous_sample;
4087 bool previous_sample_result = false;
4088 bool latest_sample_result;
4089
4090 condition_type = lttng_condition_get_type(condition);
4091
4092 switch (condition_type) {
4093 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
4094 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
4095 if (caa_likely(previous_sample_available)) {
4096 previous_sample_result =
4097 evaluate_buffer_usage_condition(condition,
4098 previous_sample, channel_info->capacity);
4099 }
4100 latest_sample_result = evaluate_buffer_usage_condition(
4101 condition, latest_sample,
4102 channel_info->capacity);
4103 break;
4104 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE:
4105 if (caa_likely(previous_sample_available)) {
4106 previous_sample_result =
4107 evaluate_session_consumed_size_condition(
4108 condition,
4109 previous_session_consumed_total);
4110 }
4111 latest_sample_result =
4112 evaluate_session_consumed_size_condition(
4113 condition,
4114 latest_session_consumed_total);
4115 break;
4116 default:
4117 /* Unknown condition type; internal error. */
4118 abort();
4119 }
4120
4121 if (!latest_sample_result ||
4122 (previous_sample_result == latest_sample_result)) {
4123 /*
4124 * Only trigger on a condition evaluation transition.
4125 *
4126 * NOTE: This edge-triggered logic may not be appropriate for
4127 * future condition types.
4128 */
4129 goto end;
4130 }
4131
4132 if (!evaluation || !latest_sample_result) {
4133 goto end;
4134 }
4135
4136 switch (condition_type) {
4137 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
4138 case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
4139 *evaluation = lttng_evaluation_buffer_usage_create(
4140 condition_type,
4141 latest_sample->highest_usage,
4142 channel_info->capacity);
4143 break;
4144 case LTTNG_CONDITION_TYPE_SESSION_CONSUMED_SIZE:
4145 *evaluation = lttng_evaluation_session_consumed_size_create(
4146 latest_session_consumed_total);
4147 break;
4148 default:
4149 abort();
4150 }
4151
4152 if (!*evaluation) {
4153 ret = -1;
4154 goto end;
4155 }
4156 end:
4157 return ret;
4158 }
4159
4160 static
4161 int client_notification_overflow(struct notification_client *client)
4162 {
4163 int ret = 0;
4164 const struct lttng_notification_channel_message msg = {
4165 .type = (int8_t) LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION_DROPPED,
4166 };
4167
4168 ASSERT_LOCKED(client->lock);
4169
4170 DBG("Dropping notification addressed to client (socket fd = %i)",
4171 client->socket);
4172 if (client->communication.outbound.dropped_notification) {
4173 /*
4174 * The client already has a "notification dropped" message
4175 * in its outgoing queue. Nothing to do since all
4176 * of those messages are coalesced.
4177 */
4178 goto end;
4179 }
4180
4181 client->communication.outbound.dropped_notification = true;
4182 ret = lttng_dynamic_buffer_append(
4183 &client->communication.outbound.payload.buffer, &msg,
4184 sizeof(msg));
4185 if (ret) {
4186 PERROR("Failed to enqueue \"dropped notification\" message in client's (socket fd = %i) outgoing queue",
4187 client->socket);
4188 }
4189 end:
4190 return ret;
4191 }
4192
4193 static int client_handle_transmission_status_wrapper(
4194 struct notification_client *client,
4195 enum client_transmission_status status,
4196 void *user_data)
4197 {
4198 return client_handle_transmission_status(client, status,
4199 (struct notification_thread_state *) user_data);
4200 }
4201
4202 static
4203 int send_evaluation_to_clients(const struct lttng_trigger *trigger,
4204 const struct lttng_evaluation *evaluation,
4205 struct notification_client_list* client_list,
4206 struct notification_thread_state *state,
4207 uid_t object_uid, gid_t object_gid)
4208 {
4209 const struct lttng_credentials creds = {
4210 .uid = LTTNG_OPTIONAL_INIT_VALUE(object_uid),
4211 .gid = LTTNG_OPTIONAL_INIT_VALUE(object_gid),
4212 };
4213
4214 return notification_client_list_send_evaluation(client_list,
4215 trigger, evaluation,
4216 &creds,
4217 client_handle_transmission_status_wrapper, state);
4218 }
4219
4220 /*
4221 * Permission checks relative to notification channel clients are performed
4222 * here. Notice how object, client, and trigger credentials are involved in
4223 * this check.
4224 *
4225 * The `object` credentials are the credentials associated with the "subject"
4226 * of a condition. For instance, a `rotation completed` condition applies
4227 * to a session. When that condition is met, it will produce an evaluation
4228 * against a session. Hence, in this case, the `object` credentials are the
4229 * credentials of the "subject" session.
4230 *
4231 * The `trigger` credentials are the credentials of the user that registered the
4232 * trigger.
4233 *
4234 * The `client` credentials are the credentials of the user that created a given
4235 * notification channel.
4236 *
4237 * In terms of visibility, it is expected that non-privilieged users can only
4238 * register triggers against "their" objects (their own sessions and
4239 * applications they are allowed to interact with). They can then open a
4240 * notification channel and subscribe to notifications associated with those
4241 * triggers.
4242 *
4243 * As for privilieged users, they can register triggers against the objects of
4244 * other users. They can then subscribe to the notifications associated to their
4245 * triggers. Privilieged users _can't_ subscribe to the notifications of
4246 * triggers owned by other users; they must create their own triggers.
4247 *
4248 * This is more a concern of usability than security. It would be difficult for
4249 * a root user reliably subscribe to a specific set of conditions without
4250 * interference from external users (those could, for instance, unregister
4251 * their triggers).
4252 */
4253 LTTNG_HIDDEN
4254 int notification_client_list_send_evaluation(
4255 struct notification_client_list *client_list,
4256 const struct lttng_trigger *trigger,
4257 const struct lttng_evaluation *evaluation,
4258 const struct lttng_credentials *source_object_creds,
4259 report_client_transmission_result_cb client_report,
4260 void *user_data)
4261 {
4262 int ret = 0;
4263 struct lttng_payload msg_payload;
4264 struct notification_client_list_element *client_list_element, *tmp;
4265 const struct lttng_notification notification = {
4266 .trigger = (struct lttng_trigger *) trigger,
4267 .evaluation = (struct lttng_evaluation *) evaluation,
4268 };
4269 struct lttng_notification_channel_message msg_header = {
4270 .type = (int8_t) LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION,
4271 };
4272 const struct lttng_credentials *trigger_creds =
4273 lttng_trigger_get_credentials(trigger);
4274
4275 lttng_payload_init(&msg_payload);
4276
4277 ret = lttng_dynamic_buffer_append(&msg_payload.buffer, &msg_header,
4278 sizeof(msg_header));
4279 if (ret) {
4280 goto end;
4281 }
4282
4283 ret = lttng_notification_serialize(&notification, &msg_payload);
4284 if (ret) {
4285 ERR("[notification-thread] Failed to serialize notification");
4286 ret = -1;
4287 goto end;
4288 }
4289
4290 /* Update payload size. */
4291 ((struct lttng_notification_channel_message *) msg_payload.buffer.data)
4292 ->size = (uint32_t)(
4293 msg_payload.buffer.size - sizeof(msg_header));
4294
4295 /* Update the payload number of fds. */
4296 {
4297 const struct lttng_payload_view pv = lttng_payload_view_from_payload(
4298 &msg_payload, 0, -1);
4299
4300 ((struct lttng_notification_channel_message *)
4301 msg_payload.buffer.data)->fds = (uint32_t)
4302 lttng_payload_view_get_fd_handle_count(&pv);
4303 }
4304
4305 pthread_mutex_lock(&client_list->lock);
4306 cds_list_for_each_entry_safe(client_list_element, tmp,
4307 &client_list->clients_list, node) {
4308 enum client_transmission_status transmission_status;
4309 struct notification_client *client =
4310 client_list_element->client;
4311
4312 ret = 0;
4313 pthread_mutex_lock(&client->lock);
4314 if (!client->communication.active) {
4315 /*
4316 * Skip inactive client (protocol error or
4317 * disconnecting).
4318 */
4319 DBG("Skipping client at it is marked as inactive");
4320 goto skip_client;
4321 }
4322
4323 if (source_object_creds) {
4324 if (client->uid != lttng_credentials_get_uid(source_object_creds) &&
4325 client->gid != lttng_credentials_get_gid(source_object_creds) &&
4326 client->uid != 0) {
4327 /*
4328 * Client is not allowed to monitor this
4329 * object.
4330 */
4331 DBG("[notification-thread] Skipping client at it does not have the object permission to receive notification for this trigger");
4332 goto skip_client;
4333 }
4334 }
4335
4336 if (client->uid != lttng_credentials_get_uid(trigger_creds) && client->gid != lttng_credentials_get_gid(trigger_creds)) {
4337 DBG("[notification-thread] Skipping client at it does not have the permission to receive notification for this trigger");
4338 goto skip_client;
4339 }
4340
4341 DBG("[notification-thread] Sending notification to client (fd = %i, %zu bytes)",
4342 client->socket, msg_payload.buffer.size);
4343
4344 if (client_has_outbound_data_left(client)) {
4345 /*
4346 * Outgoing data is already buffered for this client;
4347 * drop the notification and enqueue a "dropped
4348 * notification" message if this is the first dropped
4349 * notification since the socket spilled-over to the
4350 * queue.
4351 */
4352 ret = client_notification_overflow(client);
4353 if (ret) {
4354 /* Fatal error. */
4355 goto skip_client;
4356 }
4357 }
4358
4359 ret = lttng_payload_copy(&msg_payload, &client->communication.outbound.payload);
4360 if (ret) {
4361 /* Fatal error. */
4362 goto skip_client;
4363 }
4364
4365 transmission_status = client_flush_outgoing_queue(client);
4366 pthread_mutex_unlock(&client->lock);
4367 ret = client_report(client, transmission_status, user_data);
4368 if (ret) {
4369 /* Fatal error. */
4370 goto end_unlock_list;
4371 }
4372
4373 continue;
4374
4375 skip_client:
4376 pthread_mutex_unlock(&client->lock);
4377 if (ret) {
4378 /* Fatal error. */
4379 goto end_unlock_list;
4380 }
4381 }
4382 ret = 0;
4383
4384 end_unlock_list:
4385 pthread_mutex_unlock(&client_list->lock);
4386 end:
4387 lttng_payload_reset(&msg_payload);
4388 return ret;
4389 }
4390
4391 static
4392 struct lttng_event_notifier_notification *recv_one_event_notifier_notification(
4393 int notification_pipe_read_fd, enum lttng_domain_type domain)
4394 {
4395 int ret;
4396 uint64_t token;
4397 struct lttng_event_notifier_notification *notification = NULL;
4398 char *capture_buffer = NULL;
4399 size_t capture_buffer_size;
4400 void *reception_buffer;
4401 size_t reception_size;
4402
4403 struct lttng_ust_abi_event_notifier_notification ust_notification;
4404 struct lttng_kernel_event_notifier_notification kernel_notification;
4405
4406 /* Init lttng_event_notifier_notification */
4407 switch(domain) {
4408 case LTTNG_DOMAIN_UST:
4409 reception_buffer = (void *) &ust_notification;
4410 reception_size = sizeof(ust_notification);
4411 break;
4412 case LTTNG_DOMAIN_KERNEL:
4413 reception_buffer = (void *) &kernel_notification;
4414 reception_size = sizeof(kernel_notification);
4415 break;
4416 default:
4417 abort();
4418 }
4419
4420 /*
4421 * The monitoring pipe only holds messages smaller than PIPE_BUF,
4422 * ensuring that read/write of tracer notifications are atomic.
4423 */
4424 ret = lttng_read(notification_pipe_read_fd, reception_buffer,
4425 reception_size);
4426 if (ret != reception_size) {
4427 PERROR("Failed to read from event source notification pipe: fd = %d, size to read = %zu, ret = %d",
4428 notification_pipe_read_fd, reception_size, ret);
4429 ret = -1;
4430 goto end;
4431 }
4432
4433 switch(domain) {
4434 case LTTNG_DOMAIN_UST:
4435 token = ust_notification.token;
4436 capture_buffer_size = ust_notification.capture_buf_size;
4437 break;
4438 case LTTNG_DOMAIN_KERNEL:
4439 token = kernel_notification.token;
4440 capture_buffer_size = kernel_notification.capture_buf_size;
4441 break;
4442 default:
4443 abort();
4444 }
4445
4446 if (capture_buffer_size == 0) {
4447 capture_buffer = NULL;
4448 goto skip_capture;
4449 }
4450
4451 if (capture_buffer_size > MAX_CAPTURE_SIZE) {
4452 ERR("[notification-thread] Event notifier has a capture payload size which exceeds the maximum allowed size: capture_payload_size = %zu bytes, max allowed size = %d bytes",
4453 capture_buffer_size, MAX_CAPTURE_SIZE);
4454 goto end;
4455 }
4456
4457 capture_buffer = zmalloc(capture_buffer_size);
4458 if (!capture_buffer) {
4459 ERR("[notification-thread] Failed to allocate capture buffer");
4460 goto end;
4461 }
4462
4463 /* Fetch additional payload (capture). */
4464 ret = lttng_read(notification_pipe_read_fd, capture_buffer, capture_buffer_size);
4465 if (ret != capture_buffer_size) {
4466 ERR("[notification-thread] Failed to read from event source pipe (fd = %i)",
4467 notification_pipe_read_fd);
4468 goto end;
4469 }
4470
4471 skip_capture:
4472 notification = lttng_event_notifier_notification_create(token, domain,
4473 capture_buffer, capture_buffer_size);
4474 if (notification == NULL) {
4475 goto end;
4476 }
4477
4478 /*
4479 * Ownership transfered to the lttng_event_notifier_notification object.
4480 */
4481 capture_buffer = NULL;
4482
4483 end:
4484 free(capture_buffer);
4485 return notification;
4486 }
4487
4488 static
4489 int dispatch_one_event_notifier_notification(struct notification_thread_state *state,
4490 struct lttng_event_notifier_notification *notification)
4491 {
4492 struct cds_lfht_node *node;
4493 struct cds_lfht_iter iter;
4494 struct notification_trigger_tokens_ht_element *element;
4495 enum lttng_trigger_status trigger_status;
4496 struct lttng_evaluation *evaluation = NULL;
4497 enum action_executor_status executor_status;
4498 struct notification_client_list *client_list = NULL;
4499 const char *trigger_name;
4500 int ret;
4501 unsigned int capture_count = 0;
4502
4503 /* Find triggers associated with this token. */
4504 rcu_read_lock();
4505 cds_lfht_lookup(state->trigger_tokens_ht,
4506 hash_key_u64(&notification->tracer_token, lttng_ht_seed),
4507 match_trigger_token, &notification->tracer_token, &iter);
4508 node = cds_lfht_iter_get_node(&iter);
4509 if (caa_unlikely(!node)) {
4510 /*
4511 * This is not an error, slow consumption of the tracer
4512 * notifications can lead to situations where a trigger is
4513 * removed but we still get tracer notifications matching a
4514 * trigger that no longer exists.
4515 */
4516 ret = 0;
4517 goto end_unlock;
4518 }
4519
4520 element = caa_container_of(node,
4521 struct notification_trigger_tokens_ht_element,
4522 node);
4523
4524 if (!lttng_trigger_should_fire(element->trigger)) {
4525 ret = 0;
4526 goto end_unlock;
4527 }
4528
4529 lttng_trigger_fire(element->trigger);
4530
4531 trigger_status = lttng_trigger_get_name(element->trigger, &trigger_name);
4532 assert(trigger_status == LTTNG_TRIGGER_STATUS_OK);
4533
4534 if (lttng_condition_on_event_get_capture_descriptor_count(
4535 lttng_trigger_get_const_condition(element->trigger),
4536 &capture_count) != LTTNG_CONDITION_STATUS_OK) {
4537 ERR("Failed to get capture count");
4538 ret = -1;
4539 goto end;
4540 }
4541
4542 if (!notification->capture_buffer && capture_count != 0) {
4543 ERR("Expected capture but capture buffer is null");
4544 ret = -1;
4545 goto end;
4546 }
4547
4548 evaluation = lttng_evaluation_on_event_create(
4549 container_of(lttng_trigger_get_const_condition(
4550 element->trigger),
4551 struct lttng_condition_on_event,
4552 parent),
4553 trigger_name,
4554 notification->capture_buffer,
4555 notification->capture_buf_size, false);
4556
4557 if (evaluation == NULL) {
4558 ERR("[notification-thread] Failed to create event rule hit evaluation while creating and enqueuing action executor job");
4559 ret = -1;
4560 goto end_unlock;
4561 }
4562 client_list = get_client_list_from_condition(state,
4563 lttng_trigger_get_const_condition(element->trigger));
4564 executor_status = action_executor_enqueue(state->executor,
4565 element->trigger, evaluation, NULL, client_list);
4566 switch (executor_status) {
4567 case ACTION_EXECUTOR_STATUS_OK:
4568 ret = 0;
4569 break;
4570 case ACTION_EXECUTOR_STATUS_OVERFLOW:
4571 {
4572 struct notification_client_list_element *client_list_element,
4573 *tmp;
4574
4575 /*
4576 * Not a fatal error; this is expected and simply means the
4577 * executor has too much work queued already.
4578 */
4579 ret = 0;
4580
4581 /* No clients subscribed to notifications for this trigger. */
4582 if (!client_list) {
4583 break;
4584 }
4585
4586 /* Warn clients that a notification (or more) was dropped. */
4587 pthread_mutex_lock(&client_list->lock);
4588 cds_list_for_each_entry_safe(client_list_element, tmp,
4589 &client_list->clients_list, node) {
4590 enum client_transmission_status transmission_status;
4591 struct notification_client *client =
4592 client_list_element->client;
4593
4594 pthread_mutex_lock(&client->lock);
4595 ret = client_notification_overflow(client);
4596 if (ret) {
4597 /* Fatal error. */
4598 goto next_client;
4599 }
4600
4601 transmission_status =
4602 client_flush_outgoing_queue(client);
4603 ret = client_handle_transmission_status(
4604 client, transmission_status, state);
4605 if (ret) {
4606 /* Fatal error. */
4607 goto next_client;
4608 }
4609 next_client:
4610 pthread_mutex_unlock(&client->lock);
4611 if (ret) {
4612 break;
4613 }
4614 }
4615
4616 pthread_mutex_unlock(&client_list->lock);
4617 break;
4618 }
4619 case ACTION_EXECUTOR_STATUS_INVALID:
4620 case ACTION_EXECUTOR_STATUS_ERROR:
4621 /* Fatal error, shut down everything. */
4622 ERR("Fatal error encoutered while enqueuing action to the action executor");
4623 ret = -1;
4624 goto end_unlock;
4625 default:
4626 /* Unhandled error. */
4627 abort();
4628 }
4629
4630 end_unlock:
4631 notification_client_list_put(client_list);
4632 rcu_read_unlock();
4633 end:
4634 return ret;
4635 }
4636
4637 static
4638 int handle_one_event_notifier_notification(
4639 struct notification_thread_state *state,
4640 int pipe, enum lttng_domain_type domain)
4641 {
4642 int ret = 0;
4643 struct lttng_event_notifier_notification *notification = NULL;
4644
4645 notification = recv_one_event_notifier_notification(pipe, domain);
4646 if (notification == NULL) {
4647 /* Reception failed, don't consider it fatal. */
4648 ERR("[notification-thread] Error receiving an event notifier notification from tracer: fd = %i, domain = %s",
4649 pipe, lttng_domain_type_str(domain));
4650 goto end;
4651 }
4652
4653 ret = dispatch_one_event_notifier_notification(state, notification);
4654 if (ret) {
4655 ERR("[notification-thread] Error dispatching an event notifier notification from tracer: fd = %i, domain = %s",
4656 pipe, lttng_domain_type_str(domain));
4657 goto end;
4658 }
4659
4660 end:
4661 lttng_event_notifier_notification_destroy(notification);
4662 return ret;
4663 }
4664
4665 int handle_notification_thread_event_notification(struct notification_thread_state *state,
4666 int pipe, enum lttng_domain_type domain)
4667 {
4668 return handle_one_event_notifier_notification(state, pipe, domain);
4669 }
4670
4671 int handle_notification_thread_channel_sample(
4672 struct notification_thread_state *state, int pipe,
4673 enum lttng_domain_type domain)
4674 {
4675 int ret = 0;
4676 struct lttcomm_consumer_channel_monitor_msg sample_msg;
4677 struct channel_info *channel_info;
4678 struct cds_lfht_node *node;
4679 struct cds_lfht_iter iter;
4680 struct lttng_channel_trigger_list *trigger_list;
4681 struct lttng_trigger_list_element *trigger_list_element;
4682 bool previous_sample_available = false;
4683 struct channel_state_sample previous_sample, latest_sample;
4684 uint64_t previous_session_consumed_total, latest_session_consumed_total;
4685 struct lttng_credentials channel_creds;
4686
4687 /*
4688 * The monitoring pipe only holds messages smaller than PIPE_BUF,
4689 * ensuring that read/write of sampling messages are atomic.
4690 */
4691 ret = lttng_read(pipe, &sample_msg, sizeof(sample_msg));
4692 if (ret != sizeof(sample_msg)) {
4693 ERR("[notification-thread] Failed to read from monitoring pipe (fd = %i)",
4694 pipe);
4695 ret = -1;
4696 goto end;
4697 }
4698
4699 ret = 0;
4700 latest_sample.key.key = sample_msg.key;
4701 latest_sample.key.domain = domain;
4702 latest_sample.highest_usage = sample_msg.highest;
4703 latest_sample.lowest_usage = sample_msg.lowest;
4704 latest_sample.channel_total_consumed = sample_msg.total_consumed;
4705
4706 rcu_read_lock();
4707
4708 /* Retrieve the channel's informations */
4709 cds_lfht_lookup(state->channels_ht,
4710 hash_channel_key(&latest_sample.key),
4711 match_channel_info,
4712 &latest_sample.key,
4713 &iter);
4714 node = cds_lfht_iter_get_node(&iter);
4715 if (caa_unlikely(!node)) {
4716 /*
4717 * Not an error since the consumer can push a sample to the pipe
4718 * and the rest of the session daemon could notify us of the
4719 * channel's destruction before we get a chance to process that
4720 * sample.
4721 */
4722 DBG("[notification-thread] Received a sample for an unknown channel from consumerd, key = %" PRIu64 " in %s domain",
4723 latest_sample.key.key,
4724 lttng_domain_type_str(domain));
4725 goto end_unlock;
4726 }
4727 channel_info = caa_container_of(node, struct channel_info,
4728 channels_ht_node);
4729 DBG("[notification-thread] Handling channel sample for channel %s (key = %" PRIu64 ") in session %s (highest usage = %" PRIu64 ", lowest usage = %" PRIu64", total consumed = %" PRIu64")",
4730 channel_info->name,
4731 latest_sample.key.key,
4732 channel_info->session_info->name,
4733 latest_sample.highest_usage,
4734 latest_sample.lowest_usage,
4735 latest_sample.channel_total_consumed);
4736
4737 previous_session_consumed_total =
4738 channel_info->session_info->consumed_data_size;
4739
4740 /* Retrieve the channel's last sample, if it exists, and update it. */
4741 cds_lfht_lookup(state->channel_state_ht,
4742 hash_channel_key(&latest_sample.key),
4743 match_channel_state_sample,
4744 &latest_sample.key,
4745 &iter);
4746 node = cds_lfht_iter_get_node(&iter);
4747 if (caa_likely(node)) {
4748 struct channel_state_sample *stored_sample;
4749
4750 /* Update the sample stored. */
4751 stored_sample = caa_container_of(node,
4752 struct channel_state_sample,
4753 channel_state_ht_node);
4754
4755 memcpy(&previous_sample, stored_sample,
4756 sizeof(previous_sample));
4757 stored_sample->highest_usage = latest_sample.highest_usage;
4758 stored_sample->lowest_usage = latest_sample.lowest_usage;
4759 stored_sample->channel_total_consumed = latest_sample.channel_total_consumed;
4760 previous_sample_available = true;
4761
4762 latest_session_consumed_total =
4763 previous_session_consumed_total +
4764 (latest_sample.channel_total_consumed - previous_sample.channel_total_consumed);
4765 } else {
4766 /*
4767 * This is the channel's first sample, allocate space for and
4768 * store the new sample.
4769 */
4770 struct channel_state_sample *stored_sample;
4771
4772 stored_sample = zmalloc(sizeof(*stored_sample));
4773 if (!stored_sample) {
4774 ret = -1;
4775 goto end_unlock;
4776 }
4777
4778 memcpy(stored_sample, &latest_sample, sizeof(*stored_sample));
4779 cds_lfht_node_init(&stored_sample->channel_state_ht_node);
4780 cds_lfht_add(state->channel_state_ht,
4781 hash_channel_key(&stored_sample->key),
4782 &stored_sample->channel_state_ht_node);
4783
4784 latest_session_consumed_total =
4785 previous_session_consumed_total +
4786 latest_sample.channel_total_consumed;
4787 }
4788
4789 channel_info->session_info->consumed_data_size =
4790 latest_session_consumed_total;
4791
4792 /* Find triggers associated with this channel. */
4793 cds_lfht_lookup(state->channel_triggers_ht,
4794 hash_channel_key(&latest_sample.key),
4795 match_channel_trigger_list,
4796 &latest_sample.key,
4797 &iter);
4798 node = cds_lfht_iter_get_node(&iter);
4799 if (caa_likely(!node)) {
4800 goto end_unlock;
4801 }
4802
4803 channel_creds = (typeof(channel_creds)) {
4804 .uid = LTTNG_OPTIONAL_INIT_VALUE(channel_info->session_info->uid),
4805 .gid = LTTNG_OPTIONAL_INIT_VALUE(channel_info->session_info->gid),
4806 };
4807
4808 trigger_list = caa_container_of(node, struct lttng_channel_trigger_list,
4809 channel_triggers_ht_node);
4810 cds_list_for_each_entry(trigger_list_element, &trigger_list->list,
4811 node) {
4812 const struct lttng_condition *condition;
4813 struct lttng_trigger *trigger;
4814 struct notification_client_list *client_list = NULL;
4815 struct lttng_evaluation *evaluation = NULL;
4816 enum action_executor_status executor_status;
4817
4818 ret = 0;
4819 trigger = trigger_list_element->trigger;
4820 condition = lttng_trigger_get_const_condition(trigger);
4821 assert(condition);
4822
4823 /*
4824 * Check if any client is subscribed to the result of this
4825 * evaluation.
4826 */
4827 client_list = get_client_list_from_condition(state, condition);
4828
4829 ret = evaluate_buffer_condition(condition, &evaluation, state,
4830 previous_sample_available ? &previous_sample : NULL,
4831 &latest_sample,
4832 previous_session_consumed_total,
4833 latest_session_consumed_total,
4834 channel_info);
4835 if (caa_unlikely(ret)) {
4836 goto put_list;
4837 }
4838
4839 if (caa_likely(!evaluation)) {
4840 goto put_list;
4841 }
4842
4843 if (!lttng_trigger_should_fire(trigger)) {
4844 goto put_list;
4845 }
4846
4847 lttng_trigger_fire(trigger);
4848
4849 /*
4850 * Ownership of `evaluation` transferred to the action executor
4851 * no matter the result.
4852 */
4853 executor_status = action_executor_enqueue(state->executor,
4854 trigger, evaluation, &channel_creds,
4855 client_list);
4856 evaluation = NULL;
4857 switch (executor_status) {
4858 case ACTION_EXECUTOR_STATUS_OK:
4859 break;
4860 case ACTION_EXECUTOR_STATUS_ERROR:
4861 case ACTION_EXECUTOR_STATUS_INVALID:
4862 /*
4863 * TODO Add trigger identification (name/id) when
4864 * it is added to the API.
4865 */
4866 ERR("Fatal error occurred while enqueuing action associated with buffer-condition trigger");
4867 ret = -1;
4868 goto put_list;
4869 case ACTION_EXECUTOR_STATUS_OVERFLOW:
4870 /*
4871 * TODO Add trigger identification (name/id) when
4872 * it is added to the API.
4873 *
4874 * Not a fatal error.
4875 */
4876 WARN("No space left when enqueuing action associated with buffer-condition trigger");
4877 ret = 0;
4878 goto put_list;
4879 default:
4880 abort();
4881 }
4882
4883 put_list:
4884 notification_client_list_put(client_list);
4885 if (caa_unlikely(ret)) {
4886 break;
4887 }
4888 }
4889 end_unlock:
4890 rcu_read_unlock();
4891 end:
4892 return ret;
4893 }
This page took 0.224531 seconds and 5 git commands to generate.