Backport: Fix: tracker: ensure consistency of tracker states
[lttng-tools.git] / src / bin / lttng-sessiond / kernel.c
index ae8349c897ded12d90bfc2d018ba1994e1822f63..a72fe7f5c977ac76cd351555ec170b5781977191 100644 (file)
@@ -36,6 +36,8 @@
 
 /*
  * Add context on a kernel channel.
+ *
+ * Assumes the ownership of ctx.
  */
 int kernel_add_channel_context(struct ltt_kernel_channel *chan,
                struct ltt_kernel_context *ctx)
@@ -66,9 +68,12 @@ int kernel_add_channel_context(struct ltt_kernel_channel *chan,
 
 end:
        cds_list_add_tail(&ctx->list, &chan->ctx_list);
-       return 0;
-
+       ctx->in_list = true;
+       ctx = NULL;
 error:
+       if (ctx) {
+               trace_kernel_destroy_context(ctx);
+       }
        return ret;
 }
 
@@ -379,120 +384,274 @@ error:
        return ret;
 }
 
-
-int kernel_track_pid(struct ltt_kernel_session *session, int pid)
+static
+struct lttng_tracker_list *get_id_tracker_list(struct ltt_kernel_session *session,
+               enum lttng_tracker_type tracker_type)
 {
-       int ret;
-
-       DBG("Kernel track PID %d for session id %" PRIu64 ".",
-                       pid, session->id);
-       ret = kernctl_track_pid(session->fd, pid);
-       if (!ret) {
-               return LTTNG_OK;
-       }
-       switch (-ret) {
-       case EINVAL:
-               return LTTNG_ERR_INVALID;
-       case ENOMEM:
-               return LTTNG_ERR_NOMEM;
-       case EEXIST:
-               return LTTNG_ERR_PID_TRACKED;
+       switch (tracker_type) {
+       case LTTNG_TRACKER_PID:
+               return session->tracker_list_pid;
+       case LTTNG_TRACKER_VPID:
+               return session->tracker_list_vpid;
+       case LTTNG_TRACKER_UID:
+               return session->tracker_list_uid;
+       case LTTNG_TRACKER_VUID:
+               return session->tracker_list_vuid;
+       case LTTNG_TRACKER_GID:
+               return session->tracker_list_gid;
+       case LTTNG_TRACKER_VGID:
+               return session->tracker_list_vgid;
        default:
-               return LTTNG_ERR_UNK;
+               return NULL;
        }
 }
 
-int kernel_untrack_pid(struct ltt_kernel_session *session, int pid)
+int kernel_track_id(enum lttng_tracker_type tracker_type,
+               struct ltt_kernel_session *session,
+               struct lttng_tracker_id *id)
 {
-       int ret;
+       int ret, value;
+       struct lttng_tracker_list *tracker_list;
+       struct lttng_tracker_id *saved_ids;
+       ssize_t saved_ids_count, i;
+
+       ret = lttng_tracker_id_lookup_string(tracker_type,
+                       id, &value);
+       if (ret != LTTNG_OK) {
+               return ret;
+       }
 
-       DBG("Kernel untrack PID %d for session id %" PRIu64 ".",
-                       pid, session->id);
-       ret = kernctl_untrack_pid(session->fd, pid);
-       if (!ret) {
-               return LTTNG_OK;
+       tracker_list = get_id_tracker_list(session, tracker_type);
+       if (!tracker_list) {
+               return LTTNG_ERR_INVALID;
+       }
+       /* Save list for restore on error. */
+       saved_ids_count = lttng_tracker_id_get_list(tracker_list, &saved_ids);
+       if (saved_ids_count < 0) {
+               return LTTNG_ERR_INVALID;
+       }
+       /* Add to list. */
+       ret = lttng_tracker_list_add(tracker_list, id);
+       if (ret != LTTNG_OK) {
+               goto end;
+       }
+
+       switch (tracker_type) {
+       case LTTNG_TRACKER_PID:
+               DBG("Kernel track PID %d for session id %" PRIu64 ".",
+                               value, session->id);
+               ret = kernctl_track_pid(session->fd, value);
+               if (!ret) {
+                       ret = LTTNG_OK;
+                       goto end;
+               }
+               break;
+       case LTTNG_TRACKER_VPID:
+               DBG("Kernel track VPID %d for session id %" PRIu64 ".",
+                               value, session->id);
+               ret = kernctl_track_id(session->fd, LTTNG_TRACKER_VPID, value);
+               if (!ret) {
+                       ret = LTTNG_OK;
+                       goto end;
+               }
+               break;
+       case LTTNG_TRACKER_UID:
+               DBG("Kernel track UID %d for session id %" PRIu64 ".",
+                               value, session->id);
+               ret = kernctl_track_id(session->fd, LTTNG_TRACKER_UID, value);
+               if (!ret) {
+                       ret = LTTNG_OK;
+                       goto end;
+               }
+               break;
+       case LTTNG_TRACKER_GID:
+               DBG("Kernel track GID %d for session id %" PRIu64 ".",
+                               value, session->id);
+               ret = kernctl_track_id(session->fd, LTTNG_TRACKER_GID, value);
+               if (!ret) {
+                       ret = LTTNG_OK;
+                       goto end;
+               }
+               break;
+       case LTTNG_TRACKER_VUID:
+               DBG("Kernel track VUID %d for session id %" PRIu64 ".",
+                               value, session->id);
+               ret = kernctl_track_id(session->fd, LTTNG_TRACKER_VUID, value);
+               if (!ret) {
+                       ret = LTTNG_OK;
+                       goto end;
+               }
+               break;
+       case LTTNG_TRACKER_VGID:
+               DBG("Kernel track VGID %d for session id %" PRIu64 ".",
+                               value, session->id);
+               ret = kernctl_track_id(session->fd, LTTNG_TRACKER_VGID, value);
+               if (!ret) {
+                       ret = LTTNG_OK;
+                       goto end;
+               }
+               break;
+       default:
+               ret = -EINVAL;
+               break;
        }
+       /* Error handling. */
        switch (-ret) {
        case EINVAL:
-               return LTTNG_ERR_INVALID;
+               ret = LTTNG_ERR_INVALID;
+               break;
        case ENOMEM:
-               return LTTNG_ERR_NOMEM;
-       case ENOENT:
-               return LTTNG_ERR_PID_NOT_TRACKED;
+               ret = LTTNG_ERR_NOMEM;
+               break;
+       case EEXIST:
+               ret = LTTNG_ERR_ID_TRACKED;
+               break;
        default:
-               return LTTNG_ERR_UNK;
+               ret = LTTNG_ERR_UNK;
+               break;
+       }
+       if (lttng_tracker_id_set_list(tracker_list, saved_ids, saved_ids_count) != LTTNG_OK) {
+               ERR("Error on tracker add error handling.\n");
        }
+end:
+       for (i = 0; i < saved_ids_count; i++) {
+               free(saved_ids[i].string);
+       }
+       free(saved_ids);
+       return ret;
 }
 
-ssize_t kernel_list_tracker_pids(struct ltt_kernel_session *session,
-               int **_pids)
+int kernel_untrack_id(enum lttng_tracker_type tracker_type,
+               struct ltt_kernel_session *session,
+               struct lttng_tracker_id *id)
 {
-       int fd, ret;
-       int pid;
-       ssize_t nbmem, count = 0;
-       FILE *fp;
-       int *pids;
-
-       fd = kernctl_list_tracker_pids(session->fd);
-       if (fd < 0) {
-               PERROR("kernel tracker pids list");
-               goto error;
+       int ret, value;
+       struct lttng_tracker_list *tracker_list;
+       struct lttng_tracker_id *saved_ids;
+       ssize_t saved_ids_count, i;
+
+       ret = lttng_tracker_id_lookup_string(tracker_type,
+                       id, &value);
+       if (ret != LTTNG_OK) {
+               return ret;
        }
 
-       fp = fdopen(fd, "r");
-       if (fp == NULL) {
-               PERROR("kernel tracker pids list fdopen");
-               goto error_fp;
+       tracker_list = get_id_tracker_list(session, tracker_type);
+       if (!tracker_list) {
+               return LTTNG_ERR_INVALID;
        }
-
-       nbmem = KERNEL_TRACKER_PIDS_INIT_LIST_SIZE;
-       pids = zmalloc(sizeof(*pids) * nbmem);
-       if (pids == NULL) {
-               PERROR("alloc list pids");
-               count = -ENOMEM;
+       /* Save list for restore on error. */
+       saved_ids_count = lttng_tracker_id_get_list(tracker_list, &saved_ids);
+       if (saved_ids_count < 0) {
+               return LTTNG_ERR_INVALID;
+       }
+       /* Remove from list. */
+       ret = lttng_tracker_list_remove(tracker_list, id);
+       if (ret != LTTNG_OK) {
                goto end;
        }
 
-       while (fscanf(fp, "process { pid = %u; };\n", &pid) == 1) {
-               if (count >= nbmem) {
-                       int *new_pids;
-                       size_t new_nbmem;
-
-                       new_nbmem = nbmem << 1;
-                       DBG("Reallocating pids list from %zu to %zu entries",
-                                       nbmem, new_nbmem);
-                       new_pids = realloc(pids, new_nbmem * sizeof(*new_pids));
-                       if (new_pids == NULL) {
-                               PERROR("realloc list events");
-                               free(pids);
-                               count = -ENOMEM;
-                               goto end;
-                       }
-                       /* Zero the new memory */
-                       memset(new_pids + nbmem, 0,
-                               (new_nbmem - nbmem) * sizeof(*new_pids));
-                       nbmem = new_nbmem;
-                       pids = new_pids;
+       switch (tracker_type) {
+       case LTTNG_TRACKER_PID:
+               DBG("Kernel untrack PID %d for session id %" PRIu64 ".",
+                               value, session->id);
+               ret = kernctl_untrack_pid(session->fd, value);
+               if (!ret) {
+                       ret = LTTNG_OK;
+                       goto end;
+               }
+               break;
+       case LTTNG_TRACKER_VPID:
+               DBG("Kernel untrack VPID %d for session id %" PRIu64 ".",
+                               value, session->id);
+               ret = kernctl_untrack_id(session->fd, LTTNG_TRACKER_VPID, value);
+               if (!ret) {
+                       ret = LTTNG_OK;
+                       goto end;
+               }
+               break;
+       case LTTNG_TRACKER_UID:
+               DBG("Kernel untrack UID %d for session id %" PRIu64 ".",
+                               value, session->id);
+               ret = kernctl_untrack_id(session->fd, LTTNG_TRACKER_UID, value);
+               if (!ret) {
+                       ret = LTTNG_OK;
+                       goto end;
+               }
+               break;
+       case LTTNG_TRACKER_GID:
+               DBG("Kernel untrack GID %d for session id %" PRIu64 ".",
+                               value, session->id);
+               ret = kernctl_untrack_id(session->fd, LTTNG_TRACKER_GID, value);
+               if (!ret) {
+                       ret = LTTNG_OK;
+                       goto end;
+               }
+               break;
+       case LTTNG_TRACKER_VUID:
+               DBG("Kernel untrack VUID %d for session id %" PRIu64 ".",
+                               value, session->id);
+               ret = kernctl_untrack_id(session->fd, LTTNG_TRACKER_VUID, value);
+               if (!ret) {
+                       ret = LTTNG_OK;
+                       goto end;
+               }
+               break;
+       case LTTNG_TRACKER_VGID:
+               DBG("Kernel untrack VGID %d for session id %" PRIu64 ".",
+                               value, session->id);
+               ret = kernctl_untrack_id(session->fd, LTTNG_TRACKER_VGID, value);
+               if (!ret) {
+                       ret = LTTNG_OK;
+                       goto end;
                }
-               pids[count++] = pid;
+               break;
+       default:
+               ret = -EINVAL;
+               break;
        }
 
-       *_pids = pids;
-       DBG("Kernel list tracker pids done (%zd pids)", count);
+       /* Error handling. */
+       switch (-ret) {
+       case EINVAL:
+               ret = LTTNG_ERR_INVALID;
+               break;
+       case ENOMEM:
+               ret = LTTNG_ERR_NOMEM;
+               break;
+       case EEXIST:
+               ret = LTTNG_ERR_ID_TRACKED;
+               break;
+       default:
+               ret = LTTNG_ERR_UNK;
+               break;
+       }
+
+       if (lttng_tracker_id_set_list(tracker_list, saved_ids, saved_ids_count) != LTTNG_OK) {
+               ERR("Error on tracker remove error handling.\n");
+       }
 end:
-       ret = fclose(fp);       /* closes both fp and fd */
-       if (ret) {
-               PERROR("fclose");
+       for (i = 0; i < saved_ids_count; i++) {
+               free(saved_ids[i].string);
        }
-       return count;
+       free(saved_ids);
+       return ret;
+}
 
-error_fp:
-       ret = close(fd);
-       if (ret) {
-               PERROR("close");
+/*
+ * Called with session lock held.
+ */
+ssize_t kernel_list_tracker_ids(enum lttng_tracker_type tracker_type,
+               struct ltt_kernel_session *session,
+               struct lttng_tracker_id **_ids)
+{
+       struct lttng_tracker_list *tracker_list;
+
+       tracker_list = get_id_tracker_list(session, tracker_type);
+       if (!tracker_list) {
+               return -LTTNG_ERR_INVALID;
        }
-error:
-       return -1;
+       return lttng_tracker_id_get_list(tracker_list, _ids);
 }
 
 /*
@@ -576,25 +735,6 @@ void kernel_wait_quiescent(int fd)
        }
 }
 
-/*
- * Kernel calibrate
- */
-int kernel_calibrate(int fd, struct lttng_kernel_calibrate *calibrate)
-{
-       int ret;
-
-       assert(calibrate);
-
-       ret = kernctl_calibrate(fd, calibrate);
-       if (ret < 0) {
-               PERROR("calibrate ioctl");
-               return -1;
-       }
-
-       return 0;
-}
-
-
 /*
  *  Force flush buffer of metadata.
  */
@@ -663,17 +803,22 @@ error:
  * Open stream of channel, register it to the kernel tracer and add it
  * to the stream list of the channel.
  *
+ * Note: given that the streams may appear in random order wrt CPU
+ * number (e.g. cpu hotplug), the index value of the stream number in
+ * the stream name is not necessarily linked to the CPU number.
+ *
  * Return the number of created stream. Else, a negative value.
  */
 int kernel_open_channel_stream(struct ltt_kernel_channel *channel)
 {
-       int ret, count = 0;
+       int ret;
        struct ltt_kernel_stream *lks;
 
        assert(channel);
 
        while ((ret = kernctl_create_stream(channel->fd)) >= 0) {
-               lks = trace_kernel_create_stream(channel->channel->name, count);
+               lks = trace_kernel_create_stream(channel->channel->name,
+                               channel->stream_count);
                if (lks == NULL) {
                        ret = close(ret);
                        if (ret) {
@@ -692,13 +837,10 @@ int kernel_open_channel_stream(struct ltt_kernel_channel *channel)
                lks->tracefile_size = channel->channel->attr.tracefile_size;
                lks->tracefile_count = channel->channel->attr.tracefile_count;
 
-               /* Add stream to channe stream list */
+               /* Add stream to channel stream list */
                cds_list_add(&lks->list, &channel->stream_list.head);
                channel->stream_count++;
 
-               /* Increment counter which represent CPU number. */
-               count++;
-
                DBG("Kernel stream %s created (fd: %d, state: %d)", lks->name, lks->fd,
                                lks->state);
        }
@@ -1040,12 +1182,10 @@ int kernel_snapshot_record(struct ltt_kernel_session *ksess,
 
                /* For each channel, ask the consumer to snapshot it. */
                cds_list_for_each_entry(chan, &ksess->channel_list.head, list) {
-                       pthread_mutex_lock(socket->lock);
                        ret = consumer_snapshot_channel(socket, chan->fd, output, 0,
                                        ksess->uid, ksess->gid,
                                        DEFAULT_KERNEL_TRACE_DIR, wait,
                                        nb_packets_per_stream);
-                       pthread_mutex_unlock(socket->lock);
                        if (ret < 0) {
                                ret = LTTNG_ERR_KERN_CONSUMER_FAIL;
                                (void) kernel_consumer_destroy_metadata(socket,
@@ -1055,11 +1195,9 @@ int kernel_snapshot_record(struct ltt_kernel_session *ksess,
                }
 
                /* Snapshot metadata, */
-               pthread_mutex_lock(socket->lock);
                ret = consumer_snapshot_channel(socket, ksess->metadata->fd, output,
                                1, ksess->uid, ksess->gid,
                                DEFAULT_KERNEL_TRACE_DIR, wait, 0);
-               pthread_mutex_unlock(socket->lock);
                if (ret < 0) {
                        ret = LTTNG_ERR_KERN_CONSUMER_FAIL;
                        goto error_consumer;
This page took 0.032385 seconds and 5 git commands to generate.