struct lttng_event *ev, const char *channel_name);
/*
- * Apply a filter expression to an event.
+ * Create or enable an event with a specific filter.
*
- * If event is NULL, the filter is applied to all events of the channel.
- * If channel_name is NULL, a lookup of the event's channel is done.
- * If both are NULL, the filter is applied to all events of all channels.
+ * If the event you are trying to enable does not exist, it will be created,
+ * else it is enabled.
+ * If event_name is NULL, all events are enabled with that filter.
+ * If channel_name is NULL, the default channel is used (channel0) and created
+ * if not found.
*/
-extern int lttng_set_event_filter(struct lttng_handle *handle,
+extern int lttng_enable_event_with_filter(struct lttng_handle *handle,
struct lttng_event *event, const char *channel_name,
const char *filter_expression);
lttng-ust-ctl.h lttng-ust-abi.h \
fd-limit.c fd-limit.h \
kernel-consumer.c kernel-consumer.h \
- consumer.h filter.c filter.h \
+ consumer.h \
health.c health.h \
cmd.c cmd.h \
testpoint.h
return ret;
}
-/*
- * Command LTTNG_SET_FILTER processed by the client thread.
- */
-int cmd_set_filter(struct ltt_session *session, int domain,
- char *channel_name, struct lttng_event *event,
- struct lttng_filter_bytecode *bytecode)
-{
- int ret;
-
- switch (domain) {
- case LTTNG_DOMAIN_KERNEL:
- ret = LTTNG_ERR_FATAL;
- break;
- case LTTNG_DOMAIN_UST:
- {
- struct ltt_ust_session *usess = session->ust_session;
-
- ret = filter_ust_set(usess, domain, bytecode, event, channel_name);
- if (ret != LTTNG_OK) {
- goto error;
- }
- break;
- }
-#if 0
- case LTTNG_DOMAIN_UST_EXEC_NAME:
- case LTTNG_DOMAIN_UST_PID:
- case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
-#endif
- default:
- ret = LTTNG_ERR_UND;
- goto error;
- }
-
- ret = LTTNG_OK;
-
-error:
- return ret;
-
-}
-
-
/*
* Command LTTNG_ENABLE_EVENT processed by the client thread.
*/
int cmd_enable_event(struct ltt_session *session, int domain,
- char *channel_name, struct lttng_event *event, int wpipe)
+ char *channel_name, struct lttng_event *event,
+ struct lttng_filter_bytecode *filter, int wpipe)
{
int ret;
struct lttng_channel *attr;
}
/* At this point, the session and channel exist on the tracer */
- ret = event_ust_enable_tracepoint(usess, domain, uchan, event);
+ ret = event_ust_enable_tracepoint(usess, domain, uchan, event, filter);
if (ret != LTTNG_OK) {
goto error;
}
* Command LTTNG_ENABLE_ALL_EVENT processed by the client thread.
*/
int cmd_enable_event_all(struct ltt_session *session, int domain,
- char *channel_name, int event_type, int wpipe)
+ char *channel_name, int event_type,
+ struct lttng_filter_bytecode *filter, int wpipe)
{
int ret;
struct lttng_channel *attr;
switch (event_type) {
case LTTNG_EVENT_ALL:
case LTTNG_EVENT_TRACEPOINT:
- ret = event_ust_enable_all_tracepoints(usess, domain, uchan);
+ ret = event_ust_enable_all_tracepoints(usess, domain, uchan,
+ filter);
if (ret != LTTNG_OK) {
goto error;
}
#define CMD_H
#include "context.h"
-#include "filter.h"
#include "session.h"
/*
char *channel_name, struct lttng_event *event,
struct lttng_filter_bytecode *bytecode);
int cmd_enable_event(struct ltt_session *session, int domain,
- char *channel_name, struct lttng_event *event, int wpipe);
+ char *channel_name, struct lttng_event *event,
+ struct lttng_filter_bytecode *filter, int wpipe);
int cmd_enable_event_all(struct ltt_session *session, int domain,
- char *channel_name, int event_type, int wpipe);
+ char *channel_name, int event_type,
+ struct lttng_filter_bytecode *filter, int wpipe);
/* Trace session action commands */
int cmd_start_trace(struct ltt_session *session);
#include "trace-kernel.h"
#include "trace-ust.h"
+/*
+ * Add unique UST event based on the event name, filter bytecode and loglevel.
+ */
static void add_unique_ust_event(struct lttng_ht *ht,
struct ltt_ust_event *event)
{
event->type = LTTNG_EVENT_SYSCALL;
}
-/*
- * Return 1 if loglevels match or 0 on failure.
- */
-static int loglevel_match(struct ltt_ust_event *uevent,
- enum lttng_ust_loglevel_type log_type, int loglevel)
-{
- /*
- * For the loglevel type ALL, the loglevel is set to -1 but the event
- * received by the session daemon is 0 which does not match the negative
- * value in the existing event.
- */
- if (log_type == LTTNG_UST_LOGLEVEL_ALL) {
- loglevel = -1;
- }
-
- if (uevent == NULL || uevent->attr.loglevel_type != log_type ||
- uevent->attr.loglevel != loglevel) {
- goto no_match;
- }
-
- return 1;
-
-no_match:
- return 0;
-}
-
/*
* Disable kernel tracepoint event for a channel from the kernel session.
*/
* Enable all UST tracepoints for a channel from a UST session.
*/
int event_ust_enable_all_tracepoints(struct ltt_ust_session *usess, int domain,
- struct ltt_ust_channel *uchan)
+ struct ltt_ust_channel *uchan, struct lttng_filter_bytecode *filter)
{
int ret, i, size;
struct lttng_ht_iter iter;
struct ltt_ust_event *uevent = NULL;
struct lttng_event *events = NULL;
+ rcu_read_lock();
+
switch (domain) {
case LTTNG_DOMAIN_UST:
{
* Check if event exist and if so, continue since it was enable
* previously.
*/
- uevent = trace_ust_find_event(uchan->events, events[i].name, NULL,
+ uevent = trace_ust_find_event(uchan->events, events[i].name, filter,
events[i].loglevel);
if (uevent != NULL) {
ret = ust_app_enable_event_pid(usess, uchan, uevent,
}
/* Create ust event */
- uevent = trace_ust_create_event(&events[i]);
+ uevent = trace_ust_create_event(&events[i], filter);
if (uevent == NULL) {
ret = LTTNG_ERR_FATAL;
goto error_destroy;
goto error;
}
+ rcu_read_unlock();
return LTTNG_OK;
error_destroy:
error:
free(events);
+ rcu_read_unlock();
return ret;
}
* Enable UST tracepoint event for a channel from a UST session.
*/
int event_ust_enable_tracepoint(struct ltt_ust_session *usess, int domain,
- struct ltt_ust_channel *uchan, struct lttng_event *event)
+ struct ltt_ust_channel *uchan, struct lttng_event *event,
+ struct lttng_filter_bytecode *filter)
{
int ret = LTTNG_OK, to_create = 0;
struct ltt_ust_event *uevent;
- DBG3("Enable ust: %s l:%d f:%p", event->name, event->loglevel, NULL);
-
rcu_read_lock();
- uevent = trace_ust_find_event(uchan->events, event->name, NULL,
+ uevent = trace_ust_find_event(uchan->events, event->name, filter,
event->loglevel);
if (uevent == NULL) {
- uevent = trace_ust_create_event(event);
+ uevent = trace_ust_create_event(event, filter);
if (uevent == NULL) {
ret = LTTNG_ERR_UST_ENABLE_FAIL;
goto error;
}
+
/* Valid to set it after the goto error since uevent is still NULL */
to_create = 1;
}
- /* Check loglevels */
- ret = loglevel_match(uevent, event->loglevel_type, event->loglevel);
- if (ret == 0) {
- /*
- * No match meaning that the user tried to enable a known event but
- * with a different loglevel.
- */
- DBG("Enable event %s does not match existing event %s with loglevel "
- "respectively of %d and %d", event->name, uevent->attr.name,
- uevent->attr.loglevel, event->loglevel);
- ret = LTTNG_ERR_EVENT_EXIST_LOGLEVEL;
- goto error;
- }
-
if (uevent->enabled) {
/* It's already enabled so everything is OK */
ret = LTTNG_OK;
struct ltt_ust_event *uevent;
struct lttng_ht_node_str *node;
struct lttng_ht_iter iter;
- void *orig_match_fct;
struct lttng_ht *ht;
ht = uchan->events;
- /* Save match function so we can use the event by name match. */
- orig_match_fct = (void *) ht->match_fct;
- ht->match_fct = trace_ust_ht_match_event_by_name;
-
rcu_read_lock();
- lttng_ht_lookup(ht, (void *) event_name, &iter);
+
+ /*
+ * We use a custom lookup since we need the iterator for the next_duplicate
+ * call in the do while loop below.
+ */
+ cds_lfht_lookup(ht->ht, ht->hash_fct((void *) event_name, lttng_ht_seed),
+ trace_ust_ht_match_event_by_name, event_name, &iter.iter);
node = lttng_ht_iter_get_node_str(&iter);
if (node == NULL) {
DBG2("Trace UST event NOT found by name %s", event_name);
do {
uevent = caa_container_of(node, struct ltt_ust_event, node);
+ assert(uevent);
+
if (uevent->enabled == 0) {
/* It's already disabled so everything is OK */
ret = LTTNG_OK;
uevent->enabled = 0;
+ DBG2("Event UST %s disabled in channel %s", uevent->attr.name,
+ uchan->name);
+
/* Get next duplicate event by name. */
cds_lfht_next_duplicate(ht->ht, trace_ust_ht_match_event_by_name,
event_name, &iter.iter);
ret = LTTNG_OK;
- DBG2("Event UST %s disabled in channel %s", uevent->attr.name,
- uchan->name);
error:
- ht->match_fct = orig_match_fct;
rcu_read_unlock();
return ret;
}
struct ltt_ust_event *uevent = NULL;
struct lttng_event *events = NULL;
+ rcu_read_lock();
+
switch (domain) {
case LTTNG_DOMAIN_UST:
{
cds_lfht_for_each_entry(uchan->events->ht, &iter.iter, uevent,
node.node) {
if (uevent->enabled == 1) {
- ret = ust_app_disable_event_glb(usess, uchan, uevent);
+ ret = event_ust_disable_tracepoint(usess, domain, uchan,
+ uevent->attr.name);
if (ret < 0) {
continue;
}
- uevent->enabled = 0;
}
}
goto error;
}
+ rcu_read_unlock();
return LTTNG_OK;
error:
free(events);
+ rcu_read_unlock();
return ret;
}
struct ltt_kernel_channel *kchan, int kernel_tracer_fd);
int event_ust_enable_tracepoint(struct ltt_ust_session *usess, int domain,
- struct ltt_ust_channel *uchan, struct lttng_event *event);
+ struct ltt_ust_channel *uchan, struct lttng_event *event,
+ struct lttng_filter_bytecode *filter);
int event_ust_disable_tracepoint(struct ltt_ust_session *usess, int domain,
struct ltt_ust_channel *uchan, char *event_name);
int event_ust_enable_all_tracepoints(struct ltt_ust_session *usess, int domain,
- struct ltt_ust_channel *uchan);
+ struct ltt_ust_channel *uchan, struct lttng_filter_bytecode *filter);
int event_ust_disable_all_tracepoints(struct ltt_ust_session *usess, int domain,
struct ltt_ust_channel *uchan);
+++ /dev/null
-/*
- * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
- * Copyright (C) 2012 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2 only,
- * as published by the Free Software Foundation.
- *
- * 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <urcu/list.h>
-
-#include <common/error.h>
-#include <common/sessiond-comm/sessiond-comm.h>
-
-#include "filter.h"
-#include "kernel.h"
-#include "ust-app.h"
-#include "trace-ust.h"
-
-/*
- * Add UST context to event.
- */
-static int add_ufilter_to_event(struct ltt_ust_session *usess, int domain,
- struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent,
- struct lttng_filter_bytecode *bytecode)
-{
- int ret;
-
- if (uevent->filter) {
- ret = -EEXIST;
- goto error;
- }
- /* Same layout. */
- uevent->filter = (struct lttng_ust_filter_bytecode *) bytecode;
- uevent->filter->seqnum = usess->filter_seq_num;
-
- switch (domain) {
- case LTTNG_DOMAIN_UST:
- ret = ust_app_set_filter_event_glb(usess, uchan, uevent,
- bytecode);
- if (ret < 0) {
- goto error;
- }
- usess->filter_seq_num++;
- break;
- default:
- ret = -ENOSYS;
- goto error;
- }
-
- DBG("Filter UST added to event %s",uevent->attr.name);
-
- return 0;
-
-error:
- free(bytecode);
- return ret;
-}
-
-/*
- * Add UST context to tracer.
- */
-int filter_ust_set(struct ltt_ust_session *usess, int domain,
- struct lttng_filter_bytecode *bytecode, struct lttng_event *event,
- char *channel_name)
-{
- int ret = LTTNG_OK, have_event = 0;
- struct lttng_ht_iter iter;
- struct lttng_ht *chan_ht;
- struct ltt_ust_channel *uchan = NULL;
- struct ltt_ust_event *uevent = NULL;
-
- /*
- * Define which channel's hashtable to use from the domain or quit if
- * unknown domain.
- */
- switch (domain) {
- case LTTNG_DOMAIN_UST:
- chan_ht = usess->domain_global.channels;
- break;
-#if 0
- case LTTNG_DOMAIN_UST_EXEC_NAME:
- case LTTNG_DOMAIN_UST_PID:
- case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
-#endif
- default:
- ret = LTTNG_ERR_UND;
- goto error;
- }
-
- /* Do we have a valid event. */
- if (event && event->name[0] != '\0') {
- have_event = 1;
- }
-
- /* Get UST channel if defined */
- if (strlen(channel_name) != 0) {
- uchan = trace_ust_find_channel_by_name(chan_ht, channel_name);
- if (uchan == NULL) {
- ret = LTTNG_ERR_UST_CHAN_NOT_FOUND;
- goto error;
- }
- }
-
- /* If UST channel specified and event name, get UST event ref */
- if (uchan && have_event) {
- uevent = trace_ust_find_event(uchan->events, event->name, bytecode,
- event->loglevel);
- if (uevent == NULL) {
- ret = LTTNG_ERR_UST_EVENT_NOT_FOUND;
- goto error;
- }
- }
-
- /* At this point, we have 4 possibilities */
-
- if (uchan && uevent) { /* Add filter to event in channel */
- ret = add_ufilter_to_event(usess, domain, uchan, uevent,
- bytecode);
- } else if (uchan && !have_event) { /* Add filter to channel */
- ERR("Cannot add filter to channel");
- ret = LTTNG_ERR_FATAL; /* not supported. */
- goto error;
- } else if (!uchan && have_event) { /* Add filter to event */
- /* Add context to event without having the channel name */
- cds_lfht_for_each_entry(chan_ht->ht, &iter.iter, uchan, node.node) {
- uevent = trace_ust_find_event(uchan->events, event->name, bytecode,
- event->loglevel);
- if (uevent != NULL) {
- ret = add_ufilter_to_event(usess, domain, uchan, uevent, bytecode);
- /*
- * LTTng UST does not allowed the same event to be registered
- * multiple time in different or the same channel. So, if we
- * found our event, we stop.
- */
- goto end;
- }
- }
- ret = LTTNG_ERR_UST_EVENT_NOT_FOUND;
- goto error;
- } else if (!uchan && !have_event) { /* Add filter all events, all channels */
- ERR("Cannot add filter to channel");
- ret = LTTNG_ERR_FATAL; /* not supported. */
- goto error;
- }
-
-end:
- /* Must handle both local internal error and UST code. */
- switch (ret) {
- case -EEXIST:
- case -LTTNG_UST_ERR_EXIST:
- ret = LTTNG_ERR_FILTER_EXIST;
- break;
- case -ENOMEM:
- ret = LTTNG_ERR_FATAL;
- break;
- case -EINVAL:
- case -LTTNG_UST_ERR_INVAL:
- ret = LTTNG_ERR_FILTER_INVAL;
- break;
- case -ENOSYS:
- case -LTTNG_UST_ERR_NOSYS:
- ret = LTTNG_ERR_UNKNOWN_DOMAIN;
- break;
- default:
- ret = LTTNG_OK;
- break;
- }
-
-error:
- return ret;
-}
+++ /dev/null
-/*
- * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
- * Copyright (C) 2012 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License, version 2 only,
- * as published by the Free Software Foundation.
- *
- * 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef _LTT_FILTER_H
-#define _LTT_FILTER_H
-
-#include <lttng/lttng.h>
-
-#include "trace-kernel.h"
-#include "trace-ust.h"
-#include "ust-ctl.h"
-
-struct lttng_filter_bytecode;
-
-int filter_ust_set(struct ltt_ust_session *usess, int domain,
- struct lttng_filter_bytecode *bytecode, struct lttng_event *event,
- char *channel_name);
-
-#endif /* _LTT_FILTER_H */
#include "ust-consumer.h"
#include "utils.h"
#include "fd-limit.h"
-#include "filter.h"
#include "health.h"
#include "testpoint.h"
{
ret = cmd_enable_event(cmd_ctx->session, cmd_ctx->lsm->domain.type,
cmd_ctx->lsm->u.enable.channel_name,
- &cmd_ctx->lsm->u.enable.event, kernel_poll_pipe[1]);
+ &cmd_ctx->lsm->u.enable.event, NULL, kernel_poll_pipe[1]);
break;
}
case LTTNG_ENABLE_ALL_EVENT:
ret = cmd_enable_event_all(cmd_ctx->session, cmd_ctx->lsm->domain.type,
cmd_ctx->lsm->u.enable.channel_name,
- cmd_ctx->lsm->u.enable.event.type, kernel_poll_pipe[1]);
+ cmd_ctx->lsm->u.enable.event.type, NULL, kernel_poll_pipe[1]);
break;
}
case LTTNG_LIST_TRACEPOINTS:
cmd_ctx->lsm->u.reg.path, cdata);
break;
}
- case LTTNG_SET_FILTER:
+ case LTTNG_ENABLE_EVENT_WITH_FILTER:
{
struct lttng_filter_bytecode *bytecode;
- if (cmd_ctx->lsm->u.filter.bytecode_len > LTTNG_FILTER_MAX_LEN) {
+ if (cmd_ctx->lsm->u.enable.bytecode_len > LTTNG_FILTER_MAX_LEN) {
ret = LTTNG_ERR_FILTER_INVAL;
goto error;
}
- bytecode = zmalloc(cmd_ctx->lsm->u.filter.bytecode_len);
+ bytecode = zmalloc(cmd_ctx->lsm->u.enable.bytecode_len);
if (!bytecode) {
ret = LTTNG_ERR_FILTER_NOMEM;
goto error;
/* Receive var. len. data */
DBG("Receiving var len data from client ...");
ret = lttcomm_recv_unix_sock(sock, bytecode,
- cmd_ctx->lsm->u.filter.bytecode_len);
+ cmd_ctx->lsm->u.enable.bytecode_len);
if (ret <= 0) {
DBG("Nothing recv() from client var len data... continuing");
*sock_error = 1;
}
if (bytecode->len + sizeof(*bytecode)
- != cmd_ctx->lsm->u.filter.bytecode_len) {
+ != cmd_ctx->lsm->u.enable.bytecode_len) {
free(bytecode);
ret = LTTNG_ERR_FILTER_INVAL;
goto error;
}
- ret = cmd_set_filter(cmd_ctx->session, cmd_ctx->lsm->domain.type,
- cmd_ctx->lsm->u.filter.channel_name,
- &cmd_ctx->lsm->u.filter.event,
- bytecode);
+ ret = cmd_enable_event(cmd_ctx->session, cmd_ctx->lsm->domain.type,
+ cmd_ctx->lsm->u.enable.channel_name,
+ &cmd_ctx->lsm->u.enable.event, bytecode, kernel_poll_pipe[1]);
break;
}
case LTTNG_DATA_PENDING:
#include "trace-ust.h"
+/*
+ * Match function for the events hash table lookup.
+ *
+ * Matches by name only. Used by the disable command.
+ */
int trace_ust_ht_match_event_by_name(struct cds_lfht_node *node,
const void *_key)
{
goto no_match;
}
- /* Match. */
+ /* Match */
return 1;
no_match:
return 0;
}
+/*
+ * Match function for the hash table lookup.
+ *
+ * It matches an ust event based on three attributes which are the event name,
+ * the filter bytecode and the loglevel.
+ */
int trace_ust_ht_match_event(struct cds_lfht_node *node, const void *_key)
{
struct ltt_ust_event *event;
/* Event name */
if (strncmp(event->attr.name, key->name, sizeof(event->attr.name)) != 0) {
- DBG3("[Match] name failed: %s and %s",
- event->attr.name, key->name);
goto no_match;
}
/* Event loglevel. */
if (event->attr.loglevel != key->loglevel) {
- if (event->attr.loglevel_type == 0 && key->loglevel == 0 &&
- event->attr.loglevel == -1) {
+ if (event->attr.loglevel_type == LTTNG_UST_LOGLEVEL_ALL
+ && key->loglevel == 0 && event->attr.loglevel == -1) {
/*
- * This is because on event creation, the loglevel is set to -1 if
- * the event loglevel type is ALL so 0 and -1 are accepted for this
- * loglevel type.
+ * Match is accepted. This is because on event creation, the
+ * loglevel is set to -1 if the event loglevel type is ALL so 0 and
+ * -1 are accepted for this loglevel type since 0 is the one set by
+ * the API when receiving an enable event.
*/
} else {
- DBG3("[Match] loglevel failed: %d and %d",
- event->attr.loglevel, key->loglevel);
goto no_match;
}
}
/* Only one of the filters is NULL, fail. */
if ((key->filter && !event->filter) || (!key->filter && event->filter)) {
- DBG3("[Match] filters failed: k:%p and e:%p",
- key->filter, event->filter);
goto no_match;
}
- /* Both filters are NULL, success. */
- if (!key->filter && !event->filter) {
- goto match;
- }
-
- /* Both filters exists, check length followed by the bytecode. */
- if (event->filter->len == key->filter->len &&
- memcmp(event->filter->data, key->filter->data,
- event->filter->len) == 0) {
- goto match;
+ if (key->filter && event->filter) {
+ /* Both filters exists, check length followed by the bytecode. */
+ if (event->filter->len != key->filter->len ||
+ memcmp(event->filter->data, key->filter->data,
+ event->filter->len) != 0) {
+ goto no_match;
+ }
}
- DBG3("[Match] filters failed: k:%p and e:%p",
- key->filter, event->filter);
+ /* Match. */
+ return 1;
no_match:
return 0;
-
-match:
- DBG3("[MATCH] %s", key->name);
- return 1;
}
/*
struct lttng_ht_node_str *node;
struct lttng_ht_iter iter;
struct ltt_ust_ht_key key;
- void *orig_match_fct;
assert(name);
assert(ht);
key.filter = filter;
key.loglevel = loglevel;
- /* Save match function so we can use the ust app event match. */
- orig_match_fct = (void *) ht->match_fct;
- ht->match_fct = trace_ust_ht_match_event;
-
cds_lfht_lookup(ht->ht, ht->hash_fct((void *) name, lttng_ht_seed),
trace_ust_ht_match_event, &key, &iter.iter);
node = lttng_ht_iter_get_node_str(&iter);
error:
DBG2("Trace UST event %s NOT found", key.name);
- /* Put back original match function. */
- ht->match_fct = orig_match_fct;
return NULL;
}
*
* Return pointer to structure or NULL.
*/
-struct ltt_ust_event *trace_ust_create_event(struct lttng_event *ev)
+struct ltt_ust_event *trace_ust_create_event(struct lttng_event *ev,
+ struct lttng_filter_bytecode *filter)
{
struct ltt_ust_event *lue;
goto error_free_event;
}
+ /* Same layout. */
+ lue->filter = (struct lttng_ust_filter_bytecode *) filter;
/* Init node */
lttng_ht_node_init_str(&lue->node, lue->attr.name);
unsigned int session_id, struct lttng_domain *domain);
struct ltt_ust_channel *trace_ust_create_channel(struct lttng_channel *attr,
char *path);
-struct ltt_ust_event *trace_ust_create_event(struct lttng_event *ev);
+struct ltt_ust_event *trace_ust_create_event(struct lttng_event *ev,
+ struct lttng_filter_bytecode *filter);
struct ltt_ust_metadata *trace_ust_create_metadata(char *path);
struct ltt_ust_context *trace_ust_create_context(
struct lttng_event_context *ctx);
return NULL;
}
static inline
-struct ltt_ust_event *trace_ust_create_event(struct lttng_event *ev)
+struct ltt_ust_event *trace_ust_create_event(struct lttng_event *ev,
+ struct lttng_filter_bytecode *filter)
{
return NULL;
}
#include "ust-consumer.h"
#include "ust-ctl.h"
+/*
+ * Match function for the hash table lookup.
+ *
+ * It matches an ust app event based on three attributes which are the event
+ * name, the filter bytecode and the loglevel.
+ */
static int ht_match_ust_app_event(struct cds_lfht_node *node, const void *_key)
{
struct ust_app_event *event;
/* Event loglevel. */
if (event->attr.loglevel != key->loglevel) {
- goto no_match;
+ if (event->attr.loglevel_type == LTTNG_UST_LOGLEVEL_ALL
+ && key->loglevel == 0 && event->attr.loglevel == -1) {
+ /*
+ * Match is accepted. This is because on event creation, the
+ * loglevel is set to -1 if the event loglevel type is ALL so 0 and
+ * -1 are accepted for this loglevel type since 0 is the one set by
+ * the API when receiving an enable event.
+ */
+ } else {
+ goto no_match;
+ }
}
/* One of the filters is NULL, fail. */
goto no_match;
}
- /* Both filters are NULL, success. */
- if (!key->filter && !event->filter) {
- goto match;
- }
-
- /* Both filters exists, check length followed by the bytecode. */
- if (event->filter->len == key->filter->len &&
- memcmp(event->filter->data, key->filter->data,
- event->filter->len) == 0) {
- goto match;
+ if (key->filter && event->filter) {
+ /* Both filters exists, check length followed by the bytecode. */
+ if (event->filter->len != key->filter->len ||
+ memcmp(event->filter->data, key->filter->data,
+ event->filter->len) != 0) {
+ goto no_match;
+ }
}
-match:
+ /* Match. */
return 1;
no_match:
return 0;
-
}
+/*
+ * Unique add of an ust app event in the given ht. This uses the custom
+ * ht_match_ust_app_event match function and the event name as hash.
+ */
static void add_unique_ust_app_event(struct lttng_ht *ht,
struct ust_app_event *event)
{
return ua_ctx;
}
+/*
+ * Allocate a filter and copy the given original filter.
+ *
+ * Return allocated filter or NULL on error.
+ */
+static struct lttng_ust_filter_bytecode *alloc_copy_ust_app_filter(
+ struct lttng_ust_filter_bytecode *orig_f)
+{
+ struct lttng_ust_filter_bytecode *filter = NULL;
+
+ /* Copy filter bytecode */
+ filter = zmalloc(sizeof(*filter) + orig_f->len);
+ if (!filter) {
+ PERROR("zmalloc alloc ust app filter");
+ goto error;
+ }
+
+ memcpy(filter, orig_f, sizeof(*filter) + orig_f->len);
+
+error:
+ return filter;
+}
+
/*
* Find an ust_app using the sock and return it. RCU read side lock must be
* held before calling this helper function.
return NULL;
}
+/*
+ * Lookup for an ust app event based on event name, filter bytecode and the
+ * event loglevel.
+ *
+ * Return an ust_app_event object or NULL on error.
+ */
static struct ust_app_event *find_ust_app_event(struct lttng_ht *ht,
char *name, struct lttng_ust_filter_bytecode *filter, int loglevel)
{
struct lttng_ht_node_str *node;
struct ust_app_event *event = NULL;
struct ust_app_ht_key key;
- void *orig_match_fct;
assert(name);
assert(ht);
key.filter = filter;
key.loglevel = loglevel;
- /* Save match function so we can use the ust app event match. */
- orig_match_fct = (void *) ht->match_fct;
- ht->match_fct = ht_match_ust_app_event;
-
- lttng_ht_lookup(ht, (void *) &key, &iter);
+ /* Lookup using the event name as hash and a custom match fct. */
+ cds_lfht_lookup(ht->ht, ht->hash_fct((void *) name, lttng_ht_seed),
+ ht_match_ust_app_event, &key, &iter.iter);
node = lttng_ht_iter_get_node_str(&iter);
if (node == NULL) {
goto end;
event = caa_container_of(node, struct ust_app_event, node);
end:
- /* Put back original match function. */
- ht->match_fct = orig_match_fct;
return event;
}
health_code_update(&health_thread_cmd);
+ /* Set filter if one is present. */
+ if (ua_event->filter) {
+ ret = set_ust_event_filter(ua_event, app);
+ if (ret < 0) {
+ goto error;
+ }
+ }
+
/* If event not enabled, disable it on the tracer */
if (ua_event->enabled == 0) {
ret = disable_ust_event(app, ua_sess, ua_event);
/* Copy filter bytecode */
if (uevent->filter) {
- ua_event->filter = zmalloc(sizeof(*ua_event->filter) +
- uevent->filter->len);
- if (!ua_event->filter) {
- return;
- }
- memcpy(ua_event->filter, uevent->filter,
- sizeof(*ua_event->filter) + uevent->filter->len);
+ ua_event->filter = alloc_copy_ust_app_filter(uevent->filter);
+ /* Filter might be NULL here in case of ENONEM. */
}
}
return ret;
}
-/*
- * Set UST filter for the event on the tracer.
- */
-static
-int set_ust_app_event_filter(struct ust_app_session *ua_sess,
- struct ust_app_event *ua_event,
- struct lttng_filter_bytecode *bytecode,
- struct ust_app *app)
-{
- int ret = 0;
-
- DBG2("UST app adding context to event %s", ua_event->name);
-
- /* Copy filter bytecode */
- ua_event->filter = zmalloc(sizeof(*ua_event->filter) + bytecode->len);
- if (!ua_event->filter) {
- return -ENOMEM;
- }
- memcpy(ua_event->filter, bytecode,
- sizeof(*ua_event->filter) + bytecode->len);
- ret = set_ust_event_filter(ua_event, app);
- if (ret < 0) {
- goto error;
- }
-
-error:
- return ret;
-}
-
/*
* Enable on the tracer side a ust app event for the session and channel.
*/
return ret;
}
-/*
- * Add context to a specific event in a channel for global UST domain.
- */
-int ust_app_set_filter_event_glb(struct ltt_ust_session *usess,
- struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent,
- struct lttng_filter_bytecode *bytecode)
-{
- int ret = 0;
- struct lttng_ht_node_str *ua_chan_node;
- struct lttng_ht_iter iter, uiter;
- struct ust_app_session *ua_sess;
- struct ust_app_event *ua_event;
- struct ust_app_channel *ua_chan = NULL;
- struct ust_app *app;
-
- rcu_read_lock();
-
- cds_lfht_for_each_entry(ust_app_ht->ht, &iter.iter, app, pid_n.node) {
- if (!app->compatible) {
- /*
- * TODO: In time, we should notice the caller of this error by
- * telling him that this is a version error.
- */
- continue;
- }
- ua_sess = lookup_session_by_app(usess, app);
- if (ua_sess == NULL) {
- continue;
- }
-
- /* Lookup channel in the ust app session */
- lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &uiter);
- ua_chan_node = lttng_ht_iter_get_node_str(&uiter);
- if (ua_chan_node == NULL) {
- continue;
- }
- ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel,
- node);
-
- ua_event = find_ust_app_event(ua_chan->events, uevent->attr.name,
- (struct lttng_ust_filter_bytecode *) bytecode,
- uevent->attr.loglevel);
- if (ua_event == NULL) {
- continue;
- }
-
- ret = set_ust_app_event_filter(ua_sess, ua_event, bytecode, app);
- if (ret < 0) {
- continue;
- }
- }
-
- rcu_read_unlock();
- return ret;
-}
-
/*
* Enable event for a channel from a UST session for a specific PID.
*/
struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent);
int ust_app_add_ctx_channel_glb(struct ltt_ust_session *usess,
struct ltt_ust_channel *uchan, struct ltt_ust_context *uctx);
-int ust_app_set_filter_event_glb(struct ltt_ust_session *usess,
- struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent,
- struct lttng_filter_bytecode *bytecode);
void ust_app_global_update(struct ltt_ust_session *usess, int sock);
void ust_app_clean_list(void);
{
return 0;
}
-static inline
-int ust_app_set_filter_event_glb(struct ltt_ust_session *usess,
- struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent,
- struct lttng_filter_bytecode *bytecode)
-{
- return 0;
-}
#endif /* HAVE_LIBLTTNG_UST_CTL */
static int enable_events(char *session_name)
{
int err, ret = CMD_SUCCESS, warn = 0;
- unsigned int event_enabled = 0;
char *event_name, *channel_name = NULL;
struct lttng_event ev;
struct lttng_domain dom;
}
}
- /* Reset flag before enabling a new event. */
- event_enabled = 0;
-
- ret = lttng_enable_event(handle, &ev, channel_name);
- if (ret < 0) {
- switch (-ret) {
- case LTTNG_ERR_KERN_EVENT_EXIST:
- WARN("Kernel events already enabled (channel %s, session %s)",
- channel_name, session_name);
- break;
- default:
- ERR("Events: %s (channel %s, session %s)",
- lttng_strerror(ret), channel_name, session_name);
- break;
+ if (!opt_filter) {
+ ret = lttng_enable_event(handle, &ev, channel_name);
+ if (ret < 0) {
+ switch (-ret) {
+ case LTTNG_ERR_KERN_EVENT_EXIST:
+ WARN("Kernel events already enabled (channel %s, session %s)",
+ channel_name, session_name);
+ break;
+ default:
+ ERR("Events: %s (channel %s, session %s)",
+ lttng_strerror(ret), channel_name, session_name);
+ break;
+ }
+ goto end;
}
- goto end;
- }
- event_enabled = 1;
- switch (opt_event_type) {
- case LTTNG_EVENT_TRACEPOINT:
- if (opt_loglevel) {
- MSG("All %s tracepoints are enabled in channel %s for loglevel %s",
- opt_kernel ? "kernel" : "UST", channel_name,
- opt_loglevel);
- } else {
- MSG("All %s tracepoints are enabled in channel %s",
- opt_kernel ? "kernel" : "UST", channel_name);
+ switch (opt_event_type) {
+ case LTTNG_EVENT_TRACEPOINT:
+ if (opt_loglevel) {
+ MSG("All %s tracepoints are enabled in channel %s for loglevel %s",
+ opt_kernel ? "kernel" : "UST", channel_name,
+ opt_loglevel);
+ } else {
+ MSG("All %s tracepoints are enabled in channel %s",
+ opt_kernel ? "kernel" : "UST", channel_name);
+ }
+ break;
+ case LTTNG_EVENT_SYSCALL:
+ if (opt_kernel) {
+ MSG("All kernel system calls are enabled in channel %s",
+ channel_name);
+ }
+ break;
+ case LTTNG_EVENT_ALL:
+ if (opt_loglevel) {
+ MSG("All %s events are enabled in channel %s for loglevel %s",
+ opt_kernel ? "kernel" : "UST", channel_name,
+ opt_loglevel);
+ } else {
+ 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 have
+ * failed on the event type.
+ */
+ goto error;
}
- break;
- case LTTNG_EVENT_SYSCALL:
- if (opt_kernel) {
- MSG("All kernel system calls are enabled in channel %s",
- channel_name);
- }
- break;
- case LTTNG_EVENT_ALL:
- if (opt_loglevel) {
- MSG("All %s events are enabled in channel %s for loglevel %s",
- opt_kernel ? "kernel" : "UST", channel_name,
- opt_loglevel);
- } else {
- 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 have
- * failed on the event type.
- */
- goto error;
}
- if (opt_filter && event_enabled) {
- ret = lttng_set_event_filter(handle, &ev, channel_name,
+ if (opt_filter) {
+ ret = lttng_enable_event_with_filter(handle, &ev, channel_name,
opt_filter);
if (ret < 0) {
fprintf(stderr, "Ret filter: %d\n", ret);
ERR("%s", lttng_strerror(ret));
default:
ERR("Setting filter: '%s'", opt_filter);
- /*
- * The event was successfully enabled before so when
- * failing to set a filter, disable the event. This has
- * been discussed in bug #343 on why we do that.
- */
- err = lttng_disable_event(handle, ev.name, channel_name);
- if (err < 0) {
- ERR("Disabling all events after filter error: %s",
- lttng_strerror(err));
- } else {
- WARN("All events of channel %s have been disabled due "
- "to a filter error", channel_name);
- }
break;
}
goto error;
goto error;
}
- /* Reset flag before enabling a new event. */
- event_enabled = 0;
-
- ret = lttng_enable_event(handle, &ev, channel_name);
- if (ret < 0) {
- /* Turn ret to positive value to handle the positive error code */
- switch (-ret) {
- case LTTNG_ERR_KERN_EVENT_EXIST:
- WARN("Kernel event %s already enabled (channel %s, session %s)",
- event_name, channel_name, session_name);
- break;
- default:
- ERR("Event %s: %s (channel %s, session %s)", event_name,
- lttng_strerror(ret), channel_name, session_name);
- break;
+ if (!opt_filter) {
+ ret = lttng_enable_event(handle, &ev, channel_name);
+ if (ret < 0) {
+ /* Turn ret to positive value to handle the positive error code */
+ switch (-ret) {
+ case LTTNG_ERR_KERN_EVENT_EXIST:
+ WARN("Kernel event %s already enabled (channel %s, session %s)",
+ event_name, channel_name, session_name);
+ break;
+ default:
+ ERR("Event %s: %s (channel %s, session %s)", event_name,
+ lttng_strerror(ret), channel_name, session_name);
+ break;
+ }
+ warn = 1;
+ } else {
+ MSG("%s event %s created in channel %s",
+ opt_kernel ? "kernel": "UST", event_name, channel_name);
}
- warn = 1;
- } else {
- MSG("%s event %s created in channel %s",
- opt_kernel ? "kernel": "UST", event_name, channel_name);
- event_enabled = 1;
}
- if (opt_filter && event_enabled) {
- ret = lttng_set_event_filter(handle, &ev, channel_name,
+
+ if (opt_filter) {
+ ret = lttng_enable_event_with_filter(handle, &ev, channel_name,
opt_filter);
if (ret < 0) {
switch (-ret) {
default:
ERR("Setting filter for event %s: '%s'", ev.name,
opt_filter);
- /*
- * The event was successfully enabled before so when
- * failing to set a filter, disable the event. This has
- * been discussed in bug #343 on why we do that.
- */
- err = lttng_disable_event(handle, ev.name, channel_name);
- if (err < 0) {
- ERR("Disabling event %s after filter error: %s",
- ev.name, lttng_strerror(err));
- } else {
- WARN("Event %s of channel %s has been disabled due "
- "to a filter error", ev.name, channel_name);
- }
break;
}
goto error;
RELAYD_CLOSE_STREAM,
RELAYD_DATA_PENDING,
RELAYD_QUIESCENT_CONTROL,
- LTTNG_SET_FILTER,
+ LTTNG_ENABLE_EVENT_WITH_FILTER,
LTTNG_HEALTH_CHECK,
LTTNG_DATA_PENDING,
};
struct {
char channel_name[LTTNG_SYMBOL_NAME_LEN];
struct lttng_event event;
+ /* Length of following bytecode for filter. */
+ uint32_t bytecode_len;
} enable;
/* Create channel */
struct {
/* Number of lttng_uri following */
uint32_t size;
} uri;
- struct {
- char channel_name[LTTNG_SYMBOL_NAME_LEN];
- struct lttng_event event;
- /* Length of following bytecode */
- uint32_t bytecode_len;
- } filter;
} u;
};
}
/*
- * Set filter for an event
+ * Create or enable an event with a filter expression.
*
* Return negative error value on error.
* Return size of returned session payload data if OK.
*/
-int lttng_set_event_filter(struct lttng_handle *handle,
+int lttng_enable_event_with_filter(struct lttng_handle *handle,
struct lttng_event *event, const char *channel_name,
const char *filter_expression)
{
int ret = 0;
/* Safety check. */
- if (handle == NULL) {
+ if (handle == NULL || !filter_expression) {
return -LTTNG_ERR_INVALID;
}
- if (!filter_expression) {
- return 0;
- }
-
/*
* casting const to non-const, as the underlying function will
* use it in read-only mode.
memset(&lsm, 0, sizeof(lsm));
- lsm.cmd_type = LTTNG_SET_FILTER;
+ lsm.cmd_type = LTTNG_ENABLE_EVENT_WITH_FILTER;
/* Copy channel name */
- copy_string(lsm.u.filter.channel_name, channel_name,
- sizeof(lsm.u.filter.channel_name));
+ copy_string(lsm.u.enable.channel_name, channel_name,
+ sizeof(lsm.u.enable.channel_name));
/* Copy event name */
if (event) {
memcpy(&lsm.u.enable.event, event, sizeof(lsm.u.enable.event));
}
- lsm.u.filter.bytecode_len = sizeof(ctx->bytecode->b)
+ lsm.u.enable.bytecode_len = sizeof(ctx->bytecode->b)
+ bytecode_get_len(&ctx->bytecode->b);
copy_lttng_domain(&lsm.domain, &handle->domain);
sizeof(lsm.session.name));
ret = ask_sessiond_varlen(&lsm, &ctx->bytecode->b,
- lsm.u.filter.bytecode_len, NULL);
+ lsm.u.enable.bytecode_len, NULL);
filter_bytecode_free(ctx);
filter_ir_free(ctx);
ev.loglevel_type = LTTNG_EVENT_LOGLEVEL_ALL;
printf("Creating UST event: ");
- event = trace_ust_create_event(&ev);
+ event = trace_ust_create_event(&ev, NULL);
assert(event != NULL);
PRINT_OK();