X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=liblttng-ust%2Flttng-ust-abi.c;h=b3db6fd735c7e91239a0f61e3e89898b9754c545;hb=ef9ff354212ff4b038e1a5b6a7ed0ffe1b949663;hp=8f38289b0d03c5c56511aafdbbec7cf8f5819300;hpb=40e8d353a7ce33e5bf82537b9faf599e41fefdfd;p=lttng-ust.git diff --git a/liblttng-ust/lttng-ust-abi.c b/liblttng-ust/lttng-ust-abi.c index 8f38289b..b3db6fd7 100644 --- a/liblttng-ust/lttng-ust-abi.c +++ b/liblttng-ust/lttng-ust-abi.c @@ -28,9 +28,13 @@ #include #include #include -#include -#include "lttng/core.h" +#include +#include +#include #include "ltt-tracer.h" +#include "tracepoint-internal.h" + +static int lttng_ust_abi_close_in_progress; static int lttng_abi_tracepoint_list(void); @@ -199,6 +203,8 @@ static const struct lttng_ust_objd_ops lttng_session_ops; static const struct lttng_ust_objd_ops lttng_channel_ops; static const struct lttng_ust_objd_ops lttng_metadata_ops; static const struct lttng_ust_objd_ops lttng_event_ops; +static const struct lttng_ust_objd_ops lttng_loglevel_ops; +static const struct lttng_ust_objd_ops lttng_wildcard_ops; static const struct lttng_ust_objd_ops lib_ring_buffer_objd_ops; static const struct lttng_ust_objd_ops lttng_tracepoint_list_ops; @@ -241,9 +247,9 @@ static long lttng_abi_tracer_version(int objd, struct lttng_ust_tracer_version *v) { - v->version = LTTNG_UST_VERSION; - v->patchlevel = LTTNG_UST_PATCHLEVEL; - v->sublevel = LTTNG_UST_SUBLEVEL; + v->major = LTTNG_UST_MAJOR_VERSION; + v->minor = LTTNG_UST_MINOR_VERSION; + v->patchlevel = LTTNG_UST_PATCHLEVEL_VERSION; return 0; } @@ -275,6 +281,7 @@ long lttng_abi_add_context(int objd, * @objd: the object descriptor * @cmd: the command * @arg: command arg + * @uargs: UST arguments (internal) * * This descriptor implements lttng commands: * LTTNG_UST_SESSION @@ -289,7 +296,8 @@ long lttng_abi_add_context(int objd, * The returned session will be deleted when its file descriptor is closed. */ static -long lttng_cmd(int objd, unsigned int cmd, unsigned long arg) +long lttng_cmd(int objd, unsigned int cmd, unsigned long arg, + union ust_args *uargs) { switch (cmd) { case LTTNG_UST_SESSION: @@ -322,16 +330,17 @@ void lttng_metadata_create_events(int channel_objd) struct ltt_channel *channel = objd_private(channel_objd); static struct lttng_ust_event metadata_params = { .instrumentation = LTTNG_UST_TRACEPOINT, - .name = "lttng_metadata", + .name = "lttng_ust:metadata", }; struct ltt_event *event; + int ret; /* * We tolerate no failure path after event creation. It will stay * invariant for the rest of the session. */ - event = ltt_event_create(channel, &metadata_params, NULL); - if (!event) { + ret = ltt_event_create(channel, &metadata_params, NULL, &event); + if (ret < 0) { goto create_error; } return; @@ -343,7 +352,8 @@ create_error: int lttng_abi_create_channel(int session_objd, struct lttng_ust_channel *chan_param, - enum channel_type channel_type) + enum channel_type channel_type, + union ust_args *uargs) { struct ltt_session *session = objd_private(session_objd); const struct lttng_ust_objd_ops *ops; @@ -392,9 +402,9 @@ int lttng_abi_create_channel(int session_objd, chan_param->num_subbuf, chan_param->switch_timer_interval, chan_param->read_timer_interval, - &chan_param->shm_fd, - &chan_param->wait_fd, - &chan_param->memory_map_size, + &uargs->channel.shm_fd, + &uargs->channel.wait_fd, + &uargs->channel.memory_map_size, &chan_priv_init); if (!chan) { ret = -EINVAL; @@ -428,6 +438,7 @@ objd_error: * @obj: the object * @cmd: the command * @arg: command arg + * @uargs: UST arguments (internal) * * This descriptor implements lttng commands: * LTTNG_UST_CHANNEL @@ -442,7 +453,8 @@ objd_error: * The returned channel will be deleted when its file descriptor is closed. */ static -long lttng_session_cmd(int objd, unsigned int cmd, unsigned long arg) +long lttng_session_cmd(int objd, unsigned int cmd, unsigned long arg, + union ust_args *uargs) { struct ltt_session *session = objd_private(objd); @@ -450,7 +462,7 @@ long lttng_session_cmd(int objd, unsigned int cmd, unsigned long arg) case LTTNG_UST_CHANNEL: return lttng_abi_create_channel(objd, (struct lttng_ust_channel *) arg, - PER_CPU_CHANNEL); + PER_CPU_CHANNEL, uargs); case LTTNG_UST_SESSION_START: case LTTNG_UST_ENABLE: return ltt_session_enable(session); @@ -460,7 +472,7 @@ long lttng_session_cmd(int objd, unsigned int cmd, unsigned long arg) case LTTNG_UST_METADATA: return lttng_abi_create_channel(objd, (struct lttng_ust_channel *) arg, - METADATA_CHANNEL); + METADATA_CHANNEL, uargs); default: return -EINVAL; } @@ -492,46 +504,27 @@ static const struct lttng_ust_objd_ops lttng_session_ops = { .cmd = lttng_session_cmd, }; -/* - * beware: we don't keep the mutex over the send, but we must walk the - * whole list each time we are called again. So sending one tracepoint - * at a time means this is O(n^2). TODO: do as in the kernel and send - * multiple tracepoints for each call to amortize this cost. - */ static -void ltt_tracepoint_list_get(struct ltt_tracepoint_list *list, - char *tp_list_entry) +long lttng_tracepoint_list_cmd(int objd, unsigned int cmd, unsigned long arg, + union ust_args *uargs) { -next: - if (!list->got_first) { - tracepoint_iter_start(&list->iter); - list->got_first = 1; - goto copy; - } - tracepoint_iter_next(&list->iter); -copy: - if (!list->iter.tracepoint) { - tp_list_entry[0] = '\0'; /* end of list */ - } else { - if (!strcmp((*list->iter.tracepoint)->name, "metadata")) - goto next; - memcpy(tp_list_entry, (*list->iter.tracepoint)->name, - LTTNG_UST_SYM_NAME_LEN); - } -} - -static -long lttng_tracepoint_list_cmd(int objd, unsigned int cmd, unsigned long arg) -{ - struct ltt_tracepoint_list *list = objd_private(objd); - char *str = (char *) arg; + struct lttng_ust_tracepoint_list *list = objd_private(objd); + struct lttng_ust_tracepoint_iter *tp = + (struct lttng_ust_tracepoint_iter *) arg; + struct lttng_ust_tracepoint_iter *iter; switch (cmd) { case LTTNG_UST_TRACEPOINT_LIST_GET: - ltt_tracepoint_list_get(list, str); - if (str[0] == '\0') + { + retry: + iter = lttng_ust_tracepoint_list_get_iter_next(list); + if (!iter) return -ENOENT; + if (!strcmp(iter->name, "lttng_ust:metadata")) + goto retry; + memcpy(tp, iter, sizeof(*tp)); return 0; + } default: return -EINVAL; } @@ -541,7 +534,7 @@ static int lttng_abi_tracepoint_list(void) { int list_objd, ret; - struct ltt_tracepoint_list *list; + struct lttng_ust_tracepoint_list *list; list_objd = objd_alloc(NULL, <tng_tracepoint_list_ops); if (list_objd < 0) { @@ -555,8 +548,15 @@ int lttng_abi_tracepoint_list(void) } objd_set_private(list_objd, list); + /* populate list by walking on all registered probes. */ + ret = ltt_probes_get_event_list(list); + if (ret) { + goto list_error; + } return list_objd; +list_error: + free(list); alloc_error: { int err; @@ -571,10 +571,10 @@ objd_error: static int lttng_release_tracepoint_list(int objd) { - struct ltt_tracepoint_list *list = objd_private(objd); + struct lttng_ust_tracepoint_list *list = objd_private(objd); if (list) { - tracepoint_iter_stop(&list->iter); + ltt_probes_prune_event_list(list); free(list); return 0; } else { @@ -593,7 +593,8 @@ struct stream_priv_data { }; static -int lttng_abi_open_stream(int channel_objd, struct lttng_ust_stream *info) +int lttng_abi_open_stream(int channel_objd, struct lttng_ust_stream *info, + union ust_args *uargs) { struct ltt_channel *channel = objd_private(channel_objd); struct lttng_ust_lib_ring_buffer *buf; @@ -601,7 +602,9 @@ int lttng_abi_open_stream(int channel_objd, struct lttng_ust_stream *info) int stream_objd, ret; buf = channel->ops->buffer_read_open(channel->chan, channel->handle, - &info->shm_fd, &info->wait_fd, &info->memory_map_size); + &uargs->stream.shm_fd, + &uargs->stream.wait_fd, + &uargs->stream.memory_map_size); if (!buf) return -ENOENT; @@ -646,9 +649,8 @@ int lttng_abi_create_event(int channel_objd, * We tolerate no failure path after event creation. It will stay * invariant for the rest of the session. */ - event = ltt_event_create(channel, event_param, NULL); - if (!event) { - ret = -EINVAL; + ret = ltt_event_create(channel, event_param, NULL, &event); + if (ret < 0) { goto event_error; } objd_set_private(event_objd, event); @@ -667,12 +669,89 @@ objd_error: return ret; } +static +int lttng_abi_create_loglevel(int channel_objd, + struct lttng_ust_event *event_param) +{ + struct ltt_channel *channel = objd_private(channel_objd); + struct session_loglevel *loglevel; + int loglevel_objd, ret; + + event_param->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; + loglevel_objd = objd_alloc(NULL, <tng_loglevel_ops); + if (loglevel_objd < 0) { + ret = loglevel_objd; + goto objd_error; + } + /* + * We tolerate no failure path after loglevel creation. It will + * stay invariant for the rest of the session. + */ + ret = ltt_loglevel_create(channel, event_param, &loglevel); + if (ret < 0) { + goto loglevel_error; + } + objd_set_private(loglevel_objd, loglevel); + /* The loglevel holds a reference on the channel */ + objd_ref(channel_objd); + return loglevel_objd; + +loglevel_error: + { + int err; + + err = lttng_ust_objd_unref(loglevel_objd); + assert(!err); + } +objd_error: + return ret; +} + +static +int lttng_abi_create_wildcard(int channel_objd, + struct lttng_ust_event *event_param) +{ + struct ltt_channel *channel = objd_private(channel_objd); + struct session_wildcard *wildcard; + int wildcard_objd, ret; + + event_param->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; + wildcard_objd = objd_alloc(NULL, <tng_wildcard_ops); + if (wildcard_objd < 0) { + ret = wildcard_objd; + goto objd_error; + } + /* + * We tolerate no failure path after wildcard creation. It will + * stay invariant for the rest of the session. + */ + ret = ltt_wildcard_create(channel, event_param, &wildcard); + if (ret < 0) { + goto wildcard_error; + } + objd_set_private(wildcard_objd, wildcard); + /* The wildcard holds a reference on the channel */ + objd_ref(channel_objd); + return wildcard_objd; + +wildcard_error: + { + int err; + + err = lttng_ust_objd_unref(wildcard_objd); + assert(!err); + } +objd_error: + return ret; +} + /** * lttng_channel_cmd - lttng control through object descriptors * * @objd: the object descriptor * @cmd: the command * @arg: command arg + * @uargs: UST arguments (internal) * * This object descriptor implements lttng commands: * LTTNG_UST_STREAM @@ -690,7 +769,8 @@ objd_error: * Channel and event file descriptors also hold a reference on the session. */ static -long lttng_channel_cmd(int objd, unsigned int cmd, unsigned long arg) +long lttng_channel_cmd(int objd, unsigned int cmd, unsigned long arg, + union ust_args *uargs) { struct ltt_channel *channel = objd_private(objd); @@ -701,10 +781,23 @@ long lttng_channel_cmd(int objd, unsigned int cmd, unsigned long arg) stream = (struct lttng_ust_stream *) arg; /* stream used as output */ - return lttng_abi_open_stream(objd, stream); + return lttng_abi_open_stream(objd, stream, uargs); } case LTTNG_UST_EVENT: - return lttng_abi_create_event(objd, (struct lttng_ust_event *) arg); + { + struct lttng_ust_event *event_param = + (struct lttng_ust_event *) arg; + if (event_param->instrumentation == LTTNG_UST_TRACEPOINT_LOGLEVEL) { + return lttng_abi_create_loglevel(objd, event_param); + } else { + if (event_param->name[strlen(event_param->name) - 1] == '*') { + /* If ends with wildcard, create wildcard. */ + return lttng_abi_create_wildcard(objd, event_param); + } else { + return lttng_abi_create_event(objd, event_param); + } + } + } case LTTNG_UST_CONTEXT: return lttng_abi_add_context(objd, (struct lttng_ust_context *) arg, @@ -726,6 +819,7 @@ long lttng_channel_cmd(int objd, unsigned int cmd, unsigned long arg) * @objd: the object descriptor * @cmd: the command * @arg: command arg + * @uargs: UST arguments (internal) * * This object descriptor implements lttng commands: * LTTNG_UST_STREAM @@ -734,7 +828,8 @@ long lttng_channel_cmd(int objd, unsigned int cmd, unsigned long arg) * Channel and event file descriptors also hold a reference on the session. */ static -long lttng_metadata_cmd(int objd, unsigned int cmd, unsigned long arg) +long lttng_metadata_cmd(int objd, unsigned int cmd, unsigned long arg, + union ust_args *uargs) { struct ltt_channel *channel = objd_private(objd); @@ -745,7 +840,7 @@ long lttng_metadata_cmd(int objd, unsigned int cmd, unsigned long arg) stream = (struct lttng_ust_stream *) arg; /* stream used as output */ - return lttng_abi_open_stream(objd, stream); + return lttng_abi_open_stream(objd, stream, uargs); } case LTTNG_UST_FLUSH_BUFFER: return channel->ops->flush_buffer(channel->chan, channel->handle); @@ -811,12 +906,14 @@ static const struct lttng_ust_objd_ops lttng_metadata_ops = { * @objd: the object descriptor * @cmd: the command * @arg: command arg + * @uargs: UST arguments (internal) * * This object descriptor implements lttng commands: * (None for now. Access is done directly though shm.) */ static -long lttng_rb_cmd(int objd, unsigned int cmd, unsigned long arg) +long lttng_rb_cmd(int objd, unsigned int cmd, unsigned long arg, + union ust_args *uargs) { switch (cmd) { default: @@ -835,7 +932,21 @@ int lttng_rb_release(int objd) buf = priv->buf; channel = priv->ltt_chan; free(priv); - channel->ops->buffer_read_close(buf, channel->handle); + /* + * If we are at ABI exit, we don't want to close the + * buffer opened for read: it is being shared between + * the parent and child (right after fork), and we don't + * want the child to close it for the parent. For a real + * exit, we don't care about marking it as closed, as + * the consumer daemon (if there is one) will do fine + * even if we don't mark it as "closed" for reading on + * our side. + * We only mark it as closed if it is being explicitely + * released by the session daemon with an explicit + * release command. + */ + if (!lttng_ust_abi_close_in_progress) + channel->ops->buffer_read_close(buf, channel->handle); return lttng_ust_objd_unref(channel->objd); } @@ -853,6 +964,7 @@ static const struct lttng_ust_objd_ops lib_ring_buffer_objd_ops = { * @objd: the object descriptor * @cmd: the command * @arg: command arg + * @uargs: UST arguments (internal) * * This object descriptor implements lttng commands: * LTTNG_UST_CONTEXT @@ -863,7 +975,8 @@ static const struct lttng_ust_objd_ops lib_ring_buffer_objd_ops = { * Disable recording for this event (strong disable) */ static -long lttng_event_cmd(int objd, unsigned int cmd, unsigned long arg) +long lttng_event_cmd(int objd, unsigned int cmd, unsigned long arg, + union ust_args *uargs) { struct ltt_event *event = objd_private(objd); @@ -897,7 +1010,121 @@ static const struct lttng_ust_objd_ops lttng_event_ops = { .cmd = lttng_event_cmd, }; +/** + * lttng_loglevel_cmd - lttng control through object descriptors + * + * @objd: the object descriptor + * @cmd: the command + * @arg: command arg + * @uargs: UST arguments (internal) + * + * This object descriptor implements lttng commands: + * LTTNG_UST_CONTEXT + * Prepend a context field to each record of events of this + * loglevel. + * LTTNG_UST_ENABLE + * Enable recording for these loglevel events (weak enable) + * LTTNG_UST_DISABLE + * Disable recording for these loglevel events (strong disable) + */ +static +long lttng_loglevel_cmd(int objd, unsigned int cmd, unsigned long arg, + union ust_args *uargs) +{ + struct session_loglevel *loglevel = objd_private(objd); + + switch (cmd) { + case LTTNG_UST_CONTEXT: + return -ENOSYS; /* not implemented yet */ +#if 0 + return lttng_abi_add_context(objd, + (struct lttng_ust_context *) arg, + &loglevel->ctx, loglevel->chan->session); +#endif + case LTTNG_UST_ENABLE: + return ltt_loglevel_enable(loglevel); + case LTTNG_UST_DISABLE: + return ltt_loglevel_disable(loglevel); + default: + return -EINVAL; + } +} + +static +int lttng_loglevel_release(int objd) +{ + struct session_loglevel *loglevel = objd_private(objd); + + if (loglevel) + return lttng_ust_objd_unref(loglevel->chan->objd); + return 0; +} + +/* TODO: filter control ioctl */ +static const struct lttng_ust_objd_ops lttng_loglevel_ops = { + .release = lttng_loglevel_release, + .cmd = lttng_loglevel_cmd, +}; + +/** + * lttng_wildcard_cmd - lttng control through object descriptors + * + * @objd: the object descriptor + * @cmd: the command + * @arg: command arg + * @uargs: UST arguments (internal) + * + * This object descriptor implements lttng commands: + * LTTNG_UST_CONTEXT + * Prepend a context field to each record of events of this + * wildcard. + * LTTNG_UST_ENABLE + * Enable recording for these wildcard events (weak enable) + * LTTNG_UST_DISABLE + * Disable recording for these wildcard events (strong disable) + */ +static +long lttng_wildcard_cmd(int objd, unsigned int cmd, unsigned long arg, + union ust_args *uargs) +{ + struct session_wildcard *wildcard = objd_private(objd); + + switch (cmd) { + case LTTNG_UST_CONTEXT: + return -ENOSYS; /* not implemented yet */ +#if 0 + return lttng_abi_add_context(objd, + (struct lttng_ust_context *) arg, + &wildcard->ctx, wildcard->chan->session); +#endif + case LTTNG_UST_ENABLE: + return ltt_wildcard_enable(wildcard); + case LTTNG_UST_DISABLE: + return ltt_wildcard_disable(wildcard); + default: + return -EINVAL; + } +} + +static +int lttng_wildcard_release(int objd) +{ + struct session_wildcard *wildcard = objd_private(objd); + + if (wildcard) + return lttng_ust_objd_unref(wildcard->chan->objd); + return 0; +} + +/* TODO: filter control ioctl */ +static const struct lttng_ust_objd_ops lttng_wildcard_ops = { + .release = lttng_wildcard_release, + .cmd = lttng_wildcard_cmd, +}; + void lttng_ust_abi_exit(void) { + lttng_ust_abi_close_in_progress = 1; objd_table_destroy(); + lttng_ust_abi_close_in_progress = 0; }