*/
#define _LGPL_SOURCE
-#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
/*
* 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)
DBG("Adding context to channel %s", chan->channel->name);
ret = kernctl_add_context(chan->fd, &ctx->ctx);
if (ret < 0) {
- switch (errno) {
+ switch (-ret) {
case ENOSYS:
/* Exists but not available for this kernel */
ret = LTTNG_ERR_KERN_CONTEXT_UNAVAILABLE;
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;
}
ret = kernctl_create_event(channel->fd, event->event);
if (ret < 0) {
- switch (errno) {
+ switch (-ret) {
case EEXIST:
break;
case ENOSYS:
default:
PERROR("create event ioctl");
}
- ret = -errno;
goto free_event;
}
ret = kernctl_enable(event->fd);
if (ret < 0) {
- switch (errno) {
+ switch (-ret) {
case EEXIST:
ret = LTTNG_ERR_KERN_EVENT_EXIST;
break;
ret = kernctl_disable(chan->fd);
if (ret < 0) {
PERROR("disable chan ioctl");
- ret = errno;
goto error;
}
assert(chan);
ret = kernctl_enable(chan->fd);
- if (ret < 0 && errno != EEXIST) {
+ if (ret < 0 && ret != -EEXIST) {
PERROR("Enable kernel chan");
goto error;
}
ret = kernctl_enable(event->fd);
if (ret < 0) {
- switch (errno) {
+ switch (-ret) {
case EEXIST:
ret = LTTNG_ERR_KERN_EVENT_EXIST;
break;
ret = kernctl_disable(event->fd);
if (ret < 0) {
- switch (errno) {
+ switch (-ret) {
case EEXIST:
ret = LTTNG_ERR_KERN_EVENT_EXIST;
break;
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 (errno) {
- 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;
}
- switch (errno) {
- case EINVAL:
+ /* 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:
+ 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;
+ }
+
+ /* 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;
}
- *_pids = pids;
- DBG("Kernel list tracker pids done (%zd pids)", count);
+ 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);
}
/*
}
}
-/*
- * 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.
*/
* 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) {
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);
}
/* 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,
}
/* 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;