Typo: occured -> occurred
[lttng-tools.git] / src / bin / lttng-sessiond / notification-thread-events.c
index 66223e9d340e89f8c39b8dc3b5b5bfbecbbf096a..751e665bdc624936a8401fd307ae75ff93656978 100644 (file)
@@ -19,9 +19,6 @@
 #include <urcu.h>
 #include <urcu/rculfhash.h>
 
-#include "notification-thread.h"
-#include "notification-thread-events.h"
-#include "notification-thread-commands.h"
 #include <common/defaults.h>
 #include <common/error.h>
 #include <common/futex.h>
 #include <lttng/condition/condition-internal.h>
 #include <lttng/condition/buffer-usage-internal.h>
 #include <lttng/notification/channel-internal.h>
+
 #include <time.h>
 #include <unistd.h>
 #include <assert.h>
 #include <inttypes.h>
 #include <fcntl.h>
 
+#include "notification-thread.h"
+#include "notification-thread-events.h"
+#include "notification-thread-commands.h"
+#include "lttng-sessiond.h"
+#include "kernel.h"
+
 #define CLIENT_POLL_MASK_IN (LPOLLIN | LPOLLERR | LPOLLHUP | LPOLLRDHUP)
 #define CLIENT_POLL_MASK_IN_OUT (CLIENT_POLL_MASK_IN | LPOLLOUT)
 
@@ -97,6 +101,11 @@ struct notification_client {
        struct cds_lfht_node client_socket_ht_node;
        struct {
                struct {
+                       /*
+                        * During the reception of a message, the reception
+                        * buffers' "size" is set to contain the current
+                        * message's complete payload.
+                        */
                        struct lttng_dynamic_buffer buffer;
                        /* Bytes left to receive for the current message. */
                        size_t bytes_to_receive;
@@ -106,12 +115,13 @@ struct notification_client {
                         * Indicates whether or not credentials are expected
                         * from the client.
                         */
-                       bool receive_creds;
+                       bool expect_creds;
                        /*
                         * Indicates whether or not credentials were received
                         * from the client.
                         */
                        bool creds_received;
+                       /* Only used during credentials reception. */
                        lttng_sock_cred creds;
                } inbound;
                struct {
@@ -800,15 +810,60 @@ end:
        return 0;
 }
 
+static
+int condition_is_supported(struct lttng_condition *condition)
+{
+       int ret;
+
+       switch (lttng_condition_get_type(condition)) {
+       case LTTNG_CONDITION_TYPE_BUFFER_USAGE_LOW:
+       case LTTNG_CONDITION_TYPE_BUFFER_USAGE_HIGH:
+       {
+               enum lttng_domain_type domain;
+
+               ret = lttng_condition_buffer_usage_get_domain_type(condition,
+                               &domain);
+               if (ret) {
+                       ret = -1;
+                       goto end;
+               }
+
+               if (domain != LTTNG_DOMAIN_KERNEL) {
+                       ret = 1;
+                       goto end;
+               }
+
+               /*
+                * Older kernel tracers don't expose the API to monitor their
+                * buffers. Therefore, we reject triggers that require that
+                * mechanism to be available to be evaluated.
+                */
+               ret = kernel_supports_ring_buffer_snapshot_sample_positions(
+                               kernel_tracer_fd);
+               break;
+       }
+       default:
+               ret = 1;
+       }
+end:
+       return ret;
+}
+
 /*
  * FIXME A client's credentials are not checked when registering a trigger, nor
  *       are they stored alongside with the trigger.
  *
- * The effects of this are benign:
+ * The effects of this are benign since:
  *     - The client will succeed in registering the trigger, as it is valid,
  *     - The trigger will, internally, be bound to the channel,
  *     - The notifications will not be sent since the client's credentials
  *       are checked against the channel at that moment.
+ *
+ * If this function returns a non-zero value, it means something is
+ * fundamentally and the whole subsystem/thread will be torn down.
+ *
+ * If a non-fatal error occurs, just set the cmd_result to the appropriate
+ * error code.
  */
 static
 int handle_notification_thread_command_register_trigger(
@@ -830,6 +885,19 @@ int handle_notification_thread_command_register_trigger(
        rcu_read_lock();
 
        condition = lttng_trigger_get_condition(trigger);
+       assert(condition);
+
+       ret = condition_is_supported(condition);
+       if (ret < 0) {
+               goto error;
+       } else if (ret == 0) {
+               *cmd_result = LTTNG_ERR_NOT_SUPPORTED;
+               goto error;
+       } else {
+               /* Feature is supported, continue. */
+               ret = 0;
+       }
+
        trigger_ht_element = zmalloc(sizeof(*trigger_ht_element));
        if (!trigger_ht_element) {
                ret = -1;
@@ -1153,7 +1221,7 @@ end:
 }
 
 static
-void client_reset_inbound_state(struct notification_client *client)
+int client_reset_inbound_state(struct notification_client *client)
 {
        int ret;
 
@@ -1165,9 +1233,12 @@ void client_reset_inbound_state(struct notification_client *client)
                        sizeof(struct lttng_notification_channel_message);
        client->communication.inbound.msg_type =
                        LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNKNOWN;
-       client->communication.inbound.receive_creds = false;
        LTTNG_SOCK_SET_UID_CRED(&client->communication.inbound.creds, -1);
        LTTNG_SOCK_SET_GID_CRED(&client->communication.inbound.creds, -1);
+       ret = lttng_dynamic_buffer_set_size(
+                       &client->communication.inbound.buffer,
+                       client->communication.inbound.bytes_to_receive);
+       return ret;
 }
 
 int handle_notification_thread_client_connect(
@@ -1187,7 +1258,13 @@ int handle_notification_thread_client_connect(
        CDS_INIT_LIST_HEAD(&client->condition_list);
        lttng_dynamic_buffer_init(&client->communication.inbound.buffer);
        lttng_dynamic_buffer_init(&client->communication.outbound.buffer);
-       client_reset_inbound_state(client);
+       client->communication.inbound.expect_creds = true;
+       ret = client_reset_inbound_state(client);
+       if (ret) {
+               ERR("[notification-thread] Failed to reset client communication's inbound state");
+               ret = 0;
+               goto error;
+       }
 
        ret = lttcomm_accept_unix_sock(state->notification_channel_socket);
        if (ret < 0) {
@@ -1291,7 +1368,7 @@ int handle_notification_thread_client_disconnect_all(
 int handle_notification_thread_trigger_unregister_all(
                struct notification_thread_state *state)
 {
-       bool error_occured = false;
+       bool error_occurred = false;
        struct cds_lfht_iter iter;
        struct lttng_trigger_ht_element *trigger_ht_element;
 
@@ -1300,10 +1377,10 @@ int handle_notification_thread_trigger_unregister_all(
                int ret = handle_notification_thread_command_unregister_trigger(
                                state, trigger_ht_element->trigger, NULL);
                if (ret) {
-                       error_occured = true;
+                       error_occurred = true;
                }
        }
-       return error_occured ? -1 : 0;
+       return error_occurred ? -1 : 0;
 }
 
 static
@@ -1476,12 +1553,8 @@ int client_dispatch_message(struct notification_client *client,
                client->communication.inbound.bytes_to_receive = msg->size;
                client->communication.inbound.msg_type =
                                (enum lttng_notification_channel_message_type) msg->type;
-               if (client->communication.inbound.msg_type ==
-                               LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_HANDSHAKE) {
-                       client->communication.inbound.receive_creds = true;
-               }
                ret = lttng_dynamic_buffer_set_size(
-                               &client->communication.inbound.buffer, 0);
+                               &client->communication.inbound.buffer, msg->size);
                if (ret) {
                        goto end;
                }
@@ -1509,7 +1582,7 @@ int client_dispatch_message(struct notification_client *client,
                handshake_client =
                                (struct lttng_notification_channel_command_handshake *)
                                        client->communication.inbound.buffer.data;
-                               client->major = handshake_client->major;
+               client->major = handshake_client->major;
                client->minor = handshake_client->minor;
                if (!client->communication.inbound.creds_received) {
                        ERR("[notification-thread] No credentials received from client");
@@ -1548,7 +1621,11 @@ int client_dispatch_message(struct notification_client *client,
                }
 
                /* Set reception state to receive the next message header. */
-               client_reset_inbound_state(client);
+               ret = client_reset_inbound_state(client);
+               if (ret) {
+                       ERR("[notification-thread] Failed to reset client communication's inbound state");
+                       goto end;
+               }
                client->validated = true;
                break;
        }
@@ -1595,7 +1672,11 @@ int client_dispatch_message(struct notification_client *client,
                }
 
                /* Set reception state to receive the next message header. */
-               client_reset_inbound_state(client);
+               ret = client_reset_inbound_state(client);
+               if (ret) {
+                       ERR("[notification-thread] Failed to reset client communication's inbound state");
+                       goto end;
+               }
                break;
        }
        default:
@@ -1609,7 +1690,7 @@ end:
 int handle_notification_thread_client_in(
                struct notification_thread_state *state, int socket)
 {
-       int ret;
+       int ret = 0;
        struct notification_client *client;
        ssize_t recv_ret;
        size_t offset;
@@ -1621,21 +1702,15 @@ int handle_notification_thread_client_in(
                goto end;
        }
 
-       offset = client->communication.inbound.buffer.size;
-       ret = lttng_dynamic_buffer_set_size(
-                       &client->communication.inbound.buffer,
-                       client->communication.inbound.bytes_to_receive);
-       if (ret) {
-               goto end;
-       }
-
-       if (client->communication.inbound.receive_creds) {
+       offset = client->communication.inbound.buffer.size -
+                       client->communication.inbound.bytes_to_receive;
+       if (client->communication.inbound.expect_creds) {
                recv_ret = lttcomm_recv_creds_unix_sock(socket,
                                client->communication.inbound.buffer.data + offset,
                                client->communication.inbound.bytes_to_receive,
                                &client->communication.inbound.creds);
                if (recv_ret > 0) {
-                       client->communication.inbound.receive_creds = false;
+                       client->communication.inbound.expect_creds = false;
                        client->communication.inbound.creds_received = true;
                }
        } else {
@@ -1648,14 +1723,6 @@ int handle_notification_thread_client_in(
        }
 
        client->communication.inbound.bytes_to_receive -= recv_ret;
-       ret = lttng_dynamic_buffer_set_size(
-                       &client->communication.inbound.buffer,
-                       client->communication.inbound.buffer.size -
-                       client->communication.inbound.bytes_to_receive);
-       if (ret) {
-               goto end;
-       }
-
        if (client->communication.inbound.bytes_to_receive == 0) {
                ret = client_dispatch_message(client, state);
                if (ret) {
This page took 0.028153 seconds and 5 git commands to generate.