X-Git-Url: http://git.liburcu.org/?a=blobdiff_plain;f=liblttng-ust%2Flttng-ust-abi.c;h=c060e2d9aaae49f033cf420f0155bb7a03d5d4c8;hb=HEAD;hp=70ec22aa1ac8362ad244ed1c92caa3d032bcb244;hpb=1849ef7cdc349bef4b6f6eb4a50058e06c26d431;p=lttng-ust.git diff --git a/liblttng-ust/lttng-ust-abi.c b/liblttng-ust/lttng-ust-abi.c deleted file mode 100644 index 70ec22aa..00000000 --- a/liblttng-ust/lttng-ust-abi.c +++ /dev/null @@ -1,955 +0,0 @@ -/* - * lttng-ust-abi.c - * - * LTTng UST ABI - * - * Copyright (C) 2010-2012 Mathieu Desnoyers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; only - * version 2.1 of the License. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * - * Mimic system calls for: - * - session creation, returns an object descriptor or failure. - * - channel creation, returns an object descriptor or failure. - * - Operates on a session object descriptor - * - Takes all channel options as parameters. - * - stream get, returns an object descriptor or failure. - * - Operates on a channel object descriptor. - * - stream notifier get, returns an object descriptor or failure. - * - Operates on a channel object descriptor. - * - event creation, returns an object descriptor or failure. - * - Operates on a channel object descriptor - * - Takes an event name as parameter - * - Takes an instrumentation source as parameter - * - e.g. tracepoints, dynamic_probes... - * - Takes instrumentation source specific arguments. - */ - -#include -#include -#include -#include -#include -#include -#include -#include "tracepoint-internal.h" -#include -#include -#include "lttng-tracer.h" -#include "../libringbuffer/shm.h" -#include "../libringbuffer/frontend_types.h" - -#define OBJ_NAME_LEN 16 - -static int lttng_ust_abi_close_in_progress; - -static -int lttng_abi_tracepoint_list(void *owner); -static -int lttng_abi_tracepoint_field_list(void *owner); - -/* - * Object descriptor table. Should be protected from concurrent access - * by the caller. - */ - -struct lttng_ust_obj { - union { - struct { - void *private_data; - const struct lttng_ust_objd_ops *ops; - int f_count; - int owner_ref; /* has ref from owner */ - void *owner; - char name[OBJ_NAME_LEN]; - } s; - int freelist_next; /* offset freelist. end is -1. */ - } u; -}; - -struct lttng_ust_objd_table { - struct lttng_ust_obj *array; - unsigned int len, allocated_len; - int freelist_head; /* offset freelist head. end is -1 */ -}; - -static struct lttng_ust_objd_table objd_table = { - .freelist_head = -1, -}; - -static -int objd_alloc(void *private_data, const struct lttng_ust_objd_ops *ops, - void *owner, const char *name) -{ - struct lttng_ust_obj *obj; - - if (objd_table.freelist_head != -1) { - obj = &objd_table.array[objd_table.freelist_head]; - objd_table.freelist_head = obj->u.freelist_next; - goto end; - } - - if (objd_table.len >= objd_table.allocated_len) { - unsigned int new_allocated_len, old_allocated_len; - struct lttng_ust_obj *new_table, *old_table; - - old_allocated_len = objd_table.allocated_len; - old_table = objd_table.array; - if (!old_allocated_len) - new_allocated_len = 1; - else - new_allocated_len = old_allocated_len << 1; - new_table = zmalloc(sizeof(struct lttng_ust_obj) * new_allocated_len); - if (!new_table) - return -ENOMEM; - memcpy(new_table, old_table, - sizeof(struct lttng_ust_obj) * old_allocated_len); - free(old_table); - objd_table.array = new_table; - objd_table.allocated_len = new_allocated_len; - } - obj = &objd_table.array[objd_table.len]; - objd_table.len++; -end: - obj->u.s.private_data = private_data; - obj->u.s.ops = ops; - obj->u.s.f_count = 2; /* count == 1 : object is allocated */ - /* count == 2 : allocated + hold ref */ - obj->u.s.owner_ref = 1; /* One owner reference */ - obj->u.s.owner = owner; - strncpy(obj->u.s.name, name, OBJ_NAME_LEN); - obj->u.s.name[OBJ_NAME_LEN - 1] = '\0'; - return obj - objd_table.array; -} - -static -struct lttng_ust_obj *_objd_get(int id) -{ - if (id >= objd_table.len) - return NULL; - if (!objd_table.array[id].u.s.f_count) - return NULL; - return &objd_table.array[id]; -} - -static -void *objd_private(int id) -{ - struct lttng_ust_obj *obj = _objd_get(id); - assert(obj); - return obj->u.s.private_data; -} - -static -void objd_set_private(int id, void *private_data) -{ - struct lttng_ust_obj *obj = _objd_get(id); - assert(obj); - obj->u.s.private_data = private_data; -} - -const struct lttng_ust_objd_ops *objd_ops(int id) -{ - struct lttng_ust_obj *obj = _objd_get(id); - - if (!obj) - return NULL; - return obj->u.s.ops; -} - -static -void objd_free(int id) -{ - struct lttng_ust_obj *obj = _objd_get(id); - - assert(obj); - obj->u.freelist_next = objd_table.freelist_head; - objd_table.freelist_head = obj - objd_table.array; - assert(obj->u.s.f_count == 1); - obj->u.s.f_count = 0; /* deallocated */ -} - -static -void objd_ref(int id) -{ - struct lttng_ust_obj *obj = _objd_get(id); - obj->u.s.f_count++; -} - -int lttng_ust_objd_unref(int id, int is_owner) -{ - struct lttng_ust_obj *obj = _objd_get(id); - - if (!obj) - return -EINVAL; - if (obj->u.s.f_count == 1) { - ERR("Reference counting error\n"); - return -EINVAL; - } - if (is_owner) { - if (!obj->u.s.owner_ref) { - ERR("Error decrementing owner reference"); - return -EINVAL; - } - obj->u.s.owner_ref--; - } - if ((--obj->u.s.f_count) == 1) { - const struct lttng_ust_objd_ops *ops = objd_ops(id); - - if (ops->release) - ops->release(id); - objd_free(id); - } - return 0; -} - -static -void objd_table_destroy(void) -{ - int i; - - for (i = 0; i < objd_table.allocated_len; i++) { - struct lttng_ust_obj *obj; - - obj = _objd_get(i); - if (!obj) - continue; - if (!obj->u.s.owner_ref) - continue; /* only unref owner ref. */ - (void) lttng_ust_objd_unref(i, 1); - } - free(objd_table.array); - objd_table.array = NULL; - objd_table.len = 0; - objd_table.allocated_len = 0; - objd_table.freelist_head = -1; -} - -const char *lttng_ust_obj_get_name(int id) -{ - struct lttng_ust_obj *obj = _objd_get(id); - - if (!obj) - return NULL; - return obj->u.s.name; -} - -void lttng_ust_objd_table_owner_cleanup(void *owner) -{ - int i; - - for (i = 0; i < objd_table.allocated_len; i++) { - struct lttng_ust_obj *obj; - - obj = _objd_get(i); - if (!obj) - continue; - if (!obj->u.s.owner) - continue; /* skip root handles */ - if (!obj->u.s.owner_ref) - continue; /* only unref owner ref. */ - if (obj->u.s.owner == owner) - (void) lttng_ust_objd_unref(i, 1); - } -} - -/* - * This is LTTng's own personal way to create an ABI for sessiond. - * We send commands over a socket. - */ - -static const struct lttng_ust_objd_ops lttng_ops; -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_enabler_ops; -static const struct lttng_ust_objd_ops lttng_tracepoint_list_ops; -static const struct lttng_ust_objd_ops lttng_tracepoint_field_list_ops; - -int lttng_abi_create_root_handle(void) -{ - int root_handle; - - /* root handles have NULL owners */ - root_handle = objd_alloc(NULL, <tng_ops, NULL, "root"); - return root_handle; -} - -static -int lttng_is_channel_ready(struct lttng_channel *lttng_chan) -{ - struct channel *chan; - unsigned int nr_streams, exp_streams; - - chan = lttng_chan->chan; - nr_streams = channel_handle_get_nr_streams(lttng_chan->handle); - exp_streams = chan->nr_streams; - return nr_streams == exp_streams; -} - -static -int lttng_abi_create_session(void *owner) -{ - struct lttng_session *session; - int session_objd, ret; - - session = lttng_session_create(); - if (!session) - return -ENOMEM; - session_objd = objd_alloc(session, <tng_session_ops, owner, "session"); - if (session_objd < 0) { - ret = session_objd; - goto objd_error; - } - session->objd = session_objd; - session->owner = owner; - return session_objd; - -objd_error: - lttng_session_destroy(session); - return ret; -} - -static -long lttng_abi_tracer_version(int objd, - struct lttng_ust_tracer_version *v) -{ - v->major = LTTNG_UST_MAJOR_VERSION; - v->minor = LTTNG_UST_MINOR_VERSION; - v->patchlevel = LTTNG_UST_PATCHLEVEL_VERSION; - return 0; -} - -static -long lttng_abi_add_context(int objd, - struct lttng_ust_context *context_param, - struct lttng_ctx **ctx, struct lttng_session *session) -{ - return lttng_attach_context(context_param, ctx, session); -} - -/** - * lttng_cmd - lttng control through socket commands - * - * @objd: the object descriptor - * @cmd: the command - * @arg: command arg - * @uargs: UST arguments (internal) - * @owner: objd owner - * - * This descriptor implements lttng commands: - * LTTNG_UST_SESSION - * Returns a LTTng trace session object descriptor - * LTTNG_UST_TRACER_VERSION - * Returns the LTTng kernel tracer version - * LTTNG_UST_TRACEPOINT_LIST - * Returns a file descriptor listing available tracepoints - * LTTNG_UST_TRACEPOINT_FIELD_LIST - * Returns a file descriptor listing available tracepoint fields - * LTTNG_UST_WAIT_QUIESCENT - * Returns after all previously running probes have completed - * - * The returned session will be deleted when its file descriptor is closed. - */ -static -long lttng_cmd(int objd, unsigned int cmd, unsigned long arg, - union ust_args *uargs, void *owner) -{ - switch (cmd) { - case LTTNG_UST_SESSION: - return lttng_abi_create_session(owner); - case LTTNG_UST_TRACER_VERSION: - return lttng_abi_tracer_version(objd, - (struct lttng_ust_tracer_version *) arg); - case LTTNG_UST_TRACEPOINT_LIST: - return lttng_abi_tracepoint_list(owner); - case LTTNG_UST_TRACEPOINT_FIELD_LIST: - return lttng_abi_tracepoint_field_list(owner); - case LTTNG_UST_WAIT_QUIESCENT: - synchronize_trace(); - return 0; - default: - return -EINVAL; - } -} - -static const struct lttng_ust_objd_ops lttng_ops = { - .cmd = lttng_cmd, -}; - -int lttng_abi_map_channel(int session_objd, - struct lttng_ust_channel *ust_chan, - union ust_args *uargs, - void *owner) -{ - struct lttng_session *session = objd_private(session_objd); - const char *transport_name; - const struct lttng_transport *transport; - const char *chan_name; - int chan_objd; - struct lttng_ust_shm_handle *channel_handle; - struct lttng_channel *lttng_chan; - struct channel *chan; - struct lttng_ust_lib_ring_buffer_config *config; - void *chan_data; - uint64_t len; - int ret; - enum lttng_ust_chan_type type; - - chan_data = uargs->channel.chan_data; - len = ust_chan->len; - type = ust_chan->type; - - switch (type) { - case LTTNG_UST_CHAN_PER_CPU: - break; - default: - return -EINVAL; - } - - if (session->been_active) { - ret = -EBUSY; - goto active; /* Refuse to add channel to active session */ - } - - channel_handle = channel_handle_create(chan_data, len); - if (!channel_handle) { - ret = -EINVAL; - goto handle_error; - } - - chan = shmp(channel_handle, channel_handle->chan); - assert(chan); - chan->handle = channel_handle; - config = &chan->backend.config; - lttng_chan = channel_get_private(chan); - if (!lttng_chan) { - ret = -EINVAL; - goto alloc_error; - } - - /* Lookup transport name */ - switch (type) { - case LTTNG_UST_CHAN_PER_CPU: - if (config->output == RING_BUFFER_MMAP) { - transport_name = config->mode == RING_BUFFER_OVERWRITE ? - "relay-overwrite-mmap" : "relay-discard-mmap"; - } else { - ret = -EINVAL; - goto notransport; - } - chan_name = "channel"; - break; - default: - transport_name = ""; - chan_name = ""; - ret = -EINVAL; - goto notransport; - } - transport = lttng_transport_find(transport_name); - if (!transport) { - DBG("LTTng transport %s not found\n", - transport_name); - ret = -EINVAL; - goto notransport; - } - - chan_objd = objd_alloc(NULL, <tng_channel_ops, owner, chan_name); - if (chan_objd < 0) { - ret = chan_objd; - goto objd_error; - } - - /* Initialize our lttng chan */ - lttng_chan->chan = chan; - lttng_chan->tstate = 1; - lttng_chan->enabled = 1; - lttng_chan->ctx = NULL; - lttng_chan->session = session; - lttng_chan->ops = &transport->ops; - memcpy(<tng_chan->chan->backend.config, - transport->client_config, - sizeof(lttng_chan->chan->backend.config)); - cds_list_add(<tng_chan->node, &session->chan_head); - lttng_chan->header_type = 0; - lttng_chan->handle = channel_handle; - lttng_chan->type = type; - - /* - * We tolerate no failure path after channel creation. It will stay - * invariant for the rest of the session. - */ - objd_set_private(chan_objd, lttng_chan); - lttng_chan->objd = chan_objd; - /* The channel created holds a reference on the session */ - objd_ref(session_objd); - return chan_objd; - -objd_error: -notransport: - free(lttng_chan); -alloc_error: - channel_destroy(chan, channel_handle, 0); -handle_error: -active: - return ret; -} - -/** - * lttng_session_cmd - lttng session object command - * - * @obj: the object - * @cmd: the command - * @arg: command arg - * @uargs: UST arguments (internal) - * @owner: objd owner - * - * This descriptor implements lttng commands: - * LTTNG_UST_CHANNEL - * Returns a LTTng channel object descriptor - * LTTNG_UST_ENABLE - * Enables tracing for a session (weak enable) - * LTTNG_UST_DISABLE - * Disables tracing for a session (strong disable) - * - * 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, - union ust_args *uargs, void *owner) -{ - struct lttng_session *session = objd_private(objd); - - switch (cmd) { - case LTTNG_UST_CHANNEL: - return lttng_abi_map_channel(objd, - (struct lttng_ust_channel *) arg, - uargs, owner); - case LTTNG_UST_SESSION_START: - case LTTNG_UST_ENABLE: - return lttng_session_enable(session); - case LTTNG_UST_SESSION_STOP: - case LTTNG_UST_DISABLE: - return lttng_session_disable(session); - default: - return -EINVAL; - } -} - -/* - * Called when the last file reference is dropped. - * - * Big fat note: channels and events are invariant for the whole session after - * their creation. So this session destruction also destroys all channel and - * event structures specific to this session (they are not destroyed when their - * individual file is released). - */ -static -int lttng_release_session(int objd) -{ - struct lttng_session *session = objd_private(objd); - - if (session) { - lttng_session_destroy(session); - return 0; - } else { - return -EINVAL; - } -} - -static const struct lttng_ust_objd_ops lttng_session_ops = { - .release = lttng_release_session, - .cmd = lttng_session_cmd, -}; - -static -long lttng_tracepoint_list_cmd(int objd, unsigned int cmd, unsigned long arg, - union ust_args *uargs, void *owner) -{ - 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: - { - iter = lttng_ust_tracepoint_list_get_iter_next(list); - if (!iter) - return -LTTNG_UST_ERR_NOENT; - memcpy(tp, iter, sizeof(*tp)); - return 0; - } - default: - return -EINVAL; - } -} - -static -int lttng_abi_tracepoint_list(void *owner) -{ - int list_objd, ret; - struct lttng_ust_tracepoint_list *list; - - list_objd = objd_alloc(NULL, <tng_tracepoint_list_ops, owner, "tp_list"); - if (list_objd < 0) { - ret = list_objd; - goto objd_error; - } - list = zmalloc(sizeof(*list)); - if (!list) { - ret = -ENOMEM; - goto alloc_error; - } - objd_set_private(list_objd, list); - - /* populate list by walking on all registered probes. */ - ret = lttng_probes_get_event_list(list); - if (ret) { - goto list_error; - } - return list_objd; - -list_error: - free(list); -alloc_error: - { - int err; - - err = lttng_ust_objd_unref(list_objd, 1); - assert(!err); - } -objd_error: - return ret; -} - -static -int lttng_release_tracepoint_list(int objd) -{ - struct lttng_ust_tracepoint_list *list = objd_private(objd); - - if (list) { - lttng_probes_prune_event_list(list); - free(list); - return 0; - } else { - return -EINVAL; - } -} - -static const struct lttng_ust_objd_ops lttng_tracepoint_list_ops = { - .release = lttng_release_tracepoint_list, - .cmd = lttng_tracepoint_list_cmd, -}; - -static -long lttng_tracepoint_field_list_cmd(int objd, unsigned int cmd, - unsigned long arg, union ust_args *uargs, void *owner) -{ - struct lttng_ust_field_list *list = objd_private(objd); - struct lttng_ust_field_iter *tp = &uargs->field_list.entry; - struct lttng_ust_field_iter *iter; - - switch (cmd) { - case LTTNG_UST_TRACEPOINT_FIELD_LIST_GET: - { - iter = lttng_ust_field_list_get_iter_next(list); - if (!iter) - return -LTTNG_UST_ERR_NOENT; - memcpy(tp, iter, sizeof(*tp)); - return 0; - } - default: - return -EINVAL; - } -} - -static -int lttng_abi_tracepoint_field_list(void *owner) -{ - int list_objd, ret; - struct lttng_ust_field_list *list; - - list_objd = objd_alloc(NULL, <tng_tracepoint_field_list_ops, owner, - "tp_field_list"); - if (list_objd < 0) { - ret = list_objd; - goto objd_error; - } - list = zmalloc(sizeof(*list)); - if (!list) { - ret = -ENOMEM; - goto alloc_error; - } - objd_set_private(list_objd, list); - - /* populate list by walking on all registered probes. */ - ret = lttng_probes_get_field_list(list); - if (ret) { - goto list_error; - } - return list_objd; - -list_error: - free(list); -alloc_error: - { - int err; - - err = lttng_ust_objd_unref(list_objd, 1); - assert(!err); - } -objd_error: - return ret; -} - -static -int lttng_release_tracepoint_field_list(int objd) -{ - struct lttng_ust_field_list *list = objd_private(objd); - - if (list) { - lttng_probes_prune_field_list(list); - free(list); - return 0; - } else { - return -EINVAL; - } -} - -static const struct lttng_ust_objd_ops lttng_tracepoint_field_list_ops = { - .release = lttng_release_tracepoint_field_list, - .cmd = lttng_tracepoint_field_list_cmd, -}; - -static -int lttng_abi_map_stream(int channel_objd, struct lttng_ust_stream *info, - union ust_args *uargs, void *owner) -{ - struct lttng_channel *channel = objd_private(channel_objd); - int ret; - - ret = channel_handle_add_stream(channel->handle, - uargs->stream.shm_fd, uargs->stream.wakeup_fd, - info->stream_nr, info->len); - if (ret) - goto error_add_stream; - - return 0; - -error_add_stream: - return ret; -} - -static -int lttng_abi_create_enabler(int channel_objd, - struct lttng_ust_event *event_param, - void *owner, - enum lttng_enabler_type type) -{ - struct lttng_channel *channel = objd_private(channel_objd); - struct lttng_enabler *enabler; - int event_objd, ret; - - event_param->name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0'; - event_objd = objd_alloc(NULL, <tng_enabler_ops, owner, "enabler"); - if (event_objd < 0) { - ret = event_objd; - goto objd_error; - } - /* - * We tolerate no failure path after event creation. It will stay - * invariant for the rest of the session. - */ - enabler = lttng_enabler_create(type, event_param, channel); - if (!enabler) { - ret = -ENOMEM; - goto event_error; - } - objd_set_private(event_objd, enabler); - /* The event holds a reference on the channel */ - objd_ref(channel_objd); - return event_objd; - -event_error: - { - int err; - - err = lttng_ust_objd_unref(event_objd, 1); - 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) - * @owner: objd owner - * - * This object descriptor implements lttng commands: - * LTTNG_UST_STREAM - * Returns an event stream object descriptor or failure. - * (typically, one event stream records events from one CPU) - * LTTNG_UST_EVENT - * Returns an event object descriptor or failure. - * LTTNG_UST_CONTEXT - * Prepend a context field to each event in the channel - * LTTNG_UST_ENABLE - * Enable recording for events in this channel (weak enable) - * LTTNG_UST_DISABLE - * Disable recording for events in this channel (strong disable) - * - * 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, - union ust_args *uargs, void *owner) -{ - struct lttng_channel *channel = objd_private(objd); - - if (cmd != LTTNG_UST_STREAM) { - /* - * Check if channel received all streams. - */ - if (!lttng_is_channel_ready(channel)) - return -EPERM; - } - - switch (cmd) { - case LTTNG_UST_STREAM: - { - struct lttng_ust_stream *stream; - - stream = (struct lttng_ust_stream *) arg; - /* stream used as output */ - return lttng_abi_map_stream(objd, stream, uargs, owner); - } - case LTTNG_UST_EVENT: - { - struct lttng_ust_event *event_param = - (struct lttng_ust_event *) arg; - if (event_param->name[strlen(event_param->name) - 1] == '*') { - /* If ends with wildcard, create wildcard. */ - return lttng_abi_create_enabler(objd, event_param, - owner, LTTNG_ENABLER_WILDCARD); - } else { - return lttng_abi_create_enabler(objd, event_param, - owner, LTTNG_ENABLER_EVENT); - } - } - case LTTNG_UST_CONTEXT: - return lttng_abi_add_context(objd, - (struct lttng_ust_context *) arg, - &channel->ctx, channel->session); - case LTTNG_UST_ENABLE: - return lttng_channel_enable(channel); - case LTTNG_UST_DISABLE: - return lttng_channel_disable(channel); - case LTTNG_UST_FLUSH_BUFFER: - return channel->ops->flush_buffer(channel->chan, channel->handle); - default: - return -EINVAL; - } -} - -static -int lttng_channel_release(int objd) -{ - struct lttng_channel *channel = objd_private(objd); - - if (channel) - return lttng_ust_objd_unref(channel->session->objd, 0); - return 0; -} - -static const struct lttng_ust_objd_ops lttng_channel_ops = { - .release = lttng_channel_release, - .cmd = lttng_channel_cmd, -}; - -/** - * lttng_enabler_cmd - lttng control through object descriptors - * - * @objd: the object descriptor - * @cmd: the command - * @arg: command arg - * @uargs: UST arguments (internal) - * @owner: objd owner - * - * This object descriptor implements lttng commands: - * LTTNG_UST_CONTEXT - * Prepend a context field to each record of events of this - * enabler. - * LTTNG_UST_ENABLE - * Enable recording for this enabler - * LTTNG_UST_DISABLE - * Disable recording for this enabler - * LTTNG_UST_FILTER - * Attach a filter to an enabler. - */ -static -long lttng_enabler_cmd(int objd, unsigned int cmd, unsigned long arg, - union ust_args *uargs, void *owner) -{ - struct lttng_enabler *enabler = objd_private(objd); - - switch (cmd) { - case LTTNG_UST_CONTEXT: - return lttng_enabler_attach_context(enabler, - (struct lttng_ust_context *) arg); - case LTTNG_UST_ENABLE: - return lttng_enabler_enable(enabler); - case LTTNG_UST_DISABLE: - return lttng_enabler_disable(enabler); - case LTTNG_UST_FILTER: - { - int ret; - - ret = lttng_enabler_attach_bytecode(enabler, - (struct lttng_ust_filter_bytecode_node *) arg); - if (ret) - return ret; - return 0; - } - default: - return -EINVAL; - } -} - -static -int lttng_enabler_release(int objd) -{ - struct lttng_enabler *enabler = objd_private(objd); - - if (enabler) - return lttng_ust_objd_unref(enabler->chan->objd, 0); - return 0; -} - -static const struct lttng_ust_objd_ops lttng_enabler_ops = { - .release = lttng_enabler_release, - .cmd = lttng_enabler_cmd, -}; - -void lttng_ust_abi_exit(void) -{ - lttng_ust_abi_close_in_progress = 1; - objd_table_destroy(); - lttng_ust_abi_close_in_progress = 0; -}