#include "channel.h"
#include "kernel-ctl.h"
+#include "ust-ctl.h"
#include "utils.h"
/*
* Return allocated channel attributes.
*/
-static struct lttng_channel *init_default_attr(int dom, char *name)
+static struct lttng_channel *init_default_attr(int dom)
{
struct lttng_channel *chan;
goto error_alloc;
}
- if (snprintf(chan->name, sizeof(chan->name), "%s", name) < 0) {
- perror("snprintf channel name");
+ if (snprintf(chan->name, sizeof(chan->name), "%s",
+ DEFAULT_CHANNEL_NAME) < 0) {
+ perror("snprintf default channel name");
goto error;
}
chan->attr.num_subbuf = DEFAULT_KERNEL_CHANNEL_SUBBUF_NUM;
chan->attr.output = DEFAULT_KERNEL_CHANNEL_OUTPUT;
break;
- /* TODO: add UST */
+ case LTTNG_DOMAIN_UST_PID:
+ chan->attr.subbuf_size = DEFAULT_UST_CHANNEL_SUBBUF_SIZE;
+ chan->attr.num_subbuf = DEFAULT_UST_CHANNEL_SUBBUF_NUM;
+ chan->attr.output = DEFAULT_UST_CHANNEL_OUTPUT;
+ break;
default:
goto error; /* Not implemented */
}
* Create kernel channel of the kernel session and notify kernel thread.
*/
int channel_kernel_create(struct ltt_kernel_session *ksession,
- char *channel_name, struct lttng_channel *chan, int kernel_pipe)
+ struct lttng_channel *chan, int kernel_pipe)
{
int ret;
struct lttng_channel *attr = chan;
/* Creating channel attributes if needed */
if (attr == NULL) {
- attr = init_default_attr(LTTNG_DOMAIN_KERNEL, channel_name);
+ attr = init_default_attr(LTTNG_DOMAIN_KERNEL);
if (attr == NULL) {
ret = LTTCOMM_FATAL;
goto error;
error:
return ret;
}
+
+/*
+ * Create UST channel and enable it on the tracer.
+ */
+int channel_ust_create(struct ltt_ust_session *usession,
+ struct lttng_channel *chan, int sock)
+{
+ int ret;
+ struct lttng_channel *attr = chan;
+
+ /* Creating channel attributes if needed */
+ if (attr == NULL) {
+ attr = init_default_attr(LTTNG_DOMAIN_UST_PID);
+ if (attr == NULL) {
+ ret = LTTCOMM_FATAL;
+ goto error;
+ }
+ }
+
+ ret = ustctl_create_channel(sock, usession, attr);
+ if (ret < 0) {
+ ret = LTTCOMM_UST_CHAN_FAIL;
+ goto error;
+ }
+
+ DBG2("Channel %s UST create successfully for sock:%d", attr->name, sock);
+
+ ret = LTTCOMM_OK;
+
+error:
+ return ret;
+}
+
+/*
+ * Enable UST channel on the tracer.
+ */
+int channel_ust_enable(struct ltt_ust_session *usession,
+ struct ltt_ust_channel *uchan, int sock)
+{
+ int ret;
+ ret = LTTCOMM_OK;
+
+ ret = ustctl_enable_channel(sock, usession, uchan);
+ if (ret < 0) {
+ ret = LTTCOMM_UST_CHAN_FAIL;
+ goto error;
+ }
+
+ ret = LTTCOMM_OK;
+
+error:
+ return ret;
+}
+
+/*
+ * Disable UST channel on the tracer.
+ */
+int channel_ust_disable(struct ltt_ust_session *usession,
+ struct ltt_ust_channel *uchan, int sock)
+{
+ int ret;
+ ret = LTTCOMM_OK;
+
+ ret = ustctl_disable_channel(sock, usession, uchan);
+ if (ret < 0) {
+ ret = LTTCOMM_UST_CHAN_FAIL;
+ goto error;
+ }
+
+ ret = LTTCOMM_OK;
+
+error:
+ return ret;
+}
#include <lttng/lttng.h>
#include "trace-kernel.h"
+#include "trace-ust.h"
int channel_kernel_disable(struct ltt_kernel_session *ksession,
char *channel_name);
int channel_kernel_enable(struct ltt_kernel_session *ksession,
struct ltt_kernel_channel *kchan);
int channel_kernel_create(struct ltt_kernel_session *ksession,
- char *channel_name, struct lttng_channel *chan, int kernel_pipe);
+ struct lttng_channel *chan, int kernel_pipe);
+
+int channel_ust_create(struct ltt_ust_session *usession,
+ struct lttng_channel *chan, int sock);
+int channel_ust_disable(struct ltt_ust_session *usession,
+ struct ltt_ust_channel *uchan, int sock);
+int channel_ust_enable(struct ltt_ust_session *usession,
+ struct ltt_ust_channel *uchan, int sock);
#endif /* _LTT_CHANNEL_H */
/*
* Create an UST session and add it to the session ust list.
*/
-static int create_ust_session(pid_t pid, struct ltt_session *session)
+static int create_ust_session(struct ltt_session *session,
+ struct lttng_domain *domain)
{
- int ret = -1;
+ int ret;
struct ltt_ust_session *lus;
+ struct ltt_traceable_app *app;
+
+ switch (domain->type) {
+ case LTTNG_DOMAIN_UST_PID:
+ app = traceable_app_get_by_pid(domain->attr.pid);
+ if (app == NULL) {
+ ret = LTTCOMM_APP_NOT_FOUND;
+ goto error;
+ }
+ break;
+ default:
+ goto error;
+ }
DBG("Creating UST session");
- lus = trace_ust_create_session(session->path, pid);
+ lus = trace_ust_create_session(session->path, domain->attr.pid, domain);
if (lus == NULL) {
+ ret = LTTCOMM_UST_SESS_FAIL;
goto error;
}
if (ret < 0) {
if (ret != -EEXIST) {
ERR("Trace directory creation error");
+ ret = LTTCOMM_UST_SESS_FAIL;
goto error;
}
}
/* Create session on the UST tracer */
- ret = ustctl_create_session(lus);
+ ret = ustctl_create_session(app->sock, lus);
if (ret < 0) {
+ ret = LTTCOMM_UST_SESS_FAIL;
goto error;
}
- return 0;
+ cds_list_add(&lus->list, &session->ust_session_list.head);
+ session->ust_session_list.count++;
+
+ return LTTCOMM_OK;
error:
free(lus);
kernel_wait_quiescent(kernel_tracer_fd);
break;
+ case LTTNG_DOMAIN_UST_PID:
+ break;
default:
- /* TODO: Userspace tracing */
- ret = LTTCOMM_NOT_IMPLEMENTED;
+ ret = LTTCOMM_UNKNOWN_DOMAIN;
goto error;
}
/*
* Command LTTNG_ENABLE_CHANNEL processed by the client thread.
*/
-static int cmd_enable_channel(struct ltt_session *session, int domain,
- char *channel_name, struct lttng_channel *attr)
+static int cmd_enable_channel(struct ltt_session *session,
+ struct lttng_domain *domain, struct lttng_channel *attr)
{
int ret;
- struct ltt_kernel_channel *kchan;
- switch (domain) {
- case LTTNG_DOMAIN_KERNEL:
- kchan = trace_kernel_get_channel_by_name(channel_name,
- session->kernel_session);
- if (kchan == NULL) {
- ret = channel_kernel_create(session->kernel_session,
- channel_name, attr, kernel_poll_pipe[1]);
- } else {
- ret = channel_kernel_enable(session->kernel_session, kchan);
- }
+ switch (domain->type) {
+ case LTTNG_DOMAIN_KERNEL:
+ {
+ struct ltt_kernel_channel *kchan;
- if (ret != LTTCOMM_OK) {
+ kchan = trace_kernel_get_channel_by_name(attr->name,
+ session->kernel_session);
+ if (kchan == NULL) {
+ ret = channel_kernel_create(session->kernel_session,
+ attr, kernel_poll_pipe[1]);
+ } else {
+ ret = channel_kernel_enable(session->kernel_session, kchan);
+ }
+
+ if (ret != LTTCOMM_OK) {
+ goto error;
+ }
+
+ kernel_wait_quiescent(kernel_tracer_fd);
+ break;
+ }
+ case LTTNG_DOMAIN_UST_PID:
+ {
+ struct ltt_ust_event *uevent, *new_uevent;
+ struct ltt_ust_session *usess;
+ struct ltt_ust_channel *uchan, *app_chan;
+ struct ltt_traceable_app *app;
+
+ usess = trace_ust_get_session_by_pid(&session->ust_session_list,
+ domain->attr.pid);
+ if (usess == NULL) {
+ ret = LTTCOMM_UST_CHAN_NOT_FOUND;
+ goto error;
+ }
+
+ app = traceable_app_get_by_pid(domain->attr.pid);
+ if (app == NULL) {
+ ret = LTTCOMM_APP_NOT_FOUND;
+ goto error;
+ }
+
+ uchan = trace_ust_get_channel_by_name(attr->name, usess);
+ if (uchan == NULL) {
+ ret = channel_ust_create(usess, attr, app->sock);
+ } else {
+ ret = channel_ust_enable(usess, uchan, app->sock);
+ }
+
+ if (ret != LTTCOMM_OK) {
+ goto error;
+ }
+
+ /*TODO: This should be put in an external function */
+
+ /* Copy UST channel to add to the traceable app */
+ uchan = trace_ust_get_channel_by_name(attr->name, usess);
+ if (uchan == NULL) {
+ ret = LTTCOMM_FATAL;
+ goto error;
+ }
+
+ app_chan = trace_ust_create_channel(attr, session->path);
+ if (app_chan == NULL) {
+ PERROR("malloc ltt_ust_channel");
+ ret = LTTCOMM_FATAL;
+ goto error;
+ }
+
+ memcpy(app_chan, uchan, sizeof(struct ltt_ust_channel));
+ CDS_INIT_LIST_HEAD(&app_chan->events.head);
+
+ cds_list_for_each_entry(uevent, &uchan->events.head, list) {
+ new_uevent = malloc(sizeof(struct ltt_ust_event));
+ if (new_uevent == NULL) {
+ PERROR("malloc ltt_ust_event");
+ ret = LTTCOMM_FATAL;
goto error;
}
- kernel_wait_quiescent(kernel_tracer_fd);
- break;
- default:
- /* TODO: Userspace tracing */
- ret = LTTCOMM_NOT_IMPLEMENTED;
- goto error;
+ memcpy(new_uevent, uevent, sizeof(struct ltt_ust_event));
+ cds_list_add(&new_uevent->list, &app_chan->events.head);
+ app_chan->events.count++;
+ }
+
+ /* Add channel to traceable_app */
+ cds_list_add(&app_chan->list, &app->channels.head);
+ app->channels.count++;
+
+ DBG("UST channel %s created for app sock %d with pid %d",
+ attr->name, app->sock, domain->attr.pid);
+ break;
+ }
+ default:
+ ret = LTTCOMM_UNKNOWN_DOMAIN;
+ goto error;
}
ret = LTTCOMM_OK;
session->kernel_session);
if (kchan == NULL) {
/* This call will notify the kernel thread */
- ret = channel_kernel_create(session->kernel_session, channel_name,
+ ret = channel_kernel_create(session->kernel_session,
NULL, kernel_poll_pipe[1]);
if (ret != LTTCOMM_OK) {
goto error;
session->kernel_session);
if (kchan == NULL) {
/* This call will notify the kernel thread */
- ret = channel_kernel_create(session->kernel_session, channel_name,
- NULL, kernel_poll_pipe[1]);
+ ret = channel_kernel_create(session->kernel_session, NULL,
+ kernel_poll_pipe[1]);
if (ret != LTTCOMM_OK) {
goto error;
}
static int process_client_msg(struct command_ctx *cmd_ctx)
{
int ret = LTTCOMM_OK;
- int need_kernel_session = 1;
+ int need_tracing_session = 1;
DBG("Processing client command %d", cmd_ctx->lsm->cmd_type);
/*
* Check for command that don't needs to allocate a returned payload. We do
- * this here so we don't have to make the call for no payload" at each
+ * this here so we don't have to make the call for no payload at each
* command.
*/
switch(cmd_ctx->lsm->cmd_type) {
case LTTNG_CREATE_SESSION:
case LTTNG_LIST_SESSIONS:
case LTTNG_LIST_TRACEPOINTS:
- need_kernel_session = 0;
+ need_tracing_session = 0;
break;
default:
DBG("Getting session %s by name", cmd_ctx->lsm->session.name);
}
/* Need a session for kernel command */
- if (need_kernel_session) {
+ if (need_tracing_session) {
if (cmd_ctx->session->kernel_session == NULL) {
ret = create_kernel_session(cmd_ctx->session);
if (ret < 0) {
}
}
break;
+ case LTTNG_DOMAIN_UST_PID:
+ {
+ struct ltt_ust_session *usess;
+
+ if (need_tracing_session) {
+ usess = trace_ust_get_session_by_pid(
+ &cmd_ctx->session->ust_session_list,
+ cmd_ctx->lsm->domain.attr.pid);
+ if (usess == NULL) {
+ ret = create_ust_session(cmd_ctx->session,
+ &cmd_ctx->lsm->domain);
+ if (ret != LTTCOMM_OK) {
+ goto error;
+ }
+ }
+ }
+ break;
+ }
default:
/* TODO Userspace tracer */
break;
}
case LTTNG_ENABLE_CHANNEL:
{
- ret = cmd_enable_channel(cmd_ctx->session, cmd_ctx->lsm->domain.type,
- cmd_ctx->lsm->u.enable.channel_name,
+ ret = cmd_enable_channel(cmd_ctx->session, &cmd_ctx->lsm->domain,
&cmd_ctx->lsm->u.channel.chan);
break;
}
#include <lttngerr.h>
#include <lttng-share.h>
+#include <lttng-ust.h>
#include "trace-ust.h"
/*
- * Return an UST session by traceable app PID.
+ * Using a ust session list, it will return the session corresponding to the
+ * pid. Must be a session of domain LTTNG_DOMAIN_UST_PID.
*/
-struct ltt_ust_session *trace_ust_get_session_by_pid(pid_t pid,
- struct ltt_ust_session_list *session_list)
+struct ltt_ust_session *trace_ust_get_session_by_pid(
+ struct ltt_ust_session_list *session_list, pid_t pid)
{
- struct ltt_ust_session *lus;
+ struct ltt_ust_session *sess;
- cds_list_for_each_entry(lus, &session_list->head, list) {
- if (lus->app->pid == pid) {
- DBG("Found UST session by pid %d", pid);
- return lus;
+ if (session_list == NULL) {
+ ERR("Session list is NULL");
+ goto error;
+ }
+
+ cds_list_for_each_entry(sess, &session_list->head, list) {
+ if (sess->domain.type == LTTNG_DOMAIN_UST_PID &&
+ sess->domain.attr.pid == pid) {
+ DBG2("Trace UST session found by pid %d", pid);
+ return sess;
}
}
+error:
return NULL;
}
cds_list_for_each_entry(chan, &session->channels.head, list) {
if (strcmp(name, chan->name) == 0) {
- DBG("Found UST channel by name %s", name);
+ DBG2("Found UST channel by name %s", name);
return chan;
}
}
}
cds_list_for_each_entry(ev, &channel->events.head, list) {
- if (strcmp(name, ev->event->name) == 0) {
+ if (strcmp(name, ev->attr.name) == 0) {
DBG("Found UST event by name %s for channel %s", name,
channel->name);
return ev;
*
* Return pointer to structure or NULL.
*/
-struct ltt_ust_session *trace_ust_create_session(char *path, pid_t pid)
+struct ltt_ust_session *trace_ust_create_session(char *path, pid_t pid,
+ struct lttng_domain *domain)
{
int ret;
struct ltt_ust_session *lus;
lus->handle = -1;
lus->enabled = 1;
lus->uconsumer_fds_sent = 0;
- lus->path = NULL;
lus->metadata = NULL;
- lus->app = NULL; /* TODO: Search app by PID */
lus->channels.count = 0;
CDS_INIT_LIST_HEAD(&lus->channels.head);
+ /* Copy lttng_domain */
+ memcpy(&lus->domain, domain, sizeof(struct lttng_domain));
+
/* Set session path */
- ret = asprintf(&lus->path, "%s/ust_%d", path, pid);
+ ret = snprintf(lus->path, PATH_MAX, "%s/ust_%d", path, pid);
if (ret < 0) {
- perror("asprintf kernel traces path");
+ PERROR("snprintf kernel traces path");
goto error;
}
+ DBG2("UST trace session create successful");
+
return lus;
error:
*
* Return pointer to structure or NULL.
*/
-struct ltt_ust_channel *trace_ust_create_channel(char *name, char *path,
- struct lttng_ust_channel *chan)
+struct ltt_ust_channel *trace_ust_create_channel(struct lttng_channel *chan,
+ char *path)
{
int ret;
struct ltt_ust_channel *luc;
goto error;
}
- luc->attr = malloc(sizeof(struct lttng_ust_channel));
- if (luc->attr == NULL) {
- perror("lttng_ust_channel malloc");
- goto error;
+ /* Copy UST channel attributes */
+ memcpy(&luc->attr, &chan->attr, sizeof(struct lttng_ust_channel));
+
+ /* Translate to UST output enum */
+ switch (luc->attr.output) {
+ default:
+ luc->attr.output = LTTNG_UST_MMAP;
+ break;
}
- memcpy(luc->attr, chan, sizeof(struct lttng_ust_channel));
luc->handle = -1;
luc->enabled = 1;
- luc->ctx = NULL;
luc->events.count = 0;
CDS_INIT_LIST_HEAD(&luc->events.head);
+ memset(&luc->ctx, 0, sizeof(struct lttng_ust_context));
+
/* Copy channel name */
- strncpy(luc->name, name, LTTNG_UST_SYM_NAME_LEN);
+ strncpy(luc->name, chan->name, sizeof(&luc->name));
luc->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
/* Set trace output path */
- ret = asprintf(&luc->trace_path, "%s", path);
+ ret = snprintf(luc->trace_path, PATH_MAX, "%s", path);
if (ret < 0) {
perror("asprintf ust create channel");
goto error;
struct ltt_ust_event *trace_ust_create_event(struct lttng_event *ev)
{
struct ltt_ust_event *lue;
- struct lttng_ust_event *event;
lue = malloc(sizeof(struct ltt_ust_event));
- event = malloc(sizeof(struct lttng_ust_event));
- if (lue == NULL || event == NULL) {
- perror("ust event malloc");
+ if (lue == NULL) {
+ PERROR("ust event malloc");
goto error;
}
switch (ev->type) {
case LTTNG_EVENT_PROBE:
- event->instrumentation = LTTNG_UST_PROBE;
+ lue->attr.instrumentation = LTTNG_UST_PROBE;
break;
case LTTNG_EVENT_FUNCTION:
- event->instrumentation = LTTNG_UST_FUNCTION;
+ lue->attr.instrumentation = LTTNG_UST_FUNCTION;
break;
case LTTNG_EVENT_FUNCTION_ENTRY:
- event->instrumentation = LTTNG_UST_FUNCTION;
+ lue->attr.instrumentation = LTTNG_UST_FUNCTION;
break;
case LTTNG_EVENT_TRACEPOINT:
- event->instrumentation = LTTNG_UST_TRACEPOINT;
+ lue->attr.instrumentation = LTTNG_UST_TRACEPOINT;
break;
default:
ERR("Unknown ust instrumentation type (%d)", ev->type);
}
/* Copy event name */
- strncpy(event->name, ev->name, LTTNG_UST_SYM_NAME_LEN);
- event->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+ strncpy(lue->attr.name, ev->name, LTTNG_UST_SYM_NAME_LEN);
+ lue->attr.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
/* Setting up a ust event */
lue->handle = -1;
- lue->event = event;
lue->enabled = 1;
- lue->ctx = NULL;
+ memset(&lue->ctx, 0, sizeof(struct lttng_ust_context));
return lue;
{
int ret;
struct ltt_ust_metadata *lum;
- struct lttng_ust_channel *attr;
lum = malloc(sizeof(struct ltt_ust_metadata));
- attr = malloc(sizeof(struct lttng_ust_channel));
- if (lum == NULL || attr == NULL) {
+ if (lum == NULL) {
perror("ust metadata malloc");
goto error;
}
/* Set default attributes */
- attr->overwrite = DEFAULT_CHANNEL_OVERWRITE;
- attr->subbuf_size = DEFAULT_METADATA_SUBBUF_SIZE;
- attr->num_subbuf = DEFAULT_METADATA_SUBBUF_NUM;
- attr->switch_timer_interval = DEFAULT_CHANNEL_SWITCH_TIMER;
- attr->read_timer_interval = DEFAULT_CHANNEL_READ_TIMER;
- attr->output = DEFAULT_UST_CHANNEL_OUTPUT;
-
- lum->attr = attr;
+ lum->attr.overwrite = DEFAULT_CHANNEL_OVERWRITE;
+ lum->attr.subbuf_size = DEFAULT_METADATA_SUBBUF_SIZE;
+ lum->attr.num_subbuf = DEFAULT_METADATA_SUBBUF_NUM;
+ lum->attr.switch_timer_interval = DEFAULT_CHANNEL_SWITCH_TIMER;
+ lum->attr.read_timer_interval = DEFAULT_CHANNEL_READ_TIMER;
+ lum->attr.output = DEFAULT_UST_CHANNEL_OUTPUT;
+
lum->handle = -1;
/* Set metadata trace path */
ret = asprintf(&lum->trace_path, "%s/metadata", path);
*/
void trace_ust_destroy_event(struct ltt_ust_event *event)
{
- DBG("[trace] Destroy ust event %s", event->event->name);
-
- /* Free attributes */
- free(event->event);
- free(event->ctx);
+ DBG("[trace] Destroy ust event %s", event->attr.name);
/* Remove from event list */
cds_list_del(&event->list);
DBG("[trace] Destroy ust channel %d", channel->handle);
- free(channel->trace_path);
- /* Free attributes structure */
- free(channel->attr);
- free(channel->ctx);
-
/* For each event in the channel list */
cds_list_for_each_entry_safe(event, etmp, &channel->events.head, list) {
trace_ust_destroy_event(event);
DBG("[trace] Destroy ust metadata %d", metadata->handle);
/* Free attributes */
- free(metadata->attr);
free(metadata->trace_path);
free(metadata);
trace_ust_destroy_channel(channel);
}
- free(session->path);
+ if (session->path) {
+ free(session->path);
+ }
+
free(session);
}
#include <lttng/lttng.h>
#include <lttng-ust.h>
-#include "traceable-app.h"
-
/*
* UST session list.
*/
struct ltt_ust_event {
int handle;
int enabled;
- struct lttng_ust_context *ctx;
- struct lttng_ust_event *event;
+ struct lttng_ust_context ctx;
+ struct lttng_ust_event attr;
struct cds_list_head list;
};
struct ltt_ust_channel {
int handle;
int enabled;
- char *name;
- char *trace_path; /* Trace file path name */
- struct lttng_ust_context *ctx;
- struct lttng_ust_channel *attr;
+ char name[LTTNG_UST_SYM_NAME_LEN];
+ char trace_path[PATH_MAX]; /* Trace file path name */
+ struct lttng_ust_context ctx;
+ struct lttng_ust_channel attr;
struct ltt_ust_event_list events;
struct cds_list_head list;
};
struct ltt_ust_metadata {
int handle;
char *trace_path; /* Trace file path name */
- struct lttng_ust_channel *attr;
+ struct lttng_ust_channel attr;
};
/* UST session */
int handle;
int enabled;
int uconsumer_fds_sent;
- char *path;
- struct ltt_traceable_app *app;
+ char path[PATH_MAX];
+ struct lttng_domain domain;
struct ltt_ust_metadata *metadata;
struct ltt_ust_channel_list channels;
struct cds_list_head list;
char *name, struct ltt_ust_channel *channel);
struct ltt_ust_channel *trace_ust_get_channel_by_name(
char *name, struct ltt_ust_session *session);
-struct ltt_ust_session *trace_ust_get_session_by_pid(pid_t pid,
- struct ltt_ust_session_list *session_list);
+struct ltt_ust_session *trace_ust_get_session_by_pid(
+ struct ltt_ust_session_list *session_list, pid_t pid);
/*
* Create functions malloc() the data structure.
*/
-struct ltt_ust_session *trace_ust_create_session(char *path, pid_t pid);
-struct ltt_ust_channel *trace_ust_create_channel(char *name, char *path,
- struct lttng_ust_channel *attr);
+struct ltt_ust_session *trace_ust_create_session(char *path, pid_t pid,
+ struct lttng_domain *domain);
+struct ltt_ust_channel *trace_ust_create_channel(struct lttng_channel *attr,
+ char *path);
struct ltt_ust_event *trace_ust_create_event(struct lttng_event *ev);
struct ltt_ust_metadata *trace_ust_create_metadata(char *path);
*/
static void del_traceable_app(struct ltt_traceable_app *lta)
{
+ struct ltt_ust_channel *chan;
+
cds_list_del(<a->list);
/* Sanity check */
if (ltt_traceable_app_list.count > 0) {
ltt_traceable_app_list.count--;
}
+
+ cds_list_for_each_entry(chan, <a->channels.head, list) {
+ trace_ust_destroy_channel(chan);
+ }
}
/*
cds_list_for_each_entry(iter, <t_traceable_app_list.head, list) {
if (iter->pid == pid) {
/* Found */
+ DBG2("Found traceable app by pid %d", pid);
return iter;
}
}
+ DBG2("Traceable app with pid %d not found", pid);
+
return NULL;
}
lta->sock = sock;
strncpy(lta->name, msg->name, sizeof(lta->name));
lta->name[16] = '\0';
+ CDS_INIT_LIST_HEAD(<a->channels.head);
lock_apps_list();
add_traceable_app(lta);
lta = find_app_by_sock(sock);
if (lta) {
DBG("PID %d unregistered with sock %d", lta->pid, sock);
- close(lta->sock);
del_traceable_app(lta);
+ close(lta->sock);
free(lta);
}
unlock_apps_list();
* cleanup() functions meaning that the program will exit.
*/
cds_list_for_each_entry_safe(iter, tmp, <t_traceable_app_list.head, list) {
+ del_traceable_app(iter);
close(iter->sock);
free(iter);
}
#include <stdint.h>
#include <urcu/list.h>
+#include "trace-ust.h"
+
/*
* Application registration data structure.
*/
uint32_t v_major; /* Verion major number */
uint32_t v_minor; /* Verion minor number */
char name[17]; /* Process name (short) */
+ struct ltt_ust_channel_list channels;
struct cds_list_head list;
};
void clean_traceable_apps_list(void);
struct ltt_traceable_app_list *get_traceable_apps_list(void);
+struct ltt_traceable_app *traceable_app_get_by_pid(pid_t pid);
+
#endif /* _TRACEABLE_APP_H */
/*
* Send msg containing a command to an UST application via sock and wait for
- * the reply.
+ * the reply. Caller must free() the reply structure sent back.
*
* Return the replied structure or NULL.
*/
goto error;
}
- DBG("Sending UST command %d to sock %d", msg->cmd, sock);
+ DBG2("Sending UST command %d to sock %d", msg->cmd, sock);
/* Send UST msg */
len = lttcomm_send_unix_sock(sock, msg, sizeof(*msg));
goto error;
}
- DBG("Receiving UST reply on sock %d", sock);
+ DBG2("Receiving UST reply on sock %d", sock);
/* Get UST reply */
len = lttcomm_recv_unix_sock(sock, reply, sizeof(*reply));
/*
* Create an UST session on the tracer.
*/
-int ustctl_create_session(struct ltt_ust_session *session)
+int ustctl_create_session(int sock, struct ltt_ust_session *session)
{
struct lttcomm_ust_msg command;
- struct lttcomm_ust_reply *reply;
-
- DBG("Creating UST session for app pid:%d", session->app->pid);
+ struct lttcomm_ust_reply *reply = NULL;
command.cmd = LTTNG_UST_SESSION;
command.handle = LTTNG_UST_ROOT_HANDLE;
- reply = ustcomm_send_command(session->app->sock, &command);
+ reply = ustcomm_send_command(sock, &command);
if (reply == NULL) {
goto error;
}
}
/* Save session handle */
- session->handle = reply->handle;
+ session->handle = reply->ret_val;
+ free(reply);
+
+ DBG2("ustctl create session command successful");
+ return 0;
+
+error:
+ free(reply);
+ return -1;
+}
+
+/*
+ * Create UST channel to the tracer.
+ */
+int ustctl_create_channel(int sock, struct ltt_ust_session *session,
+ struct lttng_channel *channel)
+{
+ struct lttcomm_ust_msg command;
+ struct lttcomm_ust_reply *reply = NULL;
+ struct ltt_ust_channel *uchan;
+
+ uchan = trace_ust_create_channel(channel, session->path);
+ if (uchan == NULL) {
+ goto error;
+ }
+
+ memset(&command, 0, sizeof(command));
+
+ command.cmd = LTTNG_UST_CHANNEL;
+ command.handle = session->handle;
+
+ /* Copy channel attributes to command */
+ memcpy(&command.u.channel, &uchan->attr, sizeof(command.u.channel));
+
+ reply = ustcomm_send_command(sock, &command);
+ if (reply == NULL) {
+ goto error;
+ }
+
+ if (reply->ret_code != LTTCOMM_OK) {
+ DBG("Return code (%d): %s", reply->ret_code,
+ lttcomm_get_readable_code(reply->ret_code));
+ goto error;
+ }
+
+ uchan->handle = reply->ret_val;
+
+ /* Add channel to session */
+ cds_list_add(&uchan->list, &session->channels.head);
+ session->channels.count++;
+
+ free(reply);
+
+ return 0;
+
+error:
+ free(reply);
+ return -1;
+}
+
+/*
+ * Enable UST channel.
+ */
+int ustctl_enable_channel(int sock, struct ltt_ust_session *session,
+ struct ltt_ust_channel *chan)
+{
+ struct lttcomm_ust_msg command;
+ struct lttcomm_ust_reply *reply = NULL;
+
+ memset(&command, 0, sizeof(command));
+
+ command.cmd = LTTNG_UST_ENABLE;
+ command.handle = chan->handle;
+
+ reply = ustcomm_send_command(sock, &command);
+ if (reply == NULL) {
+ goto error;
+ }
+
+ if (reply->ret_code != LTTCOMM_OK) {
+ DBG("Return code (%d): %s", reply->ret_code,
+ lttcomm_get_readable_code(reply->ret_code));
+ goto error;
+ } else if (reply->handle != chan->handle) {
+ ERR("Receive wrong handle from UST reply on enable channel");
+ goto error;
+ }
+
+ chan->enabled = 1;
+ free(reply);
+
+ DBG2("ustctl enable channel successful for sock %d", sock);
+ return 0;
+
+error:
+ free(reply);
+ return -1;
+}
+
+/*
+ * Disable UST channel.
+ */
+int ustctl_disable_channel(int sock, struct ltt_ust_session *session,
+ struct ltt_ust_channel *chan)
+{
+ struct lttcomm_ust_msg command;
+ struct lttcomm_ust_reply *reply = NULL;
+
+ memset(&command, 0, sizeof(command));
+
+ command.cmd = LTTNG_UST_DISABLE;
+ command.handle = chan->handle;
+
+ reply = ustcomm_send_command(sock, &command);
+ if (reply == NULL) {
+ goto error;
+ }
+
+ if (reply->ret_code != LTTCOMM_OK) {
+ DBG("Return code (%d): %s", reply->ret_code,
+ lttcomm_get_readable_code(reply->ret_code));
+ goto error;
+ } else if (reply->handle != chan->handle) {
+ ERR("Receive wrong handle from UST reply on enable channel");
+ goto error;
+ }
+
+ chan->enabled = 1;
+ free(reply);
+ DBG2("ustctl disable channel successful for sock %d", sock);
return 0;
error:
+ free(reply);
return -1;
}
#ifndef _LTT_UST_CTL_H
#define _LTT_UST_CTL_H
+#include <lttng/lttng.h>
+
#include "trace-ust.h"
int ustctl_register_done(int sock);
-int ustctl_create_session(struct ltt_ust_session *session);
-int ustctl_destroy_session(struct ltt_ust_session *session);
+int ustctl_create_channel(int sock, struct ltt_ust_session *session,
+ struct lttng_channel *channel);
+int ustctl_create_session(int sock, struct ltt_ust_session *session);
+int ustctl_destroy_session(int sock, struct ltt_ust_session *session);
+int ustctl_disable_channel(int sock, struct ltt_ust_session *session,
+ struct ltt_ust_channel *chan);
+int ustctl_enable_channel(int sock, struct ltt_ust_session *session,
+ struct ltt_ust_channel *chan);
#endif /* _LTT_UST_CTL_H */