sessiond: notification: receive incoming notifications from tracers
authorJonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Tue, 31 Mar 2020 18:33:18 +0000 (14:33 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Thu, 28 Jan 2021 23:32:35 +0000 (18:32 -0500)
Receive and discard notifications received by tracers. This simply puts
in place the basic tracer notification reception mechanisms.

Signed-off-by: Jonathan Rajotte <jonathan.rajotte-julien@efficios.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
Change-Id: I3d94431051015c69785ec256095135746e3972ce

src/bin/lttng-sessiond/notification-thread-events.c
src/bin/lttng-sessiond/notification-thread-events.h
src/bin/lttng-sessiond/notification-thread.c

index 1a71131f0f90d398c37468db093372a3449120e8..d620159246a54368d44fa9b9391f4007212c54f6 100644 (file)
@@ -125,6 +125,19 @@ struct lttng_condition_list_element {
        struct cds_list_head node;
 };
 
        struct cds_list_head node;
 };
 
+/*
+ * Facilities to carry the different notifications type in the action processing
+ * code path.
+ */
+struct lttng_event_notifier_notification {
+       union {
+               struct lttng_ust_event_notifier_notification *ust;
+               struct lttng_kernel_event_notifier_notification *kernel;
+       } notification;
+       uint64_t token;
+       enum lttng_domain_type type;
+};
+
 struct channel_state_sample {
        struct channel_key key;
        struct cds_lfht_node channel_state_ht_node;
 struct channel_state_sample {
        struct channel_key key;
        struct cds_lfht_node channel_state_ht_node;
@@ -4133,6 +4146,99 @@ end:
        return ret;
 }
 
        return ret;
 }
 
+int handle_notification_thread_event_notification(struct notification_thread_state *state,
+               int notification_pipe_read_fd,
+               enum lttng_domain_type domain)
+{
+       int ret;
+       struct lttng_ust_event_notifier_notification ust_notification;
+       struct lttng_kernel_event_notifier_notification kernel_notification;
+       struct cds_lfht_node *node;
+       struct cds_lfht_iter iter;
+       struct notification_trigger_tokens_ht_element *element;
+       enum lttng_action_type action_type;
+       const struct lttng_action *action;
+       struct lttng_event_notifier_notification notification;
+       void *reception_buffer;
+       size_t reception_size;
+
+       notification.type = domain;
+
+       switch(domain) {
+       case LTTNG_DOMAIN_UST:
+               reception_buffer = (void *) &ust_notification;
+               reception_size = sizeof(ust_notification);
+               notification.notification.ust = &ust_notification;
+               break;
+       case LTTNG_DOMAIN_KERNEL:
+               reception_buffer = (void *) &kernel_notification;
+               reception_size = sizeof(kernel_notification);
+               notification.notification.kernel = &kernel_notification;
+               break;
+       default:
+               abort();
+       }
+
+       /*
+        * The monitoring pipe only holds messages smaller than PIPE_BUF,
+        * ensuring that read/write of tracer notifications are atomic.
+        */
+       ret = lttng_read(notification_pipe_read_fd, reception_buffer,
+                       reception_size);
+       if (ret != reception_size) {
+               PERROR("Failed to read from event source notification pipe: fd = %d, size to read = %zu, ret = %d",
+                               notification_pipe_read_fd, reception_size, ret);
+               ret = -1;
+               goto end;
+       }
+
+       switch(domain) {
+       case LTTNG_DOMAIN_UST:
+               notification.token = ust_notification.token;
+               break;
+       case LTTNG_DOMAIN_KERNEL:
+               notification.token = kernel_notification.token;
+               break;
+       default:
+               abort();
+       }
+
+       /* Find triggers associated with this token. */
+       rcu_read_lock();
+       cds_lfht_lookup(state->trigger_tokens_ht,
+                       hash_key_u64(&notification.token, lttng_ht_seed),
+                       match_trigger_token, &notification.token, &iter);
+       node = cds_lfht_iter_get_node(&iter);
+       if (caa_likely(!node)) {
+               /*
+                * This is not an error, slow consumption of the pipe can lead
+                * to situations where a trigger is removed but we still get
+                * tracer notification matching to a previous trigger.
+                */
+               ret = 0;
+               goto end_unlock;
+       }
+
+       element = caa_container_of(node,
+                       struct notification_trigger_tokens_ht_element,
+                       node);
+
+       action = lttng_trigger_get_const_action(element->trigger);
+       action_type = lttng_action_get_type(action);
+       DBG("Received message from tracer event source: event source fd = %d, token = %" PRIu64 ", action type = '%s'",
+                       notification_pipe_read_fd, notification.token,
+                       lttng_action_type_string(action_type));
+
+       /* TODO: Perform actions */
+
+       ret = 0;
+
+end_unlock:
+       rcu_read_unlock();
+end:
+       return ret;
+}
+
 int handle_notification_thread_channel_sample(
                struct notification_thread_state *state, int pipe,
                enum lttng_domain_type domain)
 int handle_notification_thread_channel_sample(
                struct notification_thread_state *state, int pipe,
                enum lttng_domain_type domain)
index 3602f8dca1ab6efa6057eccd388921312f615537..dffd26773ad328dfea75b7a63f04ca5581259217 100644 (file)
@@ -48,4 +48,8 @@ int handle_notification_thread_channel_sample(
                struct notification_thread_state *state, int pipe,
                enum lttng_domain_type domain);
 
                struct notification_thread_state *state, int pipe,
                enum lttng_domain_type domain);
 
+int handle_notification_thread_event_notification(
+               struct notification_thread_state *state, int pipe,
+               enum lttng_domain_type domain);
+
 #endif /* NOTIFICATION_THREAD_EVENTS_H */
 #endif /* NOTIFICATION_THREAD_EVENTS_H */
index 1a7a16119972b3cebc45e7b3098e03a83fc81bef..1ba724337b67ee69a1856087a5c8b65c45a32cd8 100644 (file)
@@ -28,6 +28,9 @@
 #include "health-sessiond.h"
 #include "thread.h"
 
 #include "health-sessiond.h"
 #include "thread.h"
 
+#include "kernel.h"
+#include <common/kernel-ctl/kernel-ctl.h>
+
 #include <urcu.h>
 #include <urcu/list.h>
 #include <urcu/rculfhash.h>
 #include <urcu.h>
 #include <urcu/list.h>
 #include <urcu/rculfhash.h>
@@ -69,6 +72,7 @@ void notification_thread_handle_destroy(
                        PERROR("close kernel consumer channel monitoring pipe");
                }
        }
                        PERROR("close kernel consumer channel monitoring pipe");
                }
        }
+
 end:
        free(handle);
 }
 end:
        free(handle);
 }
@@ -550,6 +554,59 @@ end:
        return ret;
 }
 
        return ret;
 }
 
+static int handle_event_notification_pipe(int event_source_fd,
+               enum lttng_domain_type domain,
+               uint32_t revents,
+               struct notification_thread_state *state)
+{
+       int ret = 0;
+
+       if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
+               ret = handle_notification_thread_remove_tracer_event_source_no_result(
+                               state, event_source_fd);
+               if (ret) {
+                       ERR("[notification-thread] Failed to remove event notification pipe from poll set: fd = %d",
+                                       event_source_fd);
+               }
+               goto end;
+       }
+
+       ret = handle_notification_thread_event_notification(
+                       state, event_source_fd, domain);
+       if (ret) {
+               ERR("[notification-thread] Event notification handling error occurred for fd: %d",
+                               event_source_fd);
+               ret = -1;
+               goto end;
+       }
+end:
+       return ret;
+}
+
+/*
+ * Return the event source domain type via parameter.
+ */
+static bool fd_is_event_notification_source(const struct notification_thread_state *state,
+               int fd,
+               enum lttng_domain_type *domain)
+{
+       struct notification_event_tracer_event_source_element *source_element;
+
+       assert(domain);
+
+       cds_list_for_each_entry(source_element,
+                       &state->tracer_event_sources_list, node) {
+               if (source_element->fd != fd) {
+                       continue;
+               }
+
+               *domain = source_element->domain;
+               return true;
+       }
+
+       return false;
+}
+
 /*
  * This thread services notification channel clients and commands received
  * from various lttng-sessiond components over a command queue.
 /*
  * This thread services notification channel clients and commands received
  * from various lttng-sessiond components over a command queue.
@@ -560,6 +617,7 @@ void *thread_notification(void *data)
        int ret;
        struct notification_thread_handle *handle = data;
        struct notification_thread_state state;
        int ret;
        struct notification_thread_handle *handle = data;
        struct notification_thread_state state;
+       enum lttng_domain_type domain;
 
        DBG("[notification-thread] Started notification thread");
 
 
        DBG("[notification-thread] Started notification thread");
 
@@ -637,6 +695,11 @@ void *thread_notification(void *data)
                                if (ret) {
                                        goto error;
                                }
                                if (ret) {
                                        goto error;
                                }
+                       } else if (fd_is_event_notification_source(&state, fd, &domain)) {
+                               ret = handle_event_notification_pipe(fd, domain, revents, &state);
+                               if (ret) {
+                                       goto error;
+                               }
                        } else {
                                /* Activity on a client's socket. */
                                if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
                        } else {
                                /* Activity on a client's socket. */
                                if (revents & (LPOLLERR | LPOLLHUP | LPOLLRDHUP)) {
This page took 0.030507 seconds and 4 git commands to generate.