Fix: sessiond: notification: use after free of trigger object
[lttng-tools.git] / src / bin / lttng-sessiond / notification-thread-events.c
CommitLineData
ab0ee2ca 1/*
ab5be9fa 2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
ab0ee2ca 3 *
ab5be9fa 4 * SPDX-License-Identifier: GPL-2.0-only
ab0ee2ca 5 *
ab0ee2ca
JG
6 */
7
f2b3ef9f
JG
8#include "lttng/action/action.h"
9#include "lttng/trigger/trigger-internal.h"
ab0ee2ca
JG
10#define _LGPL_SOURCE
11#include <urcu.h>
12#include <urcu/rculfhash.h>
13
ab0ee2ca
JG
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>
9b63a4aa 23#include <lttng/action/action-internal.h>
93ac2c44
JR
24#include <lttng/action/group-internal.h>
25#include <lttng/domain-internal.h>
ab0ee2ca
JG
26#include <lttng/notification/notification-internal.h>
27#include <lttng/condition/condition-internal.h>
28#include <lttng/condition/buffer-usage-internal.h>
e8360425 29#include <lttng/condition/session-consumed-size-internal.h>
ea9a44f0 30#include <lttng/condition/session-rotation-internal.h>
e393070a 31#include <lttng/condition/on-event-internal.h>
d02d7404 32#include <lttng/domain-internal.h>
ab0ee2ca 33#include <lttng/notification/channel-internal.h>
85c06c44 34#include <lttng/trigger/trigger-internal.h>
959e3c66 35#include <lttng/event-rule/event-rule-internal.h>
1da26331 36
ab0ee2ca
JG
37#include <time.h>
38#include <unistd.h>
39#include <assert.h>
40#include <inttypes.h>
d53ea4e4 41#include <fcntl.h>
ab0ee2ca 42
e98a976a 43#include "condition-internal.h"
90aa04a1 44#include "event-notifier-error-accounting.h"
1da26331
JG
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
ab0ee2ca
JG
51#define CLIENT_POLL_MASK_IN (LPOLLIN | LPOLLERR | LPOLLHUP | LPOLLRDHUP)
52#define CLIENT_POLL_MASK_IN_OUT (CLIENT_POLL_MASK_IN | LPOLLOUT)
53
82b3cbf4
JR
54/* The tracers currently limit the capture size to PIPE_BUF (4kb on linux). */
55#define MAX_CAPTURE_SIZE (PIPE_BUF)
56
51eab943
JG
57enum 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
ab0ee2ca 64struct lttng_trigger_list_element {
9e0bb80e 65 /* No ownership of the trigger object is assumed. */
f2b3ef9f 66 struct lttng_trigger *trigger;
ab0ee2ca
JG
67 struct cds_list_head node;
68};
69
70struct lttng_channel_trigger_list {
71 struct channel_key channel_key;
ea9a44f0 72 /* List of struct lttng_trigger_list_element. */
ab0ee2ca 73 struct cds_list_head list;
ea9a44f0 74 /* Node in the channel_triggers_ht */
ab0ee2ca 75 struct cds_lfht_node channel_triggers_ht_node;
83b934ad
MD
76 /* call_rcu delayed reclaim. */
77 struct rcu_head rcu_node;
ab0ee2ca
JG
78};
79
ea9a44f0
JG
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 */
89struct 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
ab0ee2ca
JG
121struct lttng_trigger_ht_element {
122 struct lttng_trigger *trigger;
123 struct cds_lfht_node node;
242388e4 124 struct cds_lfht_node node_by_name_uid;
091fa780 125 struct cds_list_head client_list_trigger_node;
83b934ad
MD
126 /* call_rcu delayed reclaim. */
127 struct rcu_head rcu_node;
ab0ee2ca
JG
128};
129
130struct lttng_condition_list_element {
131 struct lttng_condition *condition;
132 struct cds_list_head node;
133};
134
ab0ee2ca
JG
135struct 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;
e8360425 140 uint64_t channel_total_consumed;
83b934ad
MD
141 /* call_rcu delayed reclaim. */
142 struct rcu_head rcu_node;
ab0ee2ca
JG
143};
144
e4db5ace 145static unsigned long hash_channel_key(struct channel_key *key);
ed327204 146static int evaluate_buffer_condition(const struct lttng_condition *condition,
e4db5ace 147 struct lttng_evaluation **evaluation,
e8360425
JD
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);
e4db5ace 154static
9b63a4aa
JG
155int send_evaluation_to_clients(const struct lttng_trigger *trigger,
156 const struct lttng_evaluation *evaluation,
e4db5ace
JR
157 struct notification_client_list *client_list,
158 struct notification_thread_state *state,
159 uid_t channel_uid, gid_t channel_gid);
160
8abe313a 161
ea9a44f0 162/* session_info API */
8abe313a
JG
163static
164void session_info_destroy(void *_data);
165static
166void session_info_get(struct session_info *session_info);
167static
168void session_info_put(struct session_info *session_info);
169static
170struct session_info *session_info_create(const char *name,
ea9a44f0 171 uid_t uid, gid_t gid,
1eee26c5
JG
172 struct lttng_session_trigger_list *trigger_list,
173 struct cds_lfht *sessions_ht);
8abe313a
JG
174static
175void session_info_add_channel(struct session_info *session_info,
176 struct channel_info *channel_info);
177static
178void session_info_remove_channel(struct session_info *session_info,
179 struct channel_info *channel_info);
180
ea9a44f0
JG
181/* lttng_session_trigger_list API */
182static
183struct lttng_session_trigger_list *lttng_session_trigger_list_create(
184 const char *session_name,
185 struct cds_lfht *session_triggers_ht);
186static
187struct lttng_session_trigger_list *lttng_session_trigger_list_build(
188 const struct notification_thread_state *state,
189 const char *session_name);
190static
191void lttng_session_trigger_list_destroy(
192 struct lttng_session_trigger_list *list);
193static
194int lttng_session_trigger_list_add(struct lttng_session_trigger_list *list,
f2b3ef9f 195 struct lttng_trigger *trigger);
ea9a44f0 196
f2b3ef9f
JG
197static
198int client_handle_transmission_status(
199 struct notification_client *client,
200 enum client_transmission_status transmission_status,
201 struct notification_thread_state *state);
ea9a44f0 202
8b524060
FD
203static
204int handle_one_event_notifier_notification(
205 struct notification_thread_state *state,
206 int pipe, enum lttng_domain_type domain);
207
242388e4
JR
208static
209void free_lttng_trigger_ht_element_rcu(struct rcu_head *node);
210
ab0ee2ca 211static
ac1889bf 212int match_client_socket(struct cds_lfht_node *node, const void *key)
ab0ee2ca
JG
213{
214 /* This double-cast is intended to supress pointer-to-cast warning. */
ac1889bf
JG
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);
ab0ee2ca 218
ac1889bf
JG
219 return client->socket == socket;
220}
221
222static
223int 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);
ab0ee2ca 229
ac1889bf 230 return client->id == id;
ab0ee2ca
JG
231}
232
233static
234int 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
51eab943
JG
246static
247int 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
ab0ee2ca
JG
258static
259int 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
271static
272int 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
284static
242388e4 285int match_trigger(struct cds_lfht_node *node, const void *key)
ab0ee2ca 286{
242388e4
JR
287 struct lttng_trigger *trigger_key = (struct lttng_trigger *) key;
288 struct lttng_trigger_ht_element *trigger_ht_element;
ab0ee2ca 289
242388e4 290 trigger_ht_element = caa_container_of(node, struct lttng_trigger_ht_element,
ab0ee2ca 291 node);
ab0ee2ca 292
242388e4 293 return !!lttng_trigger_is_equal(trigger_key, trigger_ht_element->trigger);
ab0ee2ca
JG
294}
295
e7c93cf9
JR
296static
297int 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
ab0ee2ca
JG
307static
308int 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;
f82f93a1 312 const struct lttng_condition *condition;
ab0ee2ca
JG
313
314 assert(condition_key);
315
316 client_list = caa_container_of(node, struct notification_client_list,
505b2d90 317 notification_trigger_clients_ht_node);
091fa780 318 condition = client_list->condition;
ab0ee2ca
JG
319
320 return !!lttng_condition_is_equal(condition_key, condition);
321}
322
f82f93a1
JG
323static
324int 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
6900ae81
FD
333static
334const 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
242388e4
JR
365/*
366 * Match trigger based on name and credentials only.
367 * Name duplication is NOT allowed for the same uid.
368 */
369static
370int 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
403end:
404 return match;
405}
406
407/*
408 * Hash trigger based on name and credentials only.
409 */
410static
411unsigned 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
e4db5ace
JR
430static
431unsigned 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
ac1889bf
JG
440static
441unsigned long hash_client_socket(int socket)
442{
443 return hash_key_ulong((void *) (unsigned long) socket, lttng_ht_seed);
444}
445
446static
447unsigned long hash_client_id(notification_client_id id)
448{
449 return hash_key_u64(&id, lttng_ht_seed);
450}
451
f82f93a1
JG
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 */
460static
461enum 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:
e742b055 468 return LTTNG_OBJECT_TYPE_CHANNEL;
f82f93a1
JG
469 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_ONGOING:
470 case LTTNG_CONDITION_TYPE_SESSION_ROTATION_COMPLETED:
471 return LTTNG_OBJECT_TYPE_SESSION;
d602bd6a 472 case LTTNG_CONDITION_TYPE_ON_EVENT:
959e3c66 473 return LTTNG_OBJECT_TYPE_NONE;
f82f93a1
JG
474 default:
475 return LTTNG_OBJECT_TYPE_UNKNOWN;
476 }
477}
478
83b934ad
MD
479static
480void free_channel_info_rcu(struct rcu_head *node)
481{
482 free(caa_container_of(node, struct channel_info, rcu_node));
483}
484
ab0ee2ca
JG
485static
486void channel_info_destroy(struct channel_info *channel_info)
487{
488 if (!channel_info) {
489 return;
490 }
491
8abe313a
JG
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);
ab0ee2ca 496 }
8abe313a
JG
497 if (channel_info->name) {
498 free(channel_info->name);
ab0ee2ca 499 }
83b934ad
MD
500 call_rcu(&channel_info->rcu_node, free_channel_info_rcu);
501}
502
503static
504void free_session_info_rcu(struct rcu_head *node)
505{
506 free(caa_container_of(node, struct session_info, rcu_node));
ab0ee2ca
JG
507}
508
8abe313a 509/* Don't call directly, use the ref-counting mechanism. */
ab0ee2ca 510static
8abe313a 511void session_info_destroy(void *_data)
ab0ee2ca 512{
8abe313a 513 struct session_info *session_info = _data;
3b68d0a3 514 int ret;
ab0ee2ca 515
8abe313a
JG
516 assert(session_info);
517 if (session_info->channel_infos_ht) {
3b68d0a3
JR
518 ret = cds_lfht_destroy(session_info->channel_infos_ht, NULL);
519 if (ret) {
4c3f302b 520 ERR("[notification-thread] Failed to destroy channel information hash table");
3b68d0a3 521 }
8abe313a 522 }
ea9a44f0 523 lttng_session_trigger_list_destroy(session_info->trigger_list);
1eee26c5
JG
524
525 rcu_read_lock();
526 cds_lfht_del(session_info->sessions_ht,
527 &session_info->sessions_ht_node);
528 rcu_read_unlock();
8abe313a 529 free(session_info->name);
83b934ad 530 call_rcu(&session_info->rcu_node, free_session_info_rcu);
8abe313a 531}
ab0ee2ca 532
8abe313a
JG
533static
534void 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
542static
543void session_info_put(struct session_info *session_info)
544{
545 if (!session_info) {
546 return;
ab0ee2ca 547 }
8abe313a
JG
548 lttng_ref_put(&session_info->ref);
549}
550
551static
ea9a44f0 552struct session_info *session_info_create(const char *name, uid_t uid, gid_t gid,
1eee26c5
JG
553 struct lttng_session_trigger_list *trigger_list,
554 struct cds_lfht *sessions_ht)
8abe313a
JG
555{
556 struct session_info *session_info;
ab0ee2ca 557
8abe313a 558 assert(name);
ab0ee2ca 559
8abe313a
JG
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) {
ab0ee2ca
JG
569 goto error;
570 }
8abe313a
JG
571
572 cds_lfht_node_init(&session_info->sessions_ht_node);
573 session_info->name = strdup(name);
574 if (!session_info->name) {
ab0ee2ca
JG
575 goto error;
576 }
8abe313a
JG
577 session_info->uid = uid;
578 session_info->gid = gid;
ea9a44f0 579 session_info->trigger_list = trigger_list;
1eee26c5 580 session_info->sessions_ht = sessions_ht;
8abe313a
JG
581end:
582 return session_info;
583error:
584 session_info_put(session_info);
585 return NULL;
586}
587
588static
589void 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
599static
600void 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
609static
610struct 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
ab0ee2ca 620 cds_lfht_node_init(&channel_info->channels_ht_node);
8abe313a
JG
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;
ab0ee2ca 638end:
8abe313a 639 return channel_info;
ab0ee2ca 640error:
8abe313a 641 channel_info_destroy(channel_info);
ab0ee2ca
JG
642 return NULL;
643}
644
f2b3ef9f 645LTTNG_HIDDEN
505b2d90
JG
646bool notification_client_list_get(struct notification_client_list *list)
647{
648 return urcu_ref_get_unless_zero(&list->ref);
649}
650
651static
652void 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
658static
659void 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
091fa780
FD
665 lttng_condition_put(list->condition);
666
505b2d90
JG
667 if (list->notification_trigger_clients_ht) {
668 rcu_read_lock();
091fa780 669
505b2d90
JG
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,
091fa780 676 &list->clients_list, node) {
505b2d90
JG
677 free(client_list_element);
678 }
091fa780
FD
679
680 assert(cds_list_empty(&list->triggers_list));
681
505b2d90
JG
682 pthread_mutex_destroy(&list->lock);
683 call_rcu(&list->rcu_node, free_notification_client_list_rcu);
684}
685
091fa780
FD
686static
687bool 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
505b2d90
JG
706static
707struct notification_client_list *notification_client_list_create(
091fa780
FD
708 struct notification_thread_state *state,
709 const struct lttng_condition *condition)
505b2d90 710{
091fa780
FD
711 struct notification_client *client;
712 struct cds_lfht_iter iter;
713 struct notification_client_list *client_list;
505b2d90 714
091fa780 715 client_list = zmalloc(sizeof(*client_list));
505b2d90 716 if (!client_list) {
091fa780
FD
717 PERROR("Failed to allocate notification client list");
718 goto end;
505b2d90 719 }
091fa780 720
505b2d90 721 pthread_mutex_init(&client_list->lock, NULL);
091fa780
FD
722 /*
723 * The trigger that owns the condition has the first reference to this
724 * client list.
725 */
505b2d90
JG
726 urcu_ref_init(&client_list->ref);
727 cds_lfht_node_init(&client_list->notification_trigger_clients_ht_node);
091fa780
FD
728 CDS_INIT_LIST_HEAD(&client_list->clients_list);
729 CDS_INIT_LIST_HEAD(&client_list->triggers_list);
505b2d90 730
091fa780
FD
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;
505b2d90 742
091fa780
FD
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 }
505b2d90 751
091fa780
FD
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 =
505b2d90
JG
758 state->notification_trigger_clients_ht;
759
760 rcu_read_lock();
091fa780
FD
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);
505b2d90 769 rcu_read_unlock();
091fa780
FD
770 goto end;
771
772error_put_client_list:
773 notification_client_list_put(client_list);
774 client_list = NULL;
775
776end:
777 return client_list;
505b2d90
JG
778}
779
505b2d90
JG
780void 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. */
ed327204
JG
789static
790struct 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;
505b2d90 796 struct notification_client_list *list = NULL;
ed327204 797
505b2d90 798 rcu_read_lock();
ed327204
JG
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);
505b2d90
JG
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 }
ed327204 810
505b2d90
JG
811 rcu_read_unlock();
812 return list;
ed327204
JG
813}
814
e4db5ace 815static
f82f93a1
JG
816int 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)
e4db5ace
JR
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;
e4db5ace 829
505b2d90
JG
830 rcu_read_lock();
831
f82f93a1 832 /* Find the channel associated with the condition. */
e4db5ace 833 cds_lfht_for_each_entry(state->channel_triggers_ht, &iter,
f82f93a1 834 channel_trigger_list, channel_triggers_ht_node) {
e4db5ace
JR
835 struct lttng_trigger_list_element *element;
836
837 cds_list_for_each_entry(element, &channel_trigger_list->list, node) {
9b63a4aa 838 const struct lttng_condition *current_condition =
f82f93a1 839 lttng_trigger_get_const_condition(
e4db5ace
JR
840 element->trigger);
841
842 assert(current_condition);
843 if (!lttng_condition_is_equal(condition,
2ae99f0b 844 current_condition)) {
e4db5ace
JR
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. */
f82f93a1 860 DBG("[notification-thread] No known channel associated with newly subscribed-to condition");
e4db5ace
JR
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
f82f93a1 894 ret = evaluate_buffer_condition(condition, evaluation, state,
e8360425
JD
895 NULL, last_sample,
896 0, channel_info->session_info->consumed_data_size,
897 channel_info);
e4db5ace 898 if (ret) {
066a3c82 899 WARN("[notification-thread] Fatal error occurred while evaluating a newly subscribed-to condition");
e4db5ace
JR
900 goto end;
901 }
902
f82f93a1
JG
903 *session_uid = channel_info->session_info->uid;
904 *session_gid = channel_info->session_info->gid;
905end:
505b2d90 906 rcu_read_unlock();
f82f93a1
JG
907 return ret;
908}
909
910static
911const 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 }
938end:
939 return session_name;
940}
941
f82f93a1
JG
942static
943int 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
505b2d90 955 rcu_read_lock();
f82f93a1
JG
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) {
be558f88 983 ret = 0;
f82f93a1
JG
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
1006end_session_put:
1007 session_info_put(session_info);
1008end:
505b2d90 1009 rcu_read_unlock();
f82f93a1
JG
1010 return ret;
1011}
1012
f82f93a1
JG
1013static
1014int 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;
505b2d90
JG
1021 struct notification_client_list client_list = {
1022 .lock = PTHREAD_MUTEX_INITIALIZER,
1023 };
f82f93a1
JG
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:
7e802d0a 1043 DBG("[notification-thread] Newly subscribed-to condition not bound to object, nothing to evaluate");
f82f93a1
JG
1044 ret = 0;
1045 goto end;
1046 case LTTNG_OBJECT_TYPE_UNKNOWN:
1047 default:
1048 ret = -1;
1049 goto end;
1050 }
af0c318d
JG
1051 if (ret) {
1052 /* Fatal error. */
1053 goto end;
1054 }
e4db5ace
JR
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 */
505b2d90 1066 cds_lfht_node_init(&client_list.notification_trigger_clients_ht_node);
091fa780 1067 CDS_INIT_LIST_HEAD(&client_list.clients_list);
e4db5ace
JR
1068
1069 CDS_INIT_LIST_HEAD(&client_list_element.node);
1070 client_list_element.client = client;
091fa780 1071 cds_list_add(&client_list_element.node, &client_list.clients_list);
e4db5ace
JR
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,
f82f93a1 1076 state, object_uid, object_gid);
e4db5ace
JR
1077
1078end:
1079 return ret;
1080}
1081
ab0ee2ca
JG
1082static
1083int 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;
505b2d90 1089 struct notification_client_list *client_list = NULL;
ab0ee2ca
JG
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
ab0ee2ca
JG
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
ed327204
JG
1125 client_list = get_client_list_from_condition(state, condition);
1126 if (!client_list) {
2ae99f0b
JG
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 */
4fb43b68 1132 free(client_list_element);
505b2d90 1133 goto end;
ab0ee2ca
JG
1134 }
1135
2ae99f0b
JG
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.
505b2d90
JG
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.
2ae99f0b 1144 */
091fa780
FD
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 }
e4db5ace 1156 }
091fa780 1157 pthread_mutex_unlock(&client_list->lock);
e4db5ace
JR
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 */
ab0ee2ca
JG
1164 client_list_element->client = client;
1165 CDS_INIT_LIST_HEAD(&client_list_element->node);
505b2d90
JG
1166
1167 pthread_mutex_lock(&client_list->lock);
091fa780 1168 cds_list_add(&client_list_element->node, &client_list->clients_list);
505b2d90 1169 pthread_mutex_unlock(&client_list->lock);
ab0ee2ca
JG
1170end:
1171 if (_status) {
1172 *_status = status;
1173 }
505b2d90
JG
1174 if (client_list) {
1175 notification_client_list_put(client_list);
1176 }
ab0ee2ca
JG
1177 return ret;
1178error:
1179 free(condition_list_element);
1180 free(client_list_element);
1181 return ret;
1182}
1183
1184static
1185int 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{
ab0ee2ca
JG
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 */
ed327204
JG
1232 client_list = get_client_list_from_condition(state, condition);
1233 if (!client_list) {
505b2d90 1234 goto end;
ab0ee2ca
JG
1235 }
1236
505b2d90 1237 pthread_mutex_lock(&client_list->lock);
ab0ee2ca 1238 cds_list_for_each_entry_safe(client_list_element, client_tmp,
091fa780 1239 &client_list->clients_list, node) {
505b2d90 1240 if (client_list_element->client->id != client->id) {
ab0ee2ca
JG
1241 continue;
1242 }
1243 cds_list_del(&client_list_element->node);
1244 free(client_list_element);
1245 break;
1246 }
505b2d90
JG
1247 pthread_mutex_unlock(&client_list->lock);
1248 notification_client_list_put(client_list);
1249 client_list = NULL;
ab0ee2ca
JG
1250end:
1251 lttng_condition_destroy(condition);
1252 if (_status) {
1253 *_status = status;
1254 }
1255 return 0;
1256}
1257
83b934ad
MD
1258static
1259void free_notification_client_rcu(struct rcu_head *node)
1260{
1261 free(caa_container_of(node, struct notification_client, rcu_node));
1262}
1263
ab0ee2ca
JG
1264static
1265void notification_client_destroy(struct notification_client *client,
1266 struct notification_thread_state *state)
1267{
ab0ee2ca
JG
1268 if (!client) {
1269 return;
1270 }
1271
505b2d90
JG
1272 /*
1273 * The client object is not reachable by other threads, no need to lock
1274 * the client here.
1275 */
ab0ee2ca
JG
1276 if (client->socket >= 0) {
1277 (void) lttcomm_close_unix_sock(client->socket);
ac1889bf 1278 client->socket = -1;
ab0ee2ca 1279 }
505b2d90 1280 client->communication.active = false;
882093ee
JR
1281 lttng_payload_reset(&client->communication.inbound.payload);
1282 lttng_payload_reset(&client->communication.outbound.payload);
505b2d90 1283 pthread_mutex_destroy(&client->lock);
83b934ad 1284 call_rcu(&client->rcu_node, free_notification_client_rcu);
ab0ee2ca
JG
1285}
1286
1287/*
1288 * Call with rcu_read_lock held (and hold for the lifetime of the returned
1289 * client pointer).
1290 */
1291static
1292struct 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,
ac1889bf
JG
1300 hash_client_socket(socket),
1301 match_client_socket,
ab0ee2ca
JG
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);
1311end:
1312 return client;
1313}
1314
f2b3ef9f
JG
1315/*
1316 * Call with rcu_read_lock held (and hold for the lifetime of the returned
1317 * client pointer).
1318 */
1319static
1320struct 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);
1339end:
1340 return client;
1341}
1342
ab0ee2ca 1343static
e8360425 1344bool buffer_usage_condition_applies_to_channel(
51eab943
JG
1345 const struct lttng_condition *condition,
1346 const struct channel_info *channel_info)
ab0ee2ca
JG
1347{
1348 enum lttng_condition_status status;
e8360425
JD
1349 enum lttng_domain_type condition_domain;
1350 const char *condition_session_name = NULL;
1351 const char *condition_channel_name = NULL;
ab0ee2ca 1352
e8360425
JD
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) {
ab0ee2ca
JG
1357 goto fail;
1358 }
1359
e8360425
JD
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)) {
ab0ee2ca
JG
1372 goto fail;
1373 }
1374
e8360425
JD
1375 return true;
1376fail:
1377 return false;
1378}
1379
1380static
1381bool session_consumed_size_condition_applies_to_channel(
51eab943
JG
1382 const struct lttng_condition *condition,
1383 const struct channel_info *channel_info)
e8360425
JD
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)) {
ab0ee2ca
JG
1393 goto fail;
1394 }
1395
e8360425
JD
1396 return true;
1397fail:
1398 return false;
1399}
ab0ee2ca 1400
51eab943
JG
1401static
1402bool trigger_applies_to_channel(const struct lttng_trigger *trigger,
1403 const struct channel_info *channel_info)
1404{
1405 const struct lttng_condition *condition;
e8360425 1406 bool trigger_applies;
ab0ee2ca 1407
51eab943 1408 condition = lttng_trigger_get_const_condition(trigger);
e8360425 1409 if (!condition) {
ab0ee2ca
JG
1410 goto fail;
1411 }
e8360425
JD
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:
ab0ee2ca
JG
1424 goto fail;
1425 }
1426
e8360425 1427 return trigger_applies;
ab0ee2ca
JG
1428fail:
1429 return false;
1430}
1431
ed327204
JG
1432/* Must be called with RCU read lock held. */
1433static
1434struct 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
e742b055 1458 list = caa_container_of(node,
ed327204
JG
1459 struct lttng_session_trigger_list,
1460 session_triggers_ht_node);
1461end:
1462 return list;
1463}
1464
ea9a44f0
JG
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 */
1473static
1474struct 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();
1495end:
1496 return list;
1497}
1498
1499static
1500void 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
1506static
1507void 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
1525static
1526int lttng_session_trigger_list_add(struct lttng_session_trigger_list *list,
f2b3ef9f 1527 struct lttng_trigger *trigger)
ea9a44f0
JG
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);
1540end:
1541 return ret;
1542}
1543
1544static
1545bool 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 }
1573end:
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 */
1585static
1586struct 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;
1620error:
1621 lttng_session_trigger_list_destroy(session_trigger_list);
1622 return NULL;
1623}
1624
8abe313a
JG
1625static
1626struct 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;
ea9a44f0 1633 struct lttng_session_trigger_list *trigger_list;
8abe313a
JG
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);
1eee26c5
JG
1649 session_info_get(session);
1650 goto end;
ea9a44f0
JG
1651 }
1652
1653 trigger_list = lttng_session_trigger_list_build(state, name);
1654 if (!trigger_list) {
1655 goto error;
8abe313a
JG
1656 }
1657
1eee26c5
JG
1658 session = session_info_create(name, uid, gid, trigger_list,
1659 state->sessions_ht);
8abe313a
JG
1660 if (!session) {
1661 ERR("[notification-thread] Failed to allocation session info for session \"%s\" (uid = %i, gid = %i)",
1662 name, uid, gid);
b248644d 1663 lttng_session_trigger_list_destroy(trigger_list);
ea9a44f0 1664 goto error;
8abe313a 1665 }
ea9a44f0 1666 trigger_list = NULL;
577983cb
JG
1667
1668 cds_lfht_add(state->sessions_ht, hash_key_str(name, lttng_ht_seed),
9b63a4aa 1669 &session->sessions_ht_node);
1eee26c5 1670end:
8abe313a
JG
1671 rcu_read_unlock();
1672 return session;
ea9a44f0
JG
1673error:
1674 rcu_read_unlock();
1675 session_info_put(session);
1676 return NULL;
8abe313a
JG
1677}
1678
ab0ee2ca
JG
1679static
1680int handle_notification_thread_command_add_channel(
8abe313a
JG
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)
ab0ee2ca
JG
1686{
1687 struct cds_list_head trigger_list;
8abe313a
JG
1688 struct channel_info *new_channel_info = NULL;
1689 struct channel_key channel_key = {
1690 .key = channel_key_int,
1691 .domain = channel_domain,
1692 };
ab0ee2ca
JG
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;
8abe313a 1697 struct session_info *session_info = NULL;
ab0ee2ca
JG
1698
1699 DBG("[notification-thread] Adding channel %s from session %s, channel key = %" PRIu64 " in %s domain",
8abe313a 1700 channel_name, session_name, channel_key_int,
526200e4 1701 lttng_domain_type_str(channel_domain));
ab0ee2ca
JG
1702
1703 CDS_INIT_LIST_HEAD(&trigger_list);
1704
8abe313a
JG
1705 session_info = find_or_create_session_info(state, session_name,
1706 session_uid, session_gid);
1707 if (!session_info) {
a9577b76 1708 /* Allocation error or an internal error occurred. */
ab0ee2ca
JG
1709 goto error;
1710 }
1711
8abe313a
JG
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 }
ab0ee2ca 1717
83b934ad 1718 rcu_read_lock();
ab0ee2ca
JG
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,
8abe313a 1725 new_channel_info)) {
ab0ee2ca
JG
1726 continue;
1727 }
1728
1729 new_element = zmalloc(sizeof(*new_element));
1730 if (!new_element) {
83b934ad 1731 rcu_read_unlock();
ab0ee2ca
JG
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 }
83b934ad 1739 rcu_read_unlock();
ab0ee2ca
JG
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 }
8abe313a 1747 channel_trigger_list->channel_key = new_channel_info->key;
ab0ee2ca
JG
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,
8abe313a 1755 hash_channel_key(&new_channel_info->key),
ab0ee2ca
JG
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,
8abe313a 1762 hash_channel_key(&new_channel_info->key),
ab0ee2ca
JG
1763 &channel_trigger_list->channel_triggers_ht_node);
1764 rcu_read_unlock();
1eee26c5 1765 session_info_put(session_info);
ab0ee2ca
JG
1766 *cmd_result = LTTNG_OK;
1767 return 0;
1768error:
ab0ee2ca 1769 channel_info_destroy(new_channel_info);
8abe313a 1770 session_info_put(session_info);
ab0ee2ca
JG
1771 return 1;
1772}
1773
83b934ad
MD
1774static
1775void 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
1781static
1782void 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
ab0ee2ca
JG
1788static
1789int 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",
526200e4 1802 channel_key, lttng_domain_type_str(domain));
ab0ee2ca
JG
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);
83b934ad 1830 call_rcu(&trigger_list->rcu_node, free_channel_trigger_list_rcu);
ab0ee2ca
JG
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);
83b934ad 1849 call_rcu(&sample->rcu_node, free_channel_state_sample_rcu);
ab0ee2ca
JG
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);
1864end:
1865 rcu_read_unlock();
1866 *cmd_result = LTTNG_OK;
1867 return 0;
1868}
1869
0ca52944 1870static
ed327204 1871int handle_notification_thread_command_session_rotation(
0ca52944 1872 struct notification_thread_state *state,
ed327204
JG
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)
0ca52944 1878{
ed327204
JG
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;
f2b3ef9f 1884 const struct lttng_credentials session_creds = {
ff588497
JR
1885 .uid = LTTNG_OPTIONAL_INIT_VALUE(session_uid),
1886 .gid = LTTNG_OPTIONAL_INIT_VALUE(session_gid),
f2b3ef9f 1887 };
0ca52944 1888
ed327204
JG
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) {
a9577b76 1894 /* Allocation error or an internal error occurred. */
ed327204
JG
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;
f2b3ef9f 1913 struct lttng_trigger *trigger;
ed327204
JG
1914 struct notification_client_list *client_list;
1915 struct lttng_evaluation *evaluation = NULL;
1916 enum lttng_condition_type condition_type;
f2b3ef9f 1917 enum action_executor_status executor_status;
ed327204
JG
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
ed327204 1932 client_list = get_client_list_from_condition(state, condition);
ed327204
JG
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;
505b2d90 1945 goto put_list;
ed327204
JG
1946 }
1947
f2b3ef9f
JG
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
505b2d90
JG
1982put_list:
1983 notification_client_list_put(client_list);
ed327204 1984 if (caa_unlikely(ret)) {
505b2d90 1985 break;
ed327204
JG
1986 }
1987 }
1988end:
1989 session_info_put(session_info);
1990 *_cmd_result = cmd_result;
1991 rcu_read_unlock();
1992 return ret;
0ca52944
JG
1993}
1994
d02d7404
JR
1995static
1996int 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
d02d7404
JR
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
2035end:
2036 *_cmd_result = cmd_result;
2037 return ret;
2038}
2039
8b524060
FD
2040static
2041int 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);
a17b133b 2072 if (ret == 0 || (LTTNG_POLL_GETEV(&events, 0) & LPOLLIN) == 0) {
8b524060
FD
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 }
2088end:
2089 lttng_poll_clean(&events);
2090 return ret;
2091}
2092
d02d7404
JR
2093static
2094int 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;
2fb5e9b7 2100 bool found = false;
d02d7404
JR
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);
2fb5e9b7 2114 found = true;
d02d7404
JR
2115 break;
2116 }
2117
2fb5e9b7
JG
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 }
d02d7404
JR
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
173900f6
JG
2147 source_element->is_fd_in_poll_set = false;
2148
8b524060
FD
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
d02d7404
JR
2167end:
2168 free(source_element);
2169 *_cmd_result = cmd_result;
2170 return ret;
2171}
2172
90aa04a1
FD
2173static
2174int 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
d02d7404
JR
2207int 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
fbc9f37d
JR
2220static 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
6487ad53 2254 if (lttng_trigger_needs_tracer_notifier(trigger_ht_element->trigger)) {
90aa04a1
FD
2255 ret = condition_on_event_update_error_count(
2256 trigger_ht_element->trigger);
2257 assert(!ret);
2258 }
2259
fbc9f37d
JR
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
2274end:
2275 rcu_read_unlock();
2276 lttng_triggers_destroy(local_triggers);
2277 *_cmd_result = cmd_result;
2278 return ret;
2279}
2280
1da26331 2281static
959e3c66 2282bool condition_is_supported(struct lttng_condition *condition)
1da26331 2283{
959e3c66 2284 bool is_supported;
1da26331
JG
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 {
959e3c66 2290 int ret;
1da26331
JG
2291 enum lttng_domain_type domain;
2292
2293 ret = lttng_condition_buffer_usage_get_domain_type(condition,
2294 &domain);
959e3c66 2295 assert(ret == 0);
1da26331
JG
2296
2297 if (domain != LTTNG_DOMAIN_KERNEL) {
959e3c66 2298 is_supported = true;
1da26331
JG
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.
959e3c66
JR
2306 *
2307 * Assume unsupported on error.
1da26331 2308 */
959e3c66
JR
2309 is_supported = kernel_supports_ring_buffer_snapshot_sample_positions() == 1;
2310 break;
2311 }
d602bd6a 2312 case LTTNG_CONDITION_TYPE_ON_EVENT:
959e3c66
JR
2313 {
2314 const struct lttng_event_rule *event_rule;
2315 enum lttng_domain_type domain;
2316 const enum lttng_condition_status status =
d602bd6a 2317 lttng_condition_on_event_get_rule(
959e3c66
JR
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;
1da26331
JG
2336 break;
2337 }
2338 default:
959e3c66 2339 is_supported = true;
1da26331
JG
2340 }
2341end:
959e3c66 2342 return is_supported;
1da26331
JG
2343}
2344
51eab943
JG
2345/* Must be called with RCU read lock held. */
2346static
f2b3ef9f 2347int bind_trigger_to_matching_session(struct lttng_trigger *trigger,
51eab943
JG
2348 struct notification_thread_state *state)
2349{
2350 int ret = 0;
51eab943
JG
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
ed327204
JG
2376 trigger_list = get_session_trigger_list(state, session_name);
2377 if (!trigger_list) {
51eab943
JG
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;
51eab943 2381
ed327204 2382 }
51eab943
JG
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);
2387end:
2388 return ret;
2389}
2390
2391/* Must be called with RCU read lock held. */
2392static
f2b3ef9f 2393int bind_trigger_to_matching_channels(struct lttng_trigger *trigger,
51eab943
JG
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;
a5d64ae7 2405 struct cds_lfht_iter lookup_iter;
51eab943
JG
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,
a5d64ae7
MD
2415 &lookup_iter);
2416 node = cds_lfht_iter_get_node(&lookup_iter);
51eab943
JG
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 }
2433end:
2434 return ret;
2435}
2436
f2b3ef9f
JG
2437static
2438bool 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);
17182cfd 2448 action_type = lttng_action_get_type(action);
f2b3ef9f
JG
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
17182cfd 2464 action_type = lttng_action_get_type(inner_action);
f2b3ef9f
JG
2465 if (action_type == LTTNG_ACTION_TYPE_NOTIFY) {
2466 is_notify = true;
2467 goto end;
2468 }
2469 }
2470
2471end:
2472 return is_notify;
2473}
2474
242388e4
JR
2475static 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
2492static
2493enum 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
2758e38b
FD
2519static inline
2520void 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
6487ad53
FD
2531static
2532enum 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
2584error_remove_ht_element:
2585 cds_lfht_del(state->trigger_tokens_ht, &trigger_tokens_ht_element->node);
2586error_free_ht_element:
2587 free(trigger_tokens_ht_element);
2588end:
2589 return ret;
2590}
2591
ab0ee2ca 2592/*
f2b3ef9f 2593 * FIXME A client's credentials are not checked when registering a trigger.
ab0ee2ca 2594 *
1da26331 2595 * The effects of this are benign since:
ab0ee2ca 2596 * - The client will succeed in registering the trigger, as it is valid,
51eab943 2597 * - The trigger will, internally, be bound to the channel/session,
ab0ee2ca
JG
2598 * - The notifications will not be sent since the client's credentials
2599 * are checked against the channel at that moment.
1da26331
JG
2600 *
2601 * If this function returns a non-zero value, it means something is
50ca7858 2602 * fundamentally broken and the whole subsystem/thread will be torn down.
1da26331
JG
2603 *
2604 * If a non-fatal error occurs, just set the cmd_result to the appropriate
2605 * error code.
ab0ee2ca
JG
2606 */
2607static
2608int handle_notification_thread_command_register_trigger(
8abe313a
JG
2609 struct notification_thread_state *state,
2610 struct lttng_trigger *trigger,
2611 enum lttng_error_code *cmd_result)
ab0ee2ca
JG
2612{
2613 int ret = 0;
2614 struct lttng_condition *condition;
ab0ee2ca
JG
2615 struct notification_client_list *client_list = NULL;
2616 struct lttng_trigger_ht_element *trigger_ht_element = NULL;
ab0ee2ca 2617 struct cds_lfht_node *node;
242388e4 2618 const char* trigger_name;
ab0ee2ca 2619 bool free_trigger = true;
f2b3ef9f
JG
2620 struct lttng_evaluation *evaluation = NULL;
2621 struct lttng_credentials object_creds;
ff588497
JR
2622 uid_t object_uid;
2623 gid_t object_gid;
f2b3ef9f 2624 enum action_executor_status executor_status;
e6887944
JR
2625 const uint64_t trigger_tracer_token =
2626 state->trigger_id.next_tracer_token++;
ab0ee2ca
JG
2627
2628 rcu_read_lock();
2629
e6887944
JR
2630 /* Set the trigger's tracer token. */
2631 lttng_trigger_set_tracer_token(trigger, trigger_tracer_token);
2632
242388e4
JR
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
ab0ee2ca 2651 condition = lttng_trigger_get_condition(trigger);
1da26331
JG
2652 assert(condition);
2653
959e3c66
JR
2654 /* Some conditions require tracers to implement a minimal ABI version. */
2655 if (!condition_is_supported(condition)) {
1da26331
JG
2656 *cmd_result = LTTNG_ERR_NOT_SUPPORTED;
2657 goto error;
1da26331
JG
2658 }
2659
ab0ee2ca
JG
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);
242388e4 2668 cds_lfht_node_init(&trigger_ht_element->node_by_name_uid);
ab0ee2ca
JG
2669 trigger_ht_element->trigger = trigger;
2670
2671 node = cds_lfht_add_unique(state->triggers_ht,
2672 lttng_condition_hash(condition),
242388e4
JR
2673 match_trigger,
2674 trigger,
ab0ee2ca
JG
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
242388e4
JR
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
6487ad53
FD
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;
e7c93cf9 2700
6487ad53
FD
2701 error_code = setup_tracer_notifier(state, trigger);
2702 if (error_code != LTTNG_OK) {
2758e38b
FD
2703 notif_thread_state_remove_trigger_ht_elem(state,
2704 trigger_ht_element);
6487ad53
FD
2705 if (error_code == LTTNG_ERR_NOMEM) {
2706 ret = -1;
2707 } else {
2708 *cmd_result = error_code;
2709 ret = 0;
90aa04a1
FD
2710 }
2711
6487ad53 2712 goto error_free_ht_element;
90aa04a1 2713 }
e7c93cf9
JR
2714 }
2715
ab0ee2ca
JG
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 */
f2b3ef9f 2721 if (is_trigger_action_notify(trigger)) {
091fa780
FD
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);
f2b3ef9f 2728 if (!client_list) {
091fa780
FD
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;
f2b3ef9f 2737 }
ab0ee2ca 2738 }
f2b3ef9f 2739
091fa780
FD
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);
ab0ee2ca
JG
2745 }
2746
091fa780
FD
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
f82f93a1 2754 switch (get_condition_binding_object(condition)) {
51eab943
JG
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) {
091fa780 2759 goto error_free_ht_element;
ab0ee2ca 2760 }
f82f93a1 2761 break;
51eab943
JG
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) {
091fa780 2769 goto error_free_ht_element;
ab0ee2ca 2770 }
51eab943
JG
2771 break;
2772 case LTTNG_OBJECT_TYPE_NONE:
2773 break;
2774 default:
f2b3ef9f 2775 ERR("Unknown object type on which to bind a newly registered trigger was encountered");
51eab943 2776 ret = -1;
091fa780 2777 goto error_free_ht_element;
ab0ee2ca
JG
2778 }
2779
2ae99f0b 2780 /*
f2b3ef9f
JG
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.
2ae99f0b
JG
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 */
f2b3ef9f
JG
2809 switch (get_condition_binding_object(condition)) {
2810 case LTTNG_OBJECT_TYPE_SESSION:
2811 ret = evaluate_session_condition_for_client(condition, state,
ff588497
JR
2812 &evaluation, &object_uid,
2813 &object_gid);
bc8daafb
JG
2814 LTTNG_OPTIONAL_SET(&object_creds.uid, object_uid);
2815 LTTNG_OPTIONAL_SET(&object_creds.gid, object_gid);
b42ada90 2816 break;
f2b3ef9f
JG
2817 case LTTNG_OBJECT_TYPE_CHANNEL:
2818 ret = evaluate_channel_condition_for_client(condition, state,
ff588497
JR
2819 &evaluation, &object_uid,
2820 &object_gid);
bc8daafb
JG
2821 LTTNG_OPTIONAL_SET(&object_creds.uid, object_uid);
2822 LTTNG_OPTIONAL_SET(&object_creds.gid, object_gid);
f2b3ef9f
JG
2823 break;
2824 case LTTNG_OBJECT_TYPE_NONE:
2825 ret = 0;
242388e4 2826 break;
f2b3ef9f
JG
2827 case LTTNG_OBJECT_TYPE_UNKNOWN:
2828 default:
2829 ret = -1;
242388e4 2830 break;
f2b3ef9f
JG
2831 }
2832
2833 if (ret) {
2834 /* Fatal error. */
091fa780 2835 goto error_free_ht_element;
f2b3ef9f
JG
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;
091fa780 2843 goto success;
2ae99f0b
JG
2844 }
2845
2846 /*
f2b3ef9f
JG
2847 * Ownership of `evaluation` transferred to the action executor
2848 * no matter the result.
2ae99f0b 2849 */
f2b3ef9f
JG
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;
091fa780 2864 goto error_free_ht_element;
f2b3ef9f
JG
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;
091fa780 2874 goto success;
f2b3ef9f
JG
2875 default:
2876 abort();
2877 }
2ae99f0b 2878
091fa780 2879success:
ab0ee2ca 2880 *cmd_result = LTTNG_OK;
e6887944
JR
2881 DBG("Registered trigger: name = `%s`, tracer token = %" PRIu64,
2882 trigger_name, trigger_tracer_token);
091fa780 2883 goto end;
505b2d90 2884
ab0ee2ca 2885error_free_ht_element:
242388e4
JR
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 }
ab0ee2ca
JG
2891error:
2892 if (free_trigger) {
ab0ee2ca
JG
2893 lttng_trigger_destroy(trigger);
2894 }
091fa780 2895end:
ab0ee2ca
JG
2896 rcu_read_unlock();
2897 return ret;
2898}
2899
83b934ad
MD
2900static
2901void 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
e7c93cf9
JR
2907static
2908void 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
6487ad53
FD
2914static
2915void 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
cc2295b5 2944static
ab0ee2ca
JG
2945int handle_notification_thread_command_unregister_trigger(
2946 struct notification_thread_state *state,
ac16173e 2947 const struct lttng_trigger *trigger,
ab0ee2ca
JG
2948 enum lttng_error_code *_cmd_reply)
2949{
2950 struct cds_lfht_iter iter;
ed327204 2951 struct cds_lfht_node *triggers_ht_node;
ab0ee2ca
JG
2952 struct lttng_channel_trigger_list *trigger_list;
2953 struct notification_client_list *client_list;
ab0ee2ca 2954 struct lttng_trigger_ht_element *trigger_ht_element = NULL;
ac16173e 2955 const struct lttng_condition *condition = lttng_trigger_get_const_condition(
ab0ee2ca 2956 trigger);
ab0ee2ca
JG
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),
242388e4
JR
2963 match_trigger,
2964 trigger,
ab0ee2ca
JG
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) {
e8f7fa11 2981 if (!lttng_trigger_is_equal(trigger, trigger_element->trigger)) {
ab0ee2ca
JG
2982 continue;
2983 }
2984
2985 DBG("[notification-thread] Removed trigger from channel_triggers_ht");
2986 cds_list_del(&trigger_element->node);
e4db5ace
JR
2987 /* A trigger can only appear once per channel */
2988 break;
ab0ee2ca
JG
2989 }
2990 }
2991
6487ad53
FD
2992 if (lttng_trigger_needs_tracer_notifier(trigger)) {
2993 teardown_tracer_notifier(state, trigger);
e7c93cf9
JR
2994 }
2995
091fa780
FD
2996 trigger_ht_element = caa_container_of(triggers_ht_node,
2997 struct lttng_trigger_ht_element, node);
2998
51367634
JR
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);
ed327204 3006
091fa780
FD
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
51367634
JR
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 }
ab0ee2ca 3016
2758e38b
FD
3017 /* Remove trigger from triggers_ht. */
3018 notif_thread_state_remove_trigger_ht_elem(state, trigger_ht_element);
ab0ee2ca 3019
7ca172c1 3020 /* Release the ownership of the trigger. */
ab0ee2ca 3021 lttng_trigger_destroy(trigger_ht_element->trigger);
83b934ad 3022 call_rcu(&trigger_ht_element->rcu_node, free_lttng_trigger_ht_element_rcu);
ab0ee2ca
JG
3023end:
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. */
3032int 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
8abe313a 3040 /* Read the event pipe to put it back into a quiescent state. */
18aeca05 3041 ret = lttng_read(lttng_pipe_get_readfd(handle->cmd_queue.event_pipe), &counter,
8abe313a 3042 sizeof(counter));
18aeca05 3043 if (ret != sizeof(counter)) {
ab0ee2ca
JG
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);
97a71ea6
JR
3050 cds_list_del(&cmd->cmd_list_node);
3051 pthread_mutex_unlock(&handle->cmd_queue.lock);
6900ae81
FD
3052
3053 DBG("[notification-thread] Received `%s` command",
3054 notification_command_type_str(cmd->type));
ab0ee2ca
JG
3055 switch (cmd->type) {
3056 case NOTIFICATION_COMMAND_TYPE_REGISTER_TRIGGER:
ac16173e
JG
3057 ret = handle_notification_thread_command_register_trigger(state,
3058 cmd->parameters.register_trigger.trigger,
ab0ee2ca
JG
3059 &cmd->reply_code);
3060 break;
3061 case NOTIFICATION_COMMAND_TYPE_UNREGISTER_TRIGGER:
ab0ee2ca 3062 ret = handle_notification_thread_command_unregister_trigger(
ac16173e
JG
3063 state,
3064 cmd->parameters.unregister_trigger.trigger,
ab0ee2ca
JG
3065 &cmd->reply_code);
3066 break;
3067 case NOTIFICATION_COMMAND_TYPE_ADD_CHANNEL:
ab0ee2ca 3068 ret = handle_notification_thread_command_add_channel(
8abe313a
JG
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,
ab0ee2ca
JG
3077 &cmd->reply_code);
3078 break;
3079 case NOTIFICATION_COMMAND_TYPE_REMOVE_CHANNEL:
ab0ee2ca
JG
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;
0ca52944 3085 case NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_ONGOING:
0ca52944 3086 case NOTIFICATION_COMMAND_TYPE_SESSION_ROTATION_COMPLETED:
ed327204 3087 ret = handle_notification_thread_command_session_rotation(
0ca52944 3088 state,
ed327204
JG
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,
0ca52944
JG
3095 &cmd->reply_code);
3096 break;
d02d7404
JR
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;
fbc9f37d
JR
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 }
ab0ee2ca 3124 case NOTIFICATION_COMMAND_TYPE_QUIT:
ab0ee2ca
JG
3125 cmd->reply_code = LTTNG_OK;
3126 ret = 1;
3127 goto end;
f2b3ef9f
JG
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 {
f2b3ef9f
JG
3150 ret = client_handle_transmission_status(
3151 client, client_status, state);
f2b3ef9f
JG
3152 }
3153 rcu_read_unlock();
3154 break;
3155 }
ab0ee2ca
JG
3156 default:
3157 ERR("[notification-thread] Unknown internal command received");
3158 goto error_unlock;
3159 }
3160
3161 if (ret) {
3162 goto error_unlock;
3163 }
3164end:
0ab399e0
JG
3165 if (cmd->is_async) {
3166 free(cmd);
3167 cmd = NULL;
3168 } else {
3169 lttng_waiter_wake_up(&cmd->reply_waiter);
3170 }
ab0ee2ca
JG
3171 return ret;
3172error_unlock:
3173 /* Wake-up and return a fatal error to the calling thread. */
8ada111f 3174 lttng_waiter_wake_up(&cmd->reply_waiter);
ab0ee2ca
JG
3175 cmd->reply_code = LTTNG_ERR_FATAL;
3176error:
3177 /* Indicate a fatal error to the caller. */
3178 return -1;
3179}
3180
ab0ee2ca
JG
3181static
3182int 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);
3200end:
3201 return ret;
3202}
3203
3204static
14fa22f8 3205int client_reset_inbound_state(struct notification_client *client)
ab0ee2ca
JG
3206{
3207 int ret;
3208
882093ee
JR
3209
3210 lttng_payload_clear(&client->communication.inbound.payload);
ab0ee2ca
JG
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;
ab0ee2ca
JG
3216 LTTNG_SOCK_SET_UID_CRED(&client->communication.inbound.creds, -1);
3217 LTTNG_SOCK_SET_GID_CRED(&client->communication.inbound.creds, -1);
14fa22f8 3218 ret = lttng_dynamic_buffer_set_size(
882093ee 3219 &client->communication.inbound.payload.buffer,