From 2bdd86d4c47902237c691d3c5409f32f205df81e Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 27 Oct 2011 14:33:28 +0200 Subject: [PATCH] UST support: add UST control commands Signed-off-by: Mathieu Desnoyers --- include/lttng-sessiond-comm.h | 17 +- liblttng-sessiond-comm/lttng-sessiond-comm.c | 16 +- ltt-sessiond/Makefile.am | 6 +- ltt-sessiond/channel.c | 85 +++- ltt-sessiond/context.c | 179 +++++++ ltt-sessiond/context.h | 9 + ltt-sessiond/event.c | 81 ++++ ltt-sessiond/event.h | 5 + ltt-sessiond/lttng-ust-abi.h | 2 + ltt-sessiond/lttng-ust-ctl.h | 284 ++++++++++++ ltt-sessiond/main.c | 461 ++++++++++++++++++- ltt-sessiond/trace-kernel.h | 8 + ltt-sessiond/trace-ust.c | 6 +- ltt-sessiond/trace-ust.h | 32 +- ltt-sessiond/ust-comm.c | 68 --- ltt-sessiond/ust-comm.h | 26 -- ltt-sessiond/ust-ctl.c | 219 --------- ltt-sessiond/ust-ctl.h | 43 +- lttng/commands/enable_events.c | 70 ++- 19 files changed, 1194 insertions(+), 423 deletions(-) create mode 100644 ltt-sessiond/lttng-ust-ctl.h delete mode 100644 ltt-sessiond/ust-comm.c delete mode 100644 ltt-sessiond/ust-comm.h delete mode 100644 ltt-sessiond/ust-ctl.c diff --git a/include/lttng-sessiond-comm.h b/include/lttng-sessiond-comm.h index 7da343a9d..1b2c4b88e 100644 --- a/include/lttng-sessiond-comm.h +++ b/include/lttng-sessiond-comm.h @@ -114,8 +114,23 @@ enum lttcomm_return_code { 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 */ diff --git a/liblttng-sessiond-comm/lttng-sessiond-comm.c b/liblttng-sessiond-comm/lttng-sessiond-comm.c index 6e0e83b79..01851de5f 100644 --- a/liblttng-sessiond-comm/lttng-sessiond-comm.c +++ b/liblttng-sessiond-comm/lttng-sessiond-comm.c @@ -74,8 +74,22 @@ static const char *lttcomm_readable_code[] = { [ 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", diff --git a/ltt-sessiond/Makefile.am b/ltt-sessiond/Makefile.am index ecc977ab1..f9301896e 100644 --- a/ltt-sessiond/Makefile.am +++ b/ltt-sessiond/Makefile.am @@ -29,9 +29,7 @@ ltt_sessiond_SOURCES = utils.c utils.h \ 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. @@ -41,5 +39,5 @@ ltt_sessiond_LDADD = -lrt \ $(top_builddir)/liblttngctl/liblttngctl.la if LTTNG_TOOLS_HAVE_UST -ltt_sessiond_LDADD += -llttng-ust-comm +ltt_sessiond_LDADD += -llttng-ust-comm -lustctl endif diff --git a/ltt-sessiond/channel.c b/ltt-sessiond/channel.c index 10635536c..b61e1fb67 100644 --- a/ltt-sessiond/channel.c +++ b/ltt-sessiond/channel.c @@ -21,6 +21,13 @@ #include #include #include +#ifdef CONFIG_LTTNG_TOOLS_HAVE_UST +#include +#include +#else +#include "lttng-ust-ctl.h" +#include "lttng-ust-abi.h" +#endif #include "channel.h" #include "kernel-ctl.h" @@ -56,6 +63,7 @@ struct lttng_channel *channel_new_default_attr(int dom) 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; @@ -164,6 +172,7 @@ int channel_kernel_create(struct ltt_kernel_session *ksession, /* 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; @@ -199,23 +208,55 @@ int channel_ust_create(struct ltt_ust_session *usession, { 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; @@ -229,18 +270,20 @@ error: 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; } @@ -250,17 +293,19 @@ error: 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; } diff --git a/ltt-sessiond/context.c b/ltt-sessiond/context.c index 35cb50b7b..c7765c0e8 100644 --- a/ltt-sessiond/context.c +++ b/ltt-sessiond/context.c @@ -25,6 +25,14 @@ #include #include +#ifdef CONFIG_LTTNG_TOOLS_HAVE_UST +#include +#include +#else +#include "lttng-ust-ctl.h" +#include "lttng-ust-abi.h" +#endif + #include "context.h" #include "kernel-ctl.h" @@ -191,3 +199,174 @@ int context_kernel_add(struct ltt_kernel_session *ksession, 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; +} diff --git a/ltt-sessiond/context.h b/ltt-sessiond/context.h index 38d39d94f..872e77e7b 100644 --- a/ltt-sessiond/context.h +++ b/ltt-sessiond/context.h @@ -19,10 +19,19 @@ #define _LTT_CONTEXT_H #include +#ifdef CONFIG_LTTNG_TOOLS_HAVE_UST +#include +#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 */ diff --git a/ltt-sessiond/event.c b/ltt-sessiond/event.c index c12e385b3..eef0039d6 100644 --- a/ltt-sessiond/event.c +++ b/ltt-sessiond/event.c @@ -17,11 +17,18 @@ #include #include +#include #include #include #include +#ifdef CONFIG_LTTNG_TOOLS_HAVE_UST +#include +#else +#include "lttng-ust-ctl.h" +#endif + #include "channel.h" #include "event.h" #include "kernel-ctl.h" @@ -229,3 +236,77 @@ int event_kernel_enable_all(struct ltt_kernel_session *ksession, 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; +} diff --git a/ltt-sessiond/event.h b/ltt-sessiond/event.h index 38768c51a..879ae659c 100644 --- a/ltt-sessiond/event.h +++ b/ltt-sessiond/event.h @@ -40,4 +40,9 @@ int event_kernel_enable_all_syscalls(struct ltt_kernel_session *ksession, 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 */ diff --git a/ltt-sessiond/lttng-ust-abi.h b/ltt-sessiond/lttng-ust-abi.h index 303493eeb..da2bfb942 100644 --- a/ltt-sessiond/lttng-ust-abi.h +++ b/ltt-sessiond/lttng-ust-abi.h @@ -111,6 +111,8 @@ struct lttng_ust_context { /* 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) diff --git a/ltt-sessiond/lttng-ust-ctl.h b/ltt-sessiond/lttng-ust-ctl.h new file mode 100644 index 000000000..f3859b846 --- /dev/null +++ b/ltt-sessiond/lttng-ust-ctl.h @@ -0,0 +1,284 @@ +/* + * Copyright (C) 2011 - Julien Desfossez + * Mathieu Desnoyers + * + * 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 + +/* + * 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 */ diff --git a/ltt-sessiond/main.c b/ltt-sessiond/main.c index ddf5acd2f..c288afbb0 100644 --- a/ltt-sessiond/main.c +++ b/ltt-sessiond/main.c @@ -41,6 +41,14 @@ #include #include #include + +#ifdef CONFIG_LTTNG_TOOLS_HAVE_UST +#include +#else +#include "lttng-ust-ctl.h" +#endif + + #include #include "channel.h" @@ -413,7 +421,7 @@ static void clean_command_ctx(struct command_ctx **cmd_ctx) /* * 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; @@ -428,7 +436,7 @@ static int send_consumer_channel_streams(struct consumer_data *consumer_data, 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"); @@ -469,10 +477,84 @@ error: 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; @@ -482,7 +564,7 @@ static int send_consumer_session_streams(struct consumer_data *consumer_data, 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; } @@ -523,7 +605,86 @@ static int send_consumer_session_streams(struct consumer_data *consumer_data, } 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; } @@ -642,7 +803,7 @@ 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; @@ -678,7 +839,7 @@ static int update_stream(struct consumer_data *consumer_data, int fd) * 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; @@ -778,7 +939,7 @@ static void *thread_manage_kernel(void *data) * 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; } @@ -1622,7 +1783,7 @@ static int init_kernel_tracing(struct ltt_kernel_session *session) 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; @@ -1635,6 +1796,36 @@ 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. */ @@ -1677,11 +1868,13 @@ static int create_ust_session(struct ltt_session *session, } /* 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++; @@ -1980,10 +2173,12 @@ static int cmd_disable_event(struct ltt_session *session, int domain, 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) { @@ -1998,8 +2193,34 @@ static int cmd_disable_event(struct ltt_session *session, int domain, 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; } @@ -2063,10 +2284,23 @@ static int cmd_add_context(struct ltt_session *session, int domain, 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; } @@ -2084,11 +2318,13 @@ static int cmd_enable_event(struct ltt_session *session, int domain, 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) { @@ -2123,8 +2359,54 @@ static int cmd_enable_event(struct ltt_session *session, int domain, 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; } @@ -2241,14 +2523,16 @@ 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); @@ -2299,7 +2583,101 @@ static int cmd_start_trace(struct ltt_session *session) 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; @@ -2315,6 +2693,8 @@ static int cmd_stop_trace(struct ltt_session *session) 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; @@ -2345,7 +2725,30 @@ static int cmd_stop_trace(struct ltt_session *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; @@ -2515,6 +2918,8 @@ static ssize_t cmd_list_channels(struct ltt_session *session, list_lttng_channels(session, *channels); + /* TODO UST support */ + return nb_chan; error: @@ -2659,7 +3064,10 @@ static int process_client_msg(struct command_ctx *cmd_ctx) 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; @@ -2674,11 +3082,22 @@ static int process_client_msg(struct command_ctx *cmd_ctx) 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; } @@ -2708,7 +3127,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx) } 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); @@ -2729,7 +3148,7 @@ static int process_client_msg(struct command_ctx *cmd_ctx) } 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, diff --git a/ltt-sessiond/trace-kernel.h b/ltt-sessiond/trace-kernel.h index 2bf2f03c9..bcea65148 100644 --- a/ltt-sessiond/trace-kernel.h +++ b/ltt-sessiond/trace-kernel.h @@ -44,6 +44,10 @@ struct ltt_kernel_channel_list { 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; @@ -56,6 +60,10 @@ struct ltt_kernel_channel { 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; diff --git a/ltt-sessiond/trace-ust.c b/ltt-sessiond/trace-ust.c index cf1642a6e..c2978894e 100644 --- a/ltt-sessiond/trace-ust.c +++ b/ltt-sessiond/trace-ust.c @@ -189,6 +189,7 @@ struct ltt_ust_channel *trace_ust_create_channel(struct lttng_channel *chan, perror("asprintf ust create channel"); goto error; } + CDS_INIT_LIST_HEAD(&luc->stream_list.head); return luc; @@ -270,7 +271,7 @@ struct ltt_ust_metadata *trace_ust_create_metadata(char *path) 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; @@ -321,8 +322,7 @@ void trace_ust_destroy_metadata(struct ltt_ust_metadata *metadata) DBG("[trace] Destroy ust metadata %d", metadata->handle); /* Free attributes */ - free(metadata->trace_path); - + free(metadata->pathname); free(metadata); } diff --git a/ltt-sessiond/trace-ust.h b/ltt-sessiond/trace-ust.h index abbf9a9d1..e2901a7fa 100644 --- a/ltt-sessiond/trace-ust.h +++ b/ltt-sessiond/trace-ust.h @@ -50,6 +50,12 @@ struct ltt_ust_event_list { 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; @@ -60,9 +66,21 @@ struct ltt_ust_channel_list { 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 */ @@ -71,29 +89,41 @@ struct ltt_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 diff --git a/ltt-sessiond/ust-comm.c b/ltt-sessiond/ust-comm.c deleted file mode 100644 index 4a54bf784..000000000 --- a/ltt-sessiond/ust-comm.c +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2011 - David Goulet - * - * 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 -#include -#include -#include -#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; -} diff --git a/ltt-sessiond/ust-comm.h b/ltt-sessiond/ust-comm.h deleted file mode 100644 index f7a395166..000000000 --- a/ltt-sessiond/ust-comm.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2011 - David Goulet - * - * 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 - -struct lttcomm_ust_reply *ustcomm_send_command(int sock, - struct lttcomm_ust_msg *msg); - -#endif /* _LTT_UST_COMM_H */ diff --git a/ltt-sessiond/ust-ctl.c b/ltt-sessiond/ust-ctl.c deleted file mode 100644 index 7f70b8975..000000000 --- a/ltt-sessiond/ust-ctl.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright (C) 2011 - David Goulet - * - * 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 -#include -#include -#include -#include - -#include -#include - -#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; -} diff --git a/ltt-sessiond/ust-ctl.h b/ltt-sessiond/ust-ctl.h index a592abf22..a6d4e773e 100644 --- a/ltt-sessiond/ust-ctl.h +++ b/ltt-sessiond/ust-ctl.h @@ -19,57 +19,16 @@ #ifndef _LTT_UST_CTL_H #define _LTT_UST_CTL_H +#include #include #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 diff --git a/lttng/commands/enable_events.c b/lttng/commands/enable_events.c index fbcd40daf..cb53fb0db 100644 --- a/lttng/commands/enable_events.c +++ b/lttng/commands/enable_events.c @@ -201,10 +201,23 @@ static int enable_events(char *session_name) 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) { @@ -224,10 +237,8 @@ static int enable_events(char *session_name) 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) { @@ -236,20 +247,17 @@ static int enable_events(char *session_name) } 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; } @@ -308,13 +316,41 @@ static int enable_events(char *session_name) } } 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; -- 2.34.1