Fix: snapshot support for UST and kernel in same session
[lttng-tools.git] / src / bin / lttng-sessiond / cmd.c
index a6a81c5dbd79989b474ffa1ee5b5d3c5edc83389..903dfd36defb5f8591aa7532f7b0a202d8be863d 100644 (file)
@@ -1743,6 +1743,72 @@ find_error:
        return ret;
 }
 
+/*
+ * Command LTTNG_CREATE_SESSION_SNAPSHOT processed by the client thread.
+ */
+int cmd_create_session_snapshot(char *name, struct lttng_uri *uris,
+               size_t nb_uri, lttng_sock_cred *creds)
+{
+       int ret;
+       struct ltt_session *session;
+       struct snapshot_output *new_output = NULL;
+
+       assert(name);
+       assert(creds);
+
+       /*
+        * Create session in no output mode with URIs set to NULL. The uris we've
+        * received are for a default snapshot output if one.
+        */
+       ret = cmd_create_session_uri(name, NULL, 0, creds);
+       if (ret != LTTNG_OK) {
+               goto error;
+       }
+
+       /* Get the newly created session pointer back. This should NEVER fail. */
+       session = session_find_by_name(name);
+       assert(session);
+
+       /* Flag session for snapshot mode. */
+       session->snapshot_mode = 1;
+
+       /* Skip snapshot output creation if no URI is given. */
+       if (nb_uri == 0) {
+               goto end;
+       }
+
+       new_output = snapshot_output_alloc();
+       if (!new_output) {
+               ret = LTTNG_ERR_NOMEM;
+               goto error_snapshot_alloc;
+       }
+
+       ret = snapshot_output_init_with_uri(DEFAULT_SNAPSHOT_MAX_SIZE, NULL,
+                       uris, nb_uri, session->consumer, new_output, &session->snapshot);
+       if (ret < 0) {
+               if (ret == -ENOMEM) {
+                       ret = LTTNG_ERR_NOMEM;
+               } else {
+                       ret = LTTNG_ERR_INVALID;
+               }
+               goto error_snapshot;
+       }
+
+       rcu_read_lock();
+       snapshot_add_output(&session->snapshot, new_output);
+       rcu_read_unlock();
+
+end:
+       return LTTNG_OK;
+
+error_snapshot:
+       snapshot_output_destroy(new_output);
+error_snapshot_alloc:
+       session_destroy(session);
+error:
+       return ret;
+}
+
 /*
  * Command LTTNG_DESTROY_SESSION processed by the client thread.
  */
@@ -2188,27 +2254,6 @@ int cmd_snapshot_add_output(struct ltt_session *session,
                goto free_error;
        }
 
-       /*
-        * Copy sockets so the snapshot output can use them on destroy.
-        */
-
-       if (session->ust_session) {
-               ret = consumer_copy_sockets(new_output->consumer,
-                               session->ust_session->consumer);
-               if (ret < 0) {
-                       goto free_error;
-               }
-               new_output->ust_sockets_copied = 1;
-       }
-       if (session->kernel_session) {
-               ret = consumer_copy_sockets(new_output->consumer,
-                               session->kernel_session->consumer);
-               if (ret < 0) {
-                       goto free_error;
-               }
-               new_output->kernel_sockets_copied = 1;
-       }
-
        rcu_read_lock();
        snapshot_add_output(&session->snapshot, new_output);
        if (id) {
@@ -2412,24 +2457,28 @@ static int record_kernel_snapshot(struct ltt_kernel_session *ksess,
                goto error;
        }
 
-       if (!output->kernel_sockets_copied) {
-               ret = consumer_copy_sockets(output->consumer, ksess->consumer);
-               if (ret < 0) {
-                       goto error;
-               }
-               output->kernel_sockets_copied = 1;
+       /*
+        * Copy kernel session sockets so we can communicate with the right
+        * consumer for the snapshot record command.
+        */
+       ret = consumer_copy_sockets(output->consumer, ksess->consumer);
+       if (ret < 0) {
+               goto error;
        }
 
        ret = set_relayd_for_snapshot(ksess->consumer, output, session);
        if (ret < 0) {
-               goto error;
+               goto error_snapshot;
        }
 
        ret = kernel_snapshot_record(ksess, output, wait);
        if (ret < 0) {
-               goto error;
+               goto error_snapshot;
        }
 
+error_snapshot:
+       /* Clean up copied sockets so this output can use some other later on. */
+       consumer_destroy_output_sockets(output->consumer);
 error:
        return ret;
 }
@@ -2456,24 +2505,28 @@ static int record_ust_snapshot(struct ltt_ust_session *usess,
                goto error;
        }
 
-       if (!output->ust_sockets_copied) {
-               ret = consumer_copy_sockets(output->consumer, usess->consumer);
-               if (ret < 0) {
-                       goto error;
-               }
-               output->ust_sockets_copied = 1;
+       /*
+        * Copy kernel session sockets so we can communicate with the right
+        * consumer for the snapshot record command.
+        */
+       ret = consumer_copy_sockets(output->consumer, usess->consumer);
+       if (ret < 0) {
+               goto error;
        }
 
        ret = set_relayd_for_snapshot(usess->consumer, output, session);
        if (ret < 0) {
-               goto error;
+               goto error_snapshot;
        }
 
        ret = ust_app_snapshot_record(usess, output, wait);
        if (ret < 0) {
-               goto error;
+               goto error_snapshot;
        }
 
+error_snapshot:
+       /* Clean up copied sockets so this output can use some other later on. */
+       consumer_destroy_output_sockets(output->consumer);
 error:
        return ret;
 }
This page took 0.026154 seconds and 4 git commands to generate.