LTTCOMM_KERN_NO_SESSION, /* No kernel session found */
LTTCOMM_KERN_LIST_FAIL, /* Kernel listing events failed */
LTTCOMM_UST_SESS_FAIL, /* UST create session failed */
+ LTTCOMM_UST_CHAN_FAIL, /* UST create channel failed */
LTTCOMM_UST_CHAN_NOT_FOUND, /* UST channel not found */
- LTTCOMM_UST_CHAN_FAIL, /* UST create channel failed */
+ LTTCOMM_UST_CHAN_DISABLE_FAIL, /* UST disable channel failed */
+ LTTCOMM_UST_CHAN_ENABLE_FAIL, /* UST enable channel failed */
+ LTTCOMM_UST_CONTEXT_FAIL, /* UST add context failed */
+ LTTCOMM_UST_ENABLE_FAIL, /* UST enable event failed */
+ LTTCOMM_UST_DISABLE_FAIL, /* UST disable event failed */
+ LTTCOMM_UST_META_FAIL, /* UST open metadata failed */
+ LTTCOMM_UST_START_FAIL, /* UST start trace failed */
+ LTTCOMM_UST_STOP_FAIL, /* UST stop trace failed */
+ LTTCOMM_UST_CONSUMER_FAIL, /* UST consumer start failed */
+ LTTCOMM_UST_STREAM_FAIL, /* UST create stream failed */
+ LTTCOMM_UST_DIR_FAIL, /* UST trace directory creation failed */
+ LTTCOMM_UST_DIR_EXIST, /* UST trace directory exist */
+ LTTCOMM_UST_NO_SESSION, /* No UST session found */
+ LTTCOMM_UST_LIST_FAIL, /* UST listing events failed */
+
CONSUMERD_COMMAND_SOCK_READY, /* when consumerd command socket ready */
CONSUMERD_SUCCESS_RECV_FD, /* success on receiving fds */
CONSUMERD_ERROR_RECV_FD, /* error on receiving fds */
[ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_NO_SESSION) ] = "No kernel session found",
[ LTTCOMM_ERR_INDEX(LTTCOMM_KERN_LIST_FAIL) ] = "Listing kernel events failed",
[ LTTCOMM_ERR_INDEX(LTTCOMM_UST_SESS_FAIL) ] = "UST create session failed",
- [ LTTCOMM_ERR_INDEX(LTTCOMM_UST_CHAN_NOT_FOUND) ] = "UST channel not found",
[ LTTCOMM_ERR_INDEX(LTTCOMM_UST_CHAN_FAIL) ] = "UST create channel failed",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_UST_CHAN_NOT_FOUND) ] = "UST channel not found",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_UST_CHAN_DISABLE_FAIL) ] = "Disable UST channel failed",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_UST_CHAN_ENABLE_FAIL) ] = "Enable UST channel failed",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_UST_CONTEXT_FAIL) ] = "Add UST context failed",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_UST_ENABLE_FAIL) ] = "Enable UST event failed",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_UST_DISABLE_FAIL) ] = "Disable UST event failed",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_UST_META_FAIL) ] = "Opening metadata failed",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_UST_START_FAIL) ] = "Starting UST trace failed",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_UST_STOP_FAIL) ] = "Stoping UST trace failed",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_UST_CONSUMER_FAIL) ] = "UST consumer start failed",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_UST_STREAM_FAIL) ] = "UST create stream failed",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_UST_DIR_FAIL) ] = "UST trace directory creation failed",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_UST_DIR_EXIST) ] = "UST trace directory already exist",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_UST_NO_SESSION) ] = "No UST session found",
+ [ LTTCOMM_ERR_INDEX(LTTCOMM_UST_LIST_FAIL) ] = "Listing UST events failed",
[ LTTCOMM_ERR_INDEX(CONSUMERD_COMMAND_SOCK_READY) ] = "consumerd command socket ready",
[ LTTCOMM_ERR_INDEX(CONSUMERD_SUCCESS_RECV_FD) ] = "consumerd success on receiving fds",
[ LTTCOMM_ERR_INDEX(CONSUMERD_ERROR_RECV_FD) ] = "consumerd error on receiving fds",
if LTTNG_TOOLS_HAVE_UST
ltt_sessiond_SOURCES += \
trace-ust.c \
- ust-app.c \
- ust-comm.c ust-comm.h \
- ust-ctl.c
+ ust-app.c
endif
# link on liblttngctl for check if sessiond is already alive.
$(top_builddir)/liblttngctl/liblttngctl.la
if LTTNG_TOOLS_HAVE_UST
-ltt_sessiond_LDADD += -llttng-ust-comm
+ltt_sessiond_LDADD += -llttng-ust-comm -lustctl
endif
#include <lttng/lttng.h>
#include <lttng-sessiond-comm.h>
#include <lttngerr.h>
+#ifdef CONFIG_LTTNG_TOOLS_HAVE_UST
+#include <ust/lttng-ust-ctl.h>
+#include <ust/lttng-ust-abi.h>
+#else
+#include "lttng-ust-ctl.h"
+#include "lttng-ust-abi.h"
+#endif
#include "channel.h"
#include "kernel-ctl.h"
chan->attr.num_subbuf = DEFAULT_KERNEL_CHANNEL_SUBBUF_NUM;
chan->attr.output = DEFAULT_KERNEL_CHANNEL_OUTPUT;
break;
+ case LTTNG_DOMAIN_UST:
case LTTNG_DOMAIN_UST_PID:
chan->attr.subbuf_size = DEFAULT_UST_CHANNEL_SUBBUF_SIZE;
chan->attr.num_subbuf = DEFAULT_UST_CHANNEL_SUBBUF_NUM;
/* Creating channel attributes if needed */
if (attr == NULL) {
+ /* FIXME: this appears to be a memory leak */
attr = channel_new_default_attr(LTTNG_DOMAIN_KERNEL);
if (attr == NULL) {
ret = LTTCOMM_FATAL;
{
int ret;
struct lttng_channel *attr = chan;
+ struct ltt_ust_channel *suchan;
+ struct lttng_ust_channel_attr uattr;
+ struct object_data *obj;
/* Creating channel attributes if needed */
if (attr == NULL) {
- attr = channel_new_default_attr(LTTNG_DOMAIN_UST_PID);
+ /* FIXME: this appears to be a memory leak */
+ /* TODO: get default for other UST domains */
+ attr = channel_new_default_attr(LTTNG_DOMAIN_UST);
if (attr == NULL) {
ret = LTTCOMM_FATAL;
goto error;
}
}
- ret = ustctl_create_channel(sock, usession, attr);
+ suchan = trace_ust_create_channel(attr, usession->path);
+ if (suchan == NULL) {
+ ret = LTTCOMM_FATAL;
+ goto error;
+ }
+ uattr.overwrite = attr->attr.overwrite;
+ uattr.subbuf_size = attr->attr.subbuf_size;
+ uattr.num_subbuf = attr->attr.num_subbuf;
+ uattr.switch_timer_interval = attr->attr.switch_timer_interval;
+ uattr.read_timer_interval = attr->attr.read_timer_interval;
+ uattr.output = attr->attr.output;
+ ret = ustctl_create_channel(sock, usession->handle,
+ &uattr, &obj);
if (ret < 0) {
ret = LTTCOMM_UST_CHAN_FAIL;
goto error;
}
-
- DBG2("Channel %s UST create successfully for sock:%d", attr->name, sock);
+ suchan->attr.overwrite = uattr.overwrite;
+ suchan->attr.subbuf_size = uattr.subbuf_size;
+ suchan->attr.num_subbuf = uattr.num_subbuf;
+ suchan->attr.switch_timer_interval = uattr.switch_timer_interval;
+ suchan->attr.read_timer_interval = uattr.read_timer_interval;
+ suchan->attr.output = uattr.output;
+ suchan->handle = obj->handle;
+ suchan->attr.shm_fd = obj->shm_fd;
+ suchan->attr.wait_fd = obj->wait_fd;
+ suchan->attr.memory_map_size = obj->memory_map_size;
+ suchan->obj = obj;
+
+ /* Add channel to session */
+ cds_list_add(&suchan->list, &usession->channels.head);
+ usession->channels.count++;
+
+ DBG2("Channel %s UST create successfully for sock:%d", suchan->name, sock);
ret = LTTCOMM_OK;
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);
+ int ret = LTTCOMM_OK;
+ struct object_data obj;
+
+ obj.handle = uchan->handle;
+ obj.shm_fd = uchan->attr.shm_fd;
+ obj.wait_fd = uchan->attr.wait_fd;
+ obj.memory_map_size = uchan->attr.memory_map_size;
+ ret = ustctl_enable(sock, &obj);
if (ret < 0) {
ret = LTTCOMM_UST_CHAN_FAIL;
- goto error;
+ goto end;
}
-
ret = LTTCOMM_OK;
-
-error:
+end:
return ret;
}
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);
+ int ret = LTTCOMM_OK;
+ struct object_data obj;
+
+ obj.handle = uchan->handle;
+ obj.shm_fd = uchan->attr.shm_fd;
+ obj.wait_fd = uchan->attr.wait_fd;
+ obj.memory_map_size = uchan->attr.memory_map_size;
+ ret = ustctl_disable(sock, &obj);
if (ret < 0) {
ret = LTTCOMM_UST_CHAN_FAIL;
- goto error;
+ goto end;
}
-
ret = LTTCOMM_OK;
-
-error:
+end:
return ret;
}
#include <lttng-sessiond-comm.h>
#include <lttngerr.h>
+#ifdef CONFIG_LTTNG_TOOLS_HAVE_UST
+#include <ust/lttng-ust-ctl.h>
+#include <ust/lttng-ust-abi.h>
+#else
+#include "lttng-ust-ctl.h"
+#include "lttng-ust-abi.h"
+#endif
+
#include "context.h"
#include "kernel-ctl.h"
error:
return ret;
}
+
+/*
+ * UST support.
+ */
+
+/*
+ * Add UST context to an event of a specific channel.
+ */
+static int add_ustctx_to_event(struct ltt_ust_session *ustsession,
+ struct lttng_ust_context *ustctx,
+ struct ltt_ust_channel *ustchan, char *event_name)
+{
+ int ret, found = 0;
+ struct ltt_ust_event *ustevent;
+ struct object_data *context_data; /* FIXME: currently a memleak */
+
+ DBG("Add UST context to event %s", event_name);
+
+ ustevent = trace_ust_get_event_by_name(event_name, ustchan);
+ if (ustevent != NULL) {
+ ret = ustctl_add_context(ustsession->sock, ustctx,
+ ustevent->obj, &context_data);
+ if (ret < 0) {
+ goto error;
+ }
+ found = 1;
+ }
+
+ ret = found;
+
+error:
+ return ret;
+}
+
+/*
+ * Add UST context to all channel.
+ *
+ * If event_name is specified, add context to event instead.
+ */
+static int add_ustctx_all_channels(struct ltt_ust_session *ustsession,
+ struct lttng_ust_context *ustctx, char *event_name)
+{
+ int ret, no_event = 0, found = 0;
+ struct ltt_ust_channel *ustchan;
+ struct object_data *context_data; /* FIXME: currently a memleak */
+
+ if (strlen(event_name) == 0) {
+ no_event = 1;
+ }
+
+ DBG("Adding ust context to all channels (event: %s)", event_name);
+
+ /* Go over all channels */
+ cds_list_for_each_entry(ustchan, &ustsession->channels.head, list) {
+ if (no_event) {
+ ret = ustctl_add_context(ustsession->sock,
+ ustctx, ustchan->obj, &context_data);
+ if (ret < 0) {
+ ret = LTTCOMM_UST_CONTEXT_FAIL;
+ goto error;
+ }
+ } else {
+ ret = add_ustctx_to_event(ustsession, ustctx, ustchan, event_name);
+ if (ret < 0) {
+ ret = LTTCOMM_UST_CONTEXT_FAIL;
+ goto error;
+ } else if (ret == 1) {
+ /* Event found and context added */
+ found = 1;
+ break;
+ }
+ }
+ }
+
+ if (!found && !no_event) {
+ ret = LTTCOMM_NO_EVENT;
+ goto error;
+ }
+
+ ret = LTTCOMM_OK;
+
+error:
+ return ret;
+}
+
+/*
+ * Add UST context to a specific channel.
+ *
+ * If event_name is specified, add context to that event.
+ */
+static int add_ustctx_to_channel(struct ltt_ust_session *ustsession,
+ struct lttng_ust_context *ustctx,
+ struct ltt_ust_channel *ustchan, char *event_name)
+{
+ int ret, no_event = 0, found = 0;
+ struct object_data *context_data; /* FIXME: currently a memleak */
+
+ if (strlen(event_name) == 0) {
+ no_event = 1;
+ }
+
+ DBG("Add UST context to channel '%s', event '%s'",
+ ustchan->name, event_name);
+
+ if (no_event) {
+ ret = ustctl_add_context(ustsession->sock, ustctx,
+ ustchan->obj, &context_data);
+ if (ret < 0) {
+ ret = LTTCOMM_UST_CONTEXT_FAIL;
+ goto error;
+ }
+ } else {
+ ret = add_ustctx_to_event(ustsession, ustctx, ustchan, event_name);
+ if (ret < 0) {
+ ret = LTTCOMM_UST_CONTEXT_FAIL;
+ goto error;
+ } else if (ret == 1) {
+ /* Event found and context added */
+ found = 1;
+ }
+ }
+
+ if (!found && !no_event) {
+ ret = LTTCOMM_NO_EVENT;
+ goto error;
+ }
+
+ ret = LTTCOMM_OK;
+
+error:
+ return ret;
+}
+
+/*
+ * Add UST context to tracer.
+ */
+int context_ust_add(struct ltt_ust_session *ustsession,
+ struct lttng_event_context *ctx, char *event_name,
+ char *channel_name)
+{
+ int ret;
+ struct ltt_ust_channel *ustchan;
+ struct lttng_ust_context ustctx;
+
+ /* Setup UST context structure */
+ ustctx.ctx = ctx->ctx;
+
+ if (strlen(channel_name) == 0) {
+ ret = add_ustctx_all_channels(ustsession, &ustctx, event_name);
+ if (ret != LTTCOMM_OK) {
+ goto error;
+ }
+ } else {
+ /* Get UST channel */
+ ustchan = trace_ust_get_channel_by_name(channel_name, ustsession);
+ if (ustchan == NULL) {
+ ret = LTTCOMM_UST_CHAN_NOT_FOUND;
+ goto error;
+ }
+
+ ret = add_ustctx_to_channel(ustsession, &ustctx, ustchan, event_name);
+ if (ret != LTTCOMM_OK) {
+ goto error;
+ }
+ }
+
+ ret = LTTCOMM_OK;
+
+error:
+ return ret;
+}
#define _LTT_CONTEXT_H
#include <lttng/lttng.h>
+#ifdef CONFIG_LTTNG_TOOLS_HAVE_UST
+#include <ust/lttng-ust-abi.h>
+#else
+#include "lttng-ust-abi.h"
+#endif
+
#include "trace-kernel.h"
+#include "trace-ust.h"
int context_kernel_add(struct ltt_kernel_session *ksession,
struct lttng_event_context *ctx, char *event_name, char *channel_name);
+int context_ust_add(struct ltt_ust_session *ustsession,
+ struct lttng_event_context *ctx, char *event_name, char *channel_name);
#endif /* _LTT_CONTEXT_H */
#include <errno.h>
#include <urcu/list.h>
+#include <string.h>
#include <lttng/lttng.h>
#include <lttng-sessiond-comm.h>
#include <lttngerr.h>
+#ifdef CONFIG_LTTNG_TOOLS_HAVE_UST
+#include <ust/lttng-ust-ctl.h>
+#else
+#include "lttng-ust-ctl.h"
+#endif
+
#include "channel.h"
#include "event.h"
#include "kernel-ctl.h"
end:
return ret;
}
+
+/*
+ * Enable UST tracepoint event for a channel from a UST session.
+ */
+int event_ust_enable_tracepoint(struct ltt_ust_session *ustsession,
+ struct ltt_ust_channel *ustchan, struct lttng_event *event)
+{
+ int ret;
+ struct ltt_ust_event *ustevent;
+ struct lttng_ust_event lttngustevent;
+ struct object_data *object_event;
+
+ ustevent = trace_ust_get_event_by_name(event->name, ustchan);
+ if (ustevent == NULL) {
+ ustevent = trace_ust_create_event(event);
+ if (ustevent == NULL) {
+ ret = -1;
+ goto end;
+ }
+ strncpy(lttngustevent.name, event->name,
+ LTTNG_UST_SYM_NAME_LEN);
+ lttngustevent.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+ /* TODO: adjust to other instrumentation types */
+ lttngustevent.instrumentation = LTTNG_UST_TRACEPOINT;
+ ret = ustctl_create_event(ustsession->sock, <tngustevent,
+ ustchan->obj, &object_event);
+ if (ret < 0) {
+ if (ret == -EEXIST) {
+ ret = LTTCOMM_KERN_EVENT_EXIST;
+ } else {
+ ret = LTTCOMM_KERN_ENABLE_FAIL;
+ }
+ goto end;
+ }
+ ustevent->obj = object_event;
+ ustevent->handle = object_event->handle;
+ ustevent->enabled = 1;
+ /* Add event to event list */
+ cds_list_add(&ustevent->list, &ustchan->events.head);
+ ustchan->events.count++;
+ } else if (ustevent->enabled == 0) {
+ ret = ustctl_enable(ustsession->sock, ustevent->obj);
+ if (ret < 0) {
+ ret = LTTCOMM_KERN_ENABLE_FAIL;
+ goto end;
+ }
+ ustevent->enabled = 1;
+ }
+ ret = LTTCOMM_OK;
+end:
+ return ret;
+}
+
+int event_ust_disable_tracepoint(struct ltt_ust_session *ustsession,
+ struct ltt_ust_channel *ustchan, char *event_name)
+{
+ int ret;
+ struct ltt_ust_event *ustevent;
+
+ ustevent = trace_ust_get_event_by_name(event_name, ustchan);
+ if (ustevent == NULL) {
+ ret = LTTCOMM_NO_EVENT;
+ goto end;
+ }
+ ret = ustctl_disable(ustsession->sock, ustevent->obj);
+ if (ret < 0) {
+ ret = LTTCOMM_UST_ENABLE_FAIL;
+ goto end;
+ }
+ ustevent->enabled = 0;
+ ret = LTTCOMM_OK;
+end:
+ return ret;
+}
int event_kernel_enable_all(struct ltt_kernel_session *ksession,
struct ltt_kernel_channel *kchan, int kernel_tracer_fd);
+int event_ust_enable_tracepoint(struct ltt_ust_session *ustsession,
+ struct ltt_ust_channel *ustchan, struct lttng_event *event);
+int event_ust_disable_tracepoint(struct ltt_ust_session *ustsession,
+ struct ltt_ust_channel *ustchan, char *event_name);
+
#endif /* _LTT_EVENT_H */
/* Event and Channel FD commands */
#define LTTNG_UST_CONTEXT \
_UST_CMDW(0x70, struct lttng_ust_context)
+#define LTTNG_UST_FLUSH_BUFFER \
+ _UST_CMD(0x71)
/* Event, Channel and Session commands */
#define LTTNG_UST_ENABLE _UST_CMD(0x80)
--- /dev/null
+/*
+ * Copyright (C) 2011 - Julien Desfossez <julien.desfossez@polymtl.ca>
+ * Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; only version 2
+ * of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _LTTNG_UST_CTL_H
+#define _LTTNG_UST_CTL_H
+
+/*
+ * ust-ctl stub API when UST is not present.
+*/
+
+#include "lttng-ust-abi.h"
+#include <errno.h>
+
+/*
+ * Tracer channel attributes.
+ */
+struct lttng_ust_channel_attr {
+ int overwrite; /* 1: overwrite, 0: discard */
+ uint64_t subbuf_size; /* bytes */
+ uint64_t num_subbuf; /* power of 2 */
+ unsigned int switch_timer_interval; /* usec */
+ unsigned int read_timer_interval; /* usec */
+ enum lttng_ust_output output; /* splice, mmap */
+};
+
+struct object_data {
+ int handle;
+ int shm_fd;
+ int wait_fd;
+ uint64_t memory_map_size;
+};
+
+static inline
+int ustctl_register_done(int sock)
+{
+ return -ENOSYS;
+}
+static inline
+int ustctl_create_session(int sock)
+{
+ return -ENOSYS;
+}
+static inline
+int ustctl_open_metadata(int sock, int session_handle,
+ struct lttng_ust_channel_attr *chops,
+ struct object_data **metadata_data)
+{
+ return -ENOSYS;
+}
+static inline
+int ustctl_create_channel(int sock, int session_handle,
+ struct lttng_ust_channel_attr *chops,
+ struct object_data **channel_data)
+{
+ return -ENOSYS;
+}
+static inline
+int ustctl_create_stream(int sock, struct object_data *channel_data,
+ struct object_data **stream_data)
+{
+ return -ENOSYS;
+}
+static inline
+int ustctl_create_event(int sock, struct lttng_ust_event *ev,
+ struct object_data *channel_data,
+ struct object_data **event_data)
+{
+ return -ENOSYS;
+}
+static inline
+int ustctl_add_context(int sock, struct lttng_ust_context *ctx,
+ struct object_data *obj_data,
+ struct object_data **context_data)
+{
+ return -ENOSYS;
+}
+
+static inline
+int ustctl_enable(int sock, struct object_data *object)
+{
+ return -ENOSYS;
+}
+static inline
+int ustctl_disable(int sock, struct object_data *object)
+{
+ return -ENOSYS;
+}
+static inline
+int ustctl_start_session(int sock, int handle)
+{
+ return -ENOSYS;
+}
+static inline
+int ustctl_stop_session(int sock, int handle)
+{
+ return -ENOSYS;
+}
+
+static inline
+int ustctl_tracepoint_list(int sock) /* not implemented yet */
+{
+ return -ENOSYS;
+}
+static inline
+int ustctl_tracer_version(int sock, struct lttng_ust_tracer_version *v)
+{
+ return -ENOSYS;
+}
+static inline
+int ustctl_wait_quiescent(int sock)
+{
+ return -ENOSYS;
+}
+
+/* Flush each buffers in this channel */
+static inline
+int ustctl_flush_buffer(int sock, struct object_data *channel_data)
+{
+ return -ENOSYS;
+}
+
+/* not implemented yet */
+struct lttng_ust_calibrate;
+static inline
+int ustctl_calibrate(int sock, struct lttng_ust_calibrate *calibrate)
+{
+ return -ENOSYS;
+}
+
+/*
+ * Map channel shm_handle and add streams. Typically performed by the
+ * consumer to map the objects into its memory space.
+ */
+static inline
+struct shm_handle *ustctl_map_channel(struct object_data *chan_data)
+{
+ return NULL;
+}
+static inline
+int ustctl_add_stream(struct shm_handle *shm_handle,
+ struct object_data *stream_data)
+{
+ return -ENOSYS;
+}
+/*
+ * Note: the object_data from which the shm_handle is derived can only
+ * be released after unmapping the handle.
+ */
+static inline
+void ustctl_unmap_channel(struct shm_handle *shm_handle)
+{
+}
+
+/* Buffer operations */
+
+struct shm_handle;
+struct lib_ring_buffer;
+
+/* Open/close stream buffers for read */
+static inline
+struct lib_ring_buffer *ustctl_open_stream_read(struct shm_handle *handle,
+ int cpu)
+{
+ return NULL;
+}
+static inline
+void ustctl_close_stream_read(struct shm_handle *handle,
+ struct lib_ring_buffer *buf)
+{
+}
+
+/* For mmap mode, readable without "get" operation */
+static inline
+int ustctl_get_mmap_len(struct shm_handle *handle,
+ struct lib_ring_buffer *buf,
+ unsigned long *len)
+{
+ return -ENOSYS;
+}
+static inline
+int ustctl_get_max_subbuf_size(struct shm_handle *handle,
+ struct lib_ring_buffer *buf,
+ unsigned long *len)
+{
+ return -ENOSYS;
+}
+
+/*
+ * For mmap mode, operate on the current packet (between get/put or
+ * get_next/put_next).
+ */
+static inline
+void *ustctl_get_mmap_base(struct shm_handle *handle,
+ struct lib_ring_buffer *buf)
+{
+ return NULL;
+}
+static inline
+int ustctl_get_mmap_read_offset(struct shm_handle *handle,
+ struct lib_ring_buffer *buf, unsigned long *off)
+{
+ return -ENOSYS;
+}
+static inline
+int ustctl_get_subbuf_size(struct shm_handle *handle,
+ struct lib_ring_buffer *buf, unsigned long *len)
+{
+ return -ENOSYS;
+}
+static inline
+int ustctl_get_padded_subbuf_size(struct shm_handle *handle,
+ struct lib_ring_buffer *buf, unsigned long *len)
+{
+ return -ENOSYS;
+}
+static inline
+int ustctl_get_next_subbuf(struct shm_handle *handle,
+ struct lib_ring_buffer *buf)
+{
+ return -ENOSYS;
+}
+static inline
+int ustctl_put_next_subbuf(struct shm_handle *handle,
+ struct lib_ring_buffer *buf)
+{
+ return -ENOSYS;
+}
+
+/* snapshot */
+
+static inline
+int ustctl_snapshot(struct shm_handle *handle,
+ struct lib_ring_buffer *buf)
+{
+ return -ENOSYS;
+}
+static inline
+int ustctl_snapshot_get_consumed(struct shm_handle *handle,
+ struct lib_ring_buffer *buf, unsigned long *pos)
+{
+ return -ENOSYS;
+}
+static inline
+int ustctl_snapshot_get_produced(struct shm_handle *handle,
+ struct lib_ring_buffer *buf, unsigned long *pos)
+{
+ return -ENOSYS;
+}
+static inline
+int ustctl_get_subbuf(struct shm_handle *handle,
+ struct lib_ring_buffer *buf, unsigned long *pos)
+{
+ return -ENOSYS;
+}
+static inline
+int ustctl_put_subbuf(struct shm_handle *handle,
+ struct lib_ring_buffer *buf)
+{
+ return -ENOSYS;
+}
+
+/* Release object created by members of this API */
+static inline
+void release_object(int sock, struct object_data *data)
+{
+}
+
+#endif /* _LTTNG_UST_CTL_H */
#include <lttng-consumerd.h>
#include <lttng-sessiond-comm.h>
#include <lttng/lttng-consumer.h>
+
+#ifdef CONFIG_LTTNG_TOOLS_HAVE_UST
+#include <ust/lttng-ust-ctl.h>
+#else
+#include "lttng-ust-ctl.h"
+#endif
+
+
#include <lttngerr.h>
#include "channel.h"
/*
* Send all stream fds of kernel channel to the consumer.
*/
-static int send_consumer_channel_streams(struct consumer_data *consumer_data,
+static int send_kconsumer_channel_streams(struct consumer_data *consumer_data,
int sock, struct ltt_kernel_channel *channel)
{
int ret;
lkm.u.channel.channel_key = channel->fd;
lkm.u.channel.max_sb_size = channel->channel->attr.subbuf_size;
lkm.u.channel.mmap_len = 0; /* for kernel */
- DBG("Sending channel %d to consumer", lkm.u.stream.stream_key);
+ DBG("Sending channel %d to consumer", lkm.u.channel.channel_key);
ret = lttcomm_send_unix_sock(sock, &lkm, sizeof(lkm));
if (ret < 0) {
perror("send consumer channel");
return ret;
}
+/*
+ * Send all stream fds of UST channel to the consumer.
+ */
+static int send_ustconsumer_channel_streams(struct consumer_data *consumer_data,
+ int sock, struct ltt_ust_channel *channel)
+{
+ int ret, fds[2];
+ struct ltt_ust_stream *stream;
+ struct lttcomm_consumer_msg lum;
+
+ DBG("Sending streams of channel %s to UST consumer",
+ channel->name);
+
+ /* Send channel */
+ lum.cmd_type = LTTNG_CONSUMER_ADD_CHANNEL;
+ /*
+ * We need to keep shm_fd open to make sure this key stays
+ * unique within the session daemon.
+ */
+ lum.u.channel.channel_key = channel->obj->shm_fd;
+ lum.u.channel.max_sb_size = channel->attr.subbuf_size;
+ lum.u.channel.mmap_len = channel->obj->memory_map_size;
+ DBG("Sending channel %d to consumer", lum.u.channel.channel_key);
+ ret = lttcomm_send_unix_sock(sock, &lum, sizeof(lum));
+ if (ret < 0) {
+ perror("send consumer channel");
+ goto error;
+ }
+ fds[0] = channel->obj->shm_fd;
+ fds[1] = channel->obj->wait_fd;
+ ret = lttcomm_send_fds_unix_sock(sock, fds, 2);
+ if (ret < 0) {
+ perror("send consumer channel ancillary data");
+ goto error;
+ }
+
+ /* Send streams */
+ cds_list_for_each_entry(stream, &channel->stream_list.head, list) {
+ int fds[2];
+
+ if (!stream->obj->shm_fd) {
+ continue;
+ }
+ lum.cmd_type = LTTNG_CONSUMER_ADD_STREAM;
+ lum.u.stream.channel_key = channel->obj->shm_fd;
+ lum.u.stream.stream_key = stream->obj->shm_fd;
+ lum.u.stream.state = LTTNG_CONSUMER_ACTIVE_STREAM;
+ lum.u.stream.output = channel->attr.output;
+ lum.u.stream.mmap_len = stream->obj->memory_map_size;
+ strncpy(lum.u.stream.path_name, stream->pathname, PATH_MAX - 1);
+ lum.u.stream.path_name[PATH_MAX - 1] = '\0';
+ DBG("Sending stream %d to consumer", lum.u.stream.stream_key);
+ ret = lttcomm_send_unix_sock(sock, &lum, sizeof(lum));
+ if (ret < 0) {
+ perror("send consumer stream");
+ goto error;
+ }
+ fds[0] = stream->obj->shm_fd;
+ fds[1] = stream->obj->wait_fd;
+ ret = lttcomm_send_fds_unix_sock(sock, fds, 2);
+ if (ret < 0) {
+ perror("send consumer stream ancillary data");
+ goto error;
+ }
+ }
+
+ DBG("consumer channel streams sent");
+
+ return 0;
+
+error:
+ return ret;
+}
+
/*
* Send all stream fds of the kernel session to the consumer.
*/
-static int send_consumer_session_streams(struct consumer_data *consumer_data,
+static int send_kconsumer_session_streams(struct consumer_data *consumer_data,
struct ltt_kernel_session *session)
{
int ret;
DBG("Sending metadata stream fd");
- /* Extra protection. It's NOT suppose to be set to 0 at this point */
+ /* Extra protection. It's NOT supposed to be set to 0 at this point */
if (session->consumer_fd == 0) {
session->consumer_fd = consumer_data->cmd_sock;
}
}
cds_list_for_each_entry(chan, &session->channel_list.head, list) {
- ret = send_consumer_channel_streams(consumer_data, sock, chan);
+ ret = send_kconsumer_channel_streams(consumer_data, sock, chan);
+ if (ret < 0) {
+ goto error;
+ }
+ }
+
+ DBG("consumer fds (metadata and channel streams) sent");
+
+ return 0;
+
+error:
+ return ret;
+}
+
+/*
+ * Send all stream fds of the UST session to the consumer.
+ */
+static int send_ustconsumer_session_streams(struct consumer_data *consumer_data,
+ struct ltt_ust_session *session)
+{
+ int ret;
+ struct ltt_ust_channel *chan;
+ struct lttcomm_consumer_msg lum;
+ int sock = session->consumer_fd;
+
+ DBG("Sending metadata stream fd");
+
+ /* Extra protection. It's NOT supposed to be set to 0 at this point */
+ if (session->consumer_fd == 0) {
+ session->consumer_fd = consumer_data->cmd_sock;
+ }
+
+ if (session->metadata->obj->shm_fd != 0) {
+ int fds[2];
+
+ /* Send metadata channel fd */
+ lum.cmd_type = LTTNG_CONSUMER_ADD_CHANNEL;
+ lum.u.channel.channel_key = session->metadata->obj->shm_fd;
+ lum.u.channel.max_sb_size = session->metadata->attr.subbuf_size;
+ lum.u.channel.mmap_len = 0; /* for kernel */
+ DBG("Sending metadata channel %d to consumer", lum.u.stream.stream_key);
+ ret = lttcomm_send_unix_sock(sock, &lum, sizeof(lum));
+ if (ret < 0) {
+ perror("send consumer channel");
+ goto error;
+ }
+ fds[0] = session->metadata->obj->shm_fd;
+ fds[1] = session->metadata->obj->wait_fd;
+ ret = lttcomm_send_fds_unix_sock(sock, fds, 2);
+ if (ret < 0) {
+ perror("send consumer metadata channel");
+ goto error;
+ }
+
+ /* Send metadata stream fd */
+ lum.cmd_type = LTTNG_CONSUMER_ADD_STREAM;
+ lum.u.stream.channel_key = session->metadata->obj->shm_fd;
+ lum.u.stream.stream_key = session->metadata->stream_obj->shm_fd;
+ lum.u.stream.state = LTTNG_CONSUMER_ACTIVE_STREAM;
+ lum.u.stream.output = DEFAULT_UST_CHANNEL_OUTPUT;
+ lum.u.stream.mmap_len = session->metadata->stream_obj->memory_map_size;
+ strncpy(lum.u.stream.path_name, session->metadata->pathname, PATH_MAX - 1);
+ lum.u.stream.path_name[PATH_MAX - 1] = '\0';
+ DBG("Sending metadata stream %d to consumer", lum.u.stream.stream_key);
+ ret = lttcomm_send_unix_sock(sock, &lum, sizeof(lum));
+ if (ret < 0) {
+ perror("send consumer metadata stream");
+ goto error;
+ }
+ fds[0] = session->metadata->stream_obj->shm_fd;
+ fds[1] = session->metadata->stream_obj->wait_fd;
+ ret = lttcomm_send_fds_unix_sock(sock, fds, 2);
+ if (ret < 0) {
+ perror("send consumer stream");
+ goto error;
+ }
+ }
+
+ cds_list_for_each_entry(chan, &session->channels.head, list) {
+ ret = send_ustconsumer_channel_streams(consumer_data, sock, chan);
if (ret < 0) {
goto error;
}
*
* Useful for CPU hotplug feature.
*/
-static int update_stream(struct consumer_data *consumer_data, int fd)
+static int update_kernel_stream(struct consumer_data *consumer_data, int fd)
{
int ret = 0;
struct ltt_session *session;
* stream fds.
*/
if (session->kernel_session->consumer_fds_sent == 1) {
- ret = send_consumer_channel_streams(consumer_data,
+ ret = send_kconsumer_channel_streams(consumer_data,
session->kernel_session->consumer_fd, channel);
if (ret < 0) {
goto error;
* kernel session and updating the kernel consumer
*/
if (revents & LPOLLIN) {
- ret = update_stream(&kconsumer_data, pollfd);
+ ret = update_kernel_stream(&kconsumer_data, pollfd);
if (ret < 0) {
continue;
}
session->consumer_fd = kconsumer_data.cmd_sock;
}
- ret = send_consumer_session_streams(&kconsumer_data, session);
+ ret = send_kconsumer_session_streams(&kconsumer_data, session);
if (ret < 0) {
ret = LTTCOMM_KERN_CONSUMER_FAIL;
goto error;
return ret;
}
+/*
+ * Init tracing by creating trace directory and sending fds ust consumer.
+ */
+static int init_ust_tracing(struct ltt_ust_session *session)
+{
+ int ret = 0;
+
+ if (session->consumer_fds_sent == 0) {
+ /*
+ * Assign default ust consumer socket if no consumer assigned to the
+ * ust session. At this point, it's NOT suppose to be 0 but this is
+ * an extra security check.
+ */
+ if (session->consumer_fd == 0) {
+ session->consumer_fd = ustconsumer_data.cmd_sock;
+ }
+
+ ret = send_ustconsumer_session_streams(&ustconsumer_data, session);
+ if (ret < 0) {
+ ret = LTTCOMM_UST_CONSUMER_FAIL;
+ goto error;
+ }
+
+ session->consumer_fds_sent = 1;
+ }
+
+error:
+ return ret;
+}
+
/*
* Create an UST session and add it to the session ust list.
*/
}
/* Create session on the UST tracer */
- ret = ustctl_create_session(app->sock, lus);
+ ret = ustctl_create_session(app->sock);
if (ret < 0) {
ret = LTTCOMM_UST_SESS_FAIL;
goto error;
}
+ lus->handle = ret;
+ lus->sock = app->sock;
cds_list_add(&lus->list, &session->ust_session_list.head);
session->ust_session_list.count++;
char *channel_name, char *event_name)
{
int ret;
- struct ltt_kernel_channel *kchan;
switch (domain) {
case LTTNG_DOMAIN_KERNEL:
+ {
+ struct ltt_kernel_channel *kchan;
+
kchan = trace_kernel_get_channel_by_name(channel_name,
session->kernel_session);
if (kchan == NULL) {
kernel_wait_quiescent(kernel_tracer_fd);
break;
+ }
+ case LTTNG_DOMAIN_UST:
+ {
+ struct ltt_ust_session *ustsession;
+
+ cds_list_for_each_entry(ustsession, &session->ust_session_list.head, list) {
+ struct ltt_ust_channel *ustchan;
+
+ ustchan = trace_ust_get_channel_by_name(channel_name,
+ ustsession);
+ if (ustchan == NULL) {
+ ret = LTTCOMM_KERN_CHAN_NOT_FOUND;
+ goto error;
+ }
+ ret = event_ust_disable_tracepoint(ustsession, ustchan, event_name);
+ if (ret != LTTCOMM_OK) {
+ goto error;
+ }
+
+ ustctl_wait_quiescent(ustsession->sock);
+ }
+ break;
+ }
+ case LTTNG_DOMAIN_UST_EXEC_NAME:
+ case LTTNG_DOMAIN_UST_PID:
+ case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
default:
- /* TODO: Userspace tracing */
+ /* TODO: Other UST domains */
ret = LTTCOMM_NOT_IMPLEMENTED;
goto error;
}
if (ret != LTTCOMM_OK) {
goto error;
}
+ break;
+ case LTTNG_DOMAIN_UST:
+ {
+ struct ltt_ust_session *ustsession;
+ cds_list_for_each_entry(ustsession, &session->ust_session_list.head, list) {
+ /* Add UST context to UST tracer */
+ ret = context_ust_add(ustsession, ctx,
+ event_name, channel_name);
+ if (ret != LTTCOMM_OK) {
+ goto error;
+ }
+ }
break;
+ }
default:
- /* TODO: Userspace tracing */
+ /* TODO: UST other domains */
ret = LTTCOMM_NOT_IMPLEMENTED;
goto error;
}
char *channel_name, struct lttng_event *event)
{
int ret;
- struct ltt_kernel_channel *kchan;
struct lttng_channel *attr;
switch (domain) {
case LTTNG_DOMAIN_KERNEL:
+ {
+ struct ltt_kernel_channel *kchan;
+
kchan = trace_kernel_get_channel_by_name(channel_name,
session->kernel_session);
if (kchan == NULL) {
kernel_wait_quiescent(kernel_tracer_fd);
break;
+ }
+ case LTTNG_DOMAIN_UST:
+ {
+ struct ltt_ust_session *ustsession;
+
+ cds_list_for_each_entry(ustsession, &session->ust_session_list.head, list) {
+ struct ltt_ust_channel *ustchan;
+
+ ustchan = trace_ust_get_channel_by_name(channel_name,
+ ustsession);
+ if (ustchan == NULL) {
+ attr = channel_new_default_attr(domain);
+ if (attr == NULL) {
+ ret = LTTCOMM_FATAL;
+ goto error;
+ }
+ snprintf(attr->name, NAME_MAX, "%s", channel_name);
+
+ ret = channel_ust_create(ustsession,
+ attr, ustsession->sock);
+ if (ret != LTTCOMM_OK) {
+ goto error;
+ }
+ }
+
+ /* Get the newly created ust channel pointer */
+ ustchan = trace_ust_get_channel_by_name(channel_name,
+ ustsession);
+ if (ustchan == NULL) {
+ /* This sould not happen... */
+ ret = LTTCOMM_FATAL;
+ goto error;
+ }
+
+ ret = event_ust_enable_tracepoint(ustsession, ustchan, event);
+ if (ret != LTTCOMM_OK) {
+ goto error;
+ }
+
+ ustctl_wait_quiescent(ustsession->sock);
+ }
+ break;
+ }
+ case LTTNG_DOMAIN_UST_EXEC_NAME:
+ case LTTNG_DOMAIN_UST_PID:
+ case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
default:
- /* TODO: Userspace tracing */
+ /* TODO: UST other domains */
ret = LTTCOMM_NOT_IMPLEMENTED;
goto error;
}
static int cmd_start_trace(struct ltt_session *session)
{
int ret;
- struct ltt_kernel_channel *kchan;
struct ltt_kernel_session *ksession;
+ struct ltt_ust_session *ustsession;
/* Short cut */
ksession = session->kernel_session;
/* Kernel tracing */
if (ksession != NULL) {
+ struct ltt_kernel_channel *kchan;
+
/* Open kernel metadata */
if (ksession->metadata == NULL) {
ret = kernel_open_metadata(ksession, ksession->trace_path);
kernel_wait_quiescent(kernel_tracer_fd);
}
- /* TODO: Start all UST traces */
+ /* Start all UST traces */
+ cds_list_for_each_entry(ustsession, &session->ust_session_list.head, list) {
+ struct ltt_ust_channel *ustchan;
+
+ /* Open kernel metadata */
+ if (ustsession->metadata == NULL) {
+ struct lttng_ust_channel_attr ustattr;
+
+ /* Allocate UST metadata */
+ ustsession->metadata = trace_ust_create_metadata(ustsession->path);
+ if (ustsession->metadata == NULL) {
+ ret = LTTCOMM_UST_META_FAIL;
+ goto error;
+ }
+
+ ustattr.overwrite = ustsession->metadata->attr.overwrite;
+ ustattr.subbuf_size = ustsession->metadata->attr.subbuf_size;
+ ustattr.num_subbuf = ustsession->metadata->attr.num_subbuf;
+ ustattr.switch_timer_interval = ustsession->metadata->attr.switch_timer_interval;
+ ustattr.read_timer_interval = ustsession->metadata->attr.read_timer_interval;
+ ustattr.output = ustsession->metadata->attr.output;
+
+ /* UST tracer metadata creation */
+ ret = ustctl_open_metadata(ustsession->sock,
+ ustsession->handle, &ustattr,
+ &ustsession->metadata->obj);
+ if (ret < 0) {
+ ret = LTTCOMM_UST_META_FAIL;
+ goto error;
+ }
+ }
+
+ /* Open UST metadata stream */
+ if (ustsession->metadata->stream_obj == NULL) {
+ ret = ustctl_create_stream(ustsession->sock,
+ ustsession->metadata->obj,
+ &ustsession->metadata->stream_obj);
+ if (ret < 0) {
+ ERR("UST create metadata stream failed");
+ ret = LTTCOMM_UST_STREAM_FAIL;
+ goto error;
+ }
+ ret = asprintf(&ustsession->metadata->pathname, "%s/%s",
+ ustsession->path, "metadata");
+ if (ret < 0) {
+ perror("asprintf UST create stream");
+ goto error;
+ }
+ }
+
+ /* For each channel */
+ cds_list_for_each_entry(ustchan, &ustsession->channels.head, list) {
+ if (ustchan->stream_count == 0) {
+ struct ltt_ust_stream *ustream;
+
+ ustream = zmalloc(sizeof(*ustream));
+ if (!ustream) {
+ ret = LTTCOMM_UST_STREAM_FAIL;
+ goto error;
+ }
+ ret = ustctl_create_stream(ustsession->sock,
+ ustchan->obj, &ustream->obj);
+ if (ret < 0) {
+ ret = LTTCOMM_UST_STREAM_FAIL;
+ goto error;
+ }
+ ret = asprintf(&ustream->pathname, "%s/%s_%d",
+ ustchan->trace_path, ustchan->name,
+ ustchan->stream_count);
+ if (ret < 0) {
+ perror("asprintf UST create stream");
+ goto error;
+ }
+ cds_list_add(&ustream->list, &ustchan->stream_list.head);
+ ustchan->stream_count++;
+ }
+ }
+
+ /* Setup UST consumer socket and send fds to it */
+ ret = init_ust_tracing(ustsession);
+ if (ret < 0) {
+ ret = LTTCOMM_UST_START_FAIL;
+ goto error;
+ }
+
+ /* This start the UST tracing */
+ ret = ustctl_start_session(ustsession->sock, ustsession->handle);
+ if (ret < 0) {
+ ret = LTTCOMM_UST_START_FAIL;
+ goto error;
+ }
+
+ /* Quiescent wait after starting trace */
+ ustctl_wait_quiescent(ustsession->sock);
+ }
ret = LTTCOMM_OK;
int ret;
struct ltt_kernel_channel *kchan;
struct ltt_kernel_session *ksession;
+ struct ltt_ust_session *ustsession;
+ struct ltt_ust_channel *ustchan;
/* Short cut */
ksession = session->kernel_session;
kernel_wait_quiescent(kernel_tracer_fd);
}
- /* TODO : User-space tracer */
+ /* Stop each UST session */
+ DBG("Stop UST tracing");
+ cds_list_for_each_entry(ustsession, &session->ust_session_list.head, list) {
+ /* Flush all buffers before stopping */
+ ret = ustctl_flush_buffer(ustsession->sock, ustsession->metadata->obj);
+ if (ret < 0) {
+ ERR("UST metadata flush failed");
+ }
+
+ cds_list_for_each_entry(ustchan, &ustsession->channels.head, list) {
+ ret = ustctl_flush_buffer(ustsession->sock, ustchan->obj);
+ if (ret < 0) {
+ ERR("UST flush buffer error");
+ }
+ }
+
+ ret = ustctl_stop_session(ustsession->sock, ustsession->handle);
+ if (ret < 0) {
+ ret = LTTCOMM_KERN_STOP_FAIL;
+ goto error;
+ }
+
+ ustctl_wait_quiescent(ustsession->sock);
+ }
ret = LTTCOMM_OK;
list_lttng_channels(session, *channels);
+ /* TODO UST support */
+
return nb_chan;
error:
pthread_mutex_unlock(&kconsumer_data.pid_mutex);
}
break;
+ case LTTNG_DOMAIN_UST:
+ case LTTNG_DOMAIN_UST_EXEC_NAME:
case LTTNG_DOMAIN_UST_PID:
+ case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
{
struct ltt_ust_session *usess;
goto error;
}
}
+ /* Start the kernel consumer daemon */
+ pthread_mutex_lock(&ustconsumer_data.pid_mutex);
+ if (ustconsumer_data.pid == 0 &&
+ cmd_ctx->lsm->cmd_type != LTTNG_REGISTER_CONSUMER) {
+ pthread_mutex_unlock(&ustconsumer_data.pid_mutex);
+ ret = start_consumerd(&ustconsumer_data);
+ if (ret < 0) {
+ ret = LTTCOMM_KERN_CONSUMER_FAIL;
+ goto error;
+ }
+ }
+ pthread_mutex_unlock(&ustconsumer_data.pid_mutex);
}
break;
}
default:
- /* TODO Userspace tracer */
break;
}
}
case LTTNG_DISABLE_ALL_EVENT:
{
- DBG("Disabling all kernel event");
+ DBG("Disabling all events");
ret = cmd_disable_event_all(cmd_ctx->session, cmd_ctx->lsm->domain.type,
cmd_ctx->lsm->u.disable.channel_name);
}
case LTTNG_ENABLE_ALL_EVENT:
{
- DBG("Enabling all kernel event");
+ DBG("Enabling all events");
ret = cmd_enable_event_all(cmd_ctx->session, cmd_ctx->lsm->domain.type,
cmd_ctx->lsm->u.enable.channel_name,
struct ltt_kernel_event {
int fd;
int enabled;
+ /*
+ * TODO: need internal representation to support more than a
+ * single context.
+ */
struct lttng_kernel_context *ctx;
struct lttng_kernel_event *event;
struct cds_list_head list;
char *pathname;
unsigned int stream_count;
unsigned int event_count;
+ /*
+ * TODO: need internal representation to support more than a
+ * single context.
+ */
struct lttng_kernel_context *ctx;
struct lttng_channel *channel;
struct ltt_kernel_event_list events_list;
perror("asprintf ust create channel");
goto error;
}
+ CDS_INIT_LIST_HEAD(&luc->stream_list.head);
return luc;
lum->handle = -1;
/* Set metadata trace path */
- ret = asprintf(&lum->trace_path, "%s/metadata", path);
+ ret = asprintf(&lum->pathname, "%s/metadata", path);
if (ret < 0) {
perror("asprintf ust metadata");
goto error;
DBG("[trace] Destroy ust metadata %d", metadata->handle);
/* Free attributes */
- free(metadata->trace_path);
-
+ free(metadata->pathname);
free(metadata);
}
struct cds_list_head head;
};
+/* UST Stream list */
+struct ltt_ust_stream_list {
+ unsigned int count;
+ struct cds_list_head head;
+};
+
/* UST Channel list */
struct ltt_ust_channel_list {
unsigned int count;
struct ltt_ust_event {
int handle;
int enabled;
+ /*
+ * TODO: need internal representation to support more than a
+ * single context.
+ */
struct lttng_ust_context ctx;
struct lttng_ust_event attr;
struct cds_list_head list;
+ struct object_data *obj;
+};
+
+/* UST stream */
+struct ltt_ust_stream {
+ struct object_data *obj;
+ struct cds_list_head list;
+ char *pathname;
};
/* UST channel */
int enabled;
char name[LTTNG_UST_SYM_NAME_LEN];
char trace_path[PATH_MAX]; /* Trace file path name */
+ /*
+ * TODO: need internal representation to support more than a
+ * single context.
+ */
struct lttng_ust_context ctx;
struct lttng_ust_channel attr;
struct ltt_ust_event_list events;
struct cds_list_head list;
+ struct object_data *obj;
+ unsigned int stream_count;
+ struct ltt_ust_stream_list stream_list;
};
/* UST Metadata */
struct ltt_ust_metadata {
int handle;
- char *trace_path; /* Trace file path name */
+ struct object_data *obj;
+ char *pathname; /* Trace file path name */
struct lttng_ust_channel attr;
+ struct object_data *stream_obj;
};
/* UST session */
struct ltt_ust_session {
+ int sock; /* socket to send cmds to app */
int handle;
int enabled;
int consumer_fds_sent;
+ int consumer_fd;
char path[PATH_MAX];
struct lttng_domain domain;
struct ltt_ust_metadata *metadata;
struct ltt_ust_channel_list channels;
struct cds_list_head list;
+ struct object_data *obj;
};
#ifdef CONFIG_LTTNG_TOOLS_HAVE_UST
+++ /dev/null
-/*
- * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; only version 2
- * of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <config.h>
-#include <stdlib.h>
-#include <lttngerr.h>
-#include <ust/lttng-ust-comm.h>
-#include "ust-comm.h"
-
-/*
- * Send msg containing a command to an UST application via sock and wait for
- * the reply. Caller must free() the reply structure sent back.
- *
- * Return the replied structure or NULL.
- */
-struct lttcomm_ust_reply *ustcomm_send_command(int sock,
- struct lttcomm_ust_msg *msg)
-{
- ssize_t len;
- struct lttcomm_ust_reply *reply;
-
- /* Extra safety */
- if (msg == NULL || sock < 0) {
- goto error;
- }
-
- DBG2("Sending UST command %d to sock %d", msg->cmd, sock);
-
- /* Send UST msg */
- len = ustcomm_send_unix_sock(sock, msg, sizeof(*msg));
- if (len < 0) {
- goto error;
- }
-
- reply = malloc(sizeof(struct lttcomm_ust_reply));
- if (reply == NULL) {
- perror("malloc ust reply");
- goto error;
- }
-
- DBG2("Receiving UST reply on sock %d", sock);
-
- /* Get UST reply */
- len = ustcomm_recv_unix_sock(sock, reply, sizeof(*reply));
- if (len < 0 || len < sizeof(*reply)) {
- goto error;
- }
-
- return reply;
-
-error:
- return NULL;
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; only version 2 of the License.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef _LTT_UST_COMM_H
-#define _LTT_UST_COMM_H
-
-#include <lttng-sessiond-comm.h>
-
-struct lttcomm_ust_reply *ustcomm_send_command(int sock,
- struct lttcomm_ust_msg *msg);
-
-#endif /* _LTT_UST_COMM_H */
+++ /dev/null
-/*
- * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; only version 2
- * of the License.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#define _GNU_SOURCE
-#include <config.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <ust/lttng-ust-comm.h>
-#include <lttngerr.h>
-
-#include "ust-comm.h"
-#include "ust-ctl.h"
-
-/*
- * Send registration done packet to the application.
- */
-int ustctl_register_done(int sock)
-{
- struct lttcomm_ust_msg command;
- struct lttcomm_ust_reply *reply;
-
- DBG("Sending register done command to %d", sock);
-
- command.cmd = LTTNG_UST_REGISTER_DONE;
- command.handle = LTTNG_UST_ROOT_HANDLE;
-
- reply = ustcomm_send_command(sock, &command);
- if (reply == NULL) {
- goto error;
- }
-
- if (reply->ret_code != USTCOMM_OK) {
- DBG("Return code: %s", ustcomm_get_readable_code(reply->ret_code));
- goto error;
- }
-
- return 0;
-
-error:
- return -1;
-}
-
-/*
- * Create an UST session on the tracer.
- */
-int ustctl_create_session(int sock, struct ltt_ust_session *session)
-{
- struct lttcomm_ust_msg command;
- struct lttcomm_ust_reply *reply = NULL;
-
- command.cmd = LTTNG_UST_SESSION;
- command.handle = LTTNG_UST_ROOT_HANDLE;
-
- reply = ustcomm_send_command(sock, &command);
- if (reply == NULL) {
- goto error;
- }
-
- if (reply->ret_code != USTCOMM_OK) {
- DBG("Return code: %s", ustcomm_get_readable_code(reply->ret_code));
- goto error;
- }
-
- /* Save session 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 != USTCOMM_OK) {
- DBG("Return code (%d): %s", reply->ret_code,
- ustcomm_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 != USTCOMM_OK) {
- DBG("Return code (%d): %s", reply->ret_code,
- ustcomm_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 != USTCOMM_OK) {
- DBG("Return code (%d): %s", reply->ret_code,
- ustcomm_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 <config.h>
#include <lttng/lttng.h>
#include "trace-ust.h"
#ifdef CONFIG_LTTNG_TOOLS_HAVE_UST
-int ustctl_register_done(int sock);
-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);
#else
-static inline
-int ustctl_register_done(int sock)
-{
- return -ENOSYS;
-}
-static inline
-int ustctl_create_channel(int sock, struct ltt_ust_session *session,
- struct lttng_channel *channel)
-{
- return -ENOSYS;
-}
-static inline
-int ustctl_create_session(int sock, struct ltt_ust_session *session)
-{
- return -ENOSYS;
-}
-static inline
-int ustctl_destroy_session(int sock, struct ltt_ust_session *session)
-{
- return -ENOSYS;
-}
-static inline
-int ustctl_disable_channel(int sock, struct ltt_ust_session *session,
- struct ltt_ust_channel *chan)
-{
- return -ENOSYS;
-}
-static inline
-int ustctl_enable_channel(int sock, struct ltt_ust_session *session,
- struct ltt_ust_channel *chan)
-{
- return -ENOSYS;
-}
#endif
channel_name = opt_channel_name;
}
+ if (opt_kernel && opt_userspace) {
+ MSG("Choose only one of --kernel or --userspace");
+ ret = CMD_FATAL;
+ goto error;
+ }
/* Create lttng domain */
if (opt_kernel) {
dom.type = LTTNG_DOMAIN_KERNEL;
}
+ if (opt_userspace) {
+ /* TODO
+ * LTTNG_DOMAIN_UST_EXEC_NAME,
+ * LTTNG_DOMAIN_UST_PID,
+ * LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN
+ */
+ dom.type = LTTNG_DOMAIN_UST;
+ }
handle = lttng_create_handle(session_name, &dom);
if (handle == NULL) {
switch (opt_event_type) {
case LTTNG_EVENT_TRACEPOINT:
- if (opt_kernel) {
- MSG("All kernel tracepoints are enabled in channel %s",
- channel_name);
- }
+ MSG("All %s tracepoints are enabled in channel %s",
+ opt_kernel ? "kernel" : "UST", channel_name);
break;
case LTTNG_EVENT_SYSCALL:
if (opt_kernel) {
}
break;
case LTTNG_EVENT_ALL:
- if (opt_kernel) {
- MSG("All kernel events are enabled in channel %s",
- channel_name);
- }
+ MSG("All %s events are enabled in channel %s",
+ opt_kernel ? "kernel" : "UST", channel_name);
break;
default:
/*
- * We should not be here since lttng_enable_event should had failed
- * on the event type.
+ * We should not be here since
+ * lttng_enable_event should have failed on the
+ * event type.
*/
goto error;
-
}
-
goto end;
}
}
} else if (opt_userspace) { /* User-space tracer action */
/*
- * TODO: Waiting on lttng UST 2.0
+ * TODO: only supporting pid_all tracing for
+ * now. Should have different domain based on
+ * opt_pid.
*/
- if (opt_pid_all) {
- } else if (opt_pid != 0) {
+ if (!opt_pid_all) {
+ MSG("Only supporting tracing all UST processes (-u --all) for now.");
+ ret = CMD_NOT_IMPLEMENTED;
+ goto error;
+ }
+ DBG("Enabling UST event %s for channel %s",
+ event_name, channel_name);
+ /* Copy name and type of the event */
+ strncpy(ev.name, event_name, LTTNG_SYMBOL_NAME_LEN);
+ ev.name[LTTNG_SYMBOL_NAME_LEN - 1] = '\0';
+ ev.type = opt_event_type;
+
+ switch (opt_event_type) {
+ case LTTNG_EVENT_ALL: /* Default behavior is tracepoint */
+ ev.type = LTTNG_EVENT_TRACEPOINT;
+ /* Fall-through */
+ case LTTNG_EVENT_TRACEPOINT:
+ break;
+ case LTTNG_EVENT_PROBE:
+ case LTTNG_EVENT_FUNCTION:
+ case LTTNG_EVENT_FUNCTION_ENTRY:
+ case LTTNG_EVENT_SYSCALL:
+ default:
+ ret = CMD_NOT_IMPLEMENTED;
+ goto error;
+ }
+
+ ret = lttng_enable_event(handle, &ev, channel_name);
+ if (ret == 0) {
+ MSG("UST event %s created in channel %s", event_name, channel_name);
}
- ret = CMD_NOT_IMPLEMENTED;
- goto error;
} else {
ERR("Please specify a tracer (--kernel or --userspace)");
goto error;