if (ua_chan->obj != NULL) {
/* Remove channel from application UST object descriptor. */
iter.iter.node = &ua_chan->ust_objd_node.node;
- lttng_ht_del(app->ust_objd, &iter);
+ ret = lttng_ht_del(app->ust_objd, &iter);
+ assert(!ret);
ret = ustctl_release_object(sock, ua_chan->obj);
if (ret < 0 && ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) {
ERR("UST app sock %d release channel obj failed with ret %d",
ret = consumer_push_metadata(socket, registry->metadata_key,
metadata_str, len, offset);
if (ret < 0) {
+ /*
+ * There is an acceptable race here between the registry metadata key
+ * assignment and the creation on the consumer. The session daemon can
+ * concurrently push metadata for this registry while being created on
+ * the consumer since the metadata key of the registry is assigned
+ * *before* it is setup to avoid the consumer to ask for metadata that
+ * could possibly be not found in the session daemon.
+ *
+ * The metadata will get pushed either by the session being stopped or
+ * the consumer requesting metadata if that race is triggered.
+ */
+ if (ret == -LTTCOMM_CONSUMERD_CHANNEL_FAIL) {
+ ret = 0;
+ }
+
+ /* Update back the actual metadata len sent since it failed here. */
+ pthread_mutex_lock(®istry->lock);
+ registry->metadata_len_sent -= len;
+ pthread_mutex_unlock(®istry->lock);
ret_val = ret;
goto error_push;
}
* 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)
+ char *name, struct lttng_ust_filter_bytecode *filter, int loglevel,
+ const struct lttng_event_exclusion *exclusion)
{
struct lttng_ht_iter iter;
struct lttng_ht_node_str *node;
key.name = name;
key.filter = filter;
key.loglevel = loglevel;
+ /* lttng_event_exclusion and lttng_ust_event_exclusion structures are similar */
+ key.exclusion = (struct lttng_ust_event_exclusion *)exclusion;
/* 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),
return ret;
}
+/*
+ * Set event exclusions on the tracer.
+ */
+static
+int set_ust_event_exclusion(struct ust_app_event *ua_event,
+ struct ust_app *app)
+{
+ int ret;
+
+ health_code_update();
+
+ if (!ua_event->exclusion || !ua_event->exclusion->count) {
+ ret = 0;
+ goto error;
+ }
+
+ ret = ustctl_set_exclusion(app->sock, ua_event->exclusion,
+ ua_event->obj);
+ if (ret < 0) {
+ if (ret != -EPIPE && ret != -LTTNG_UST_ERR_EXITING) {
+ ERR("UST app event %s exclusions failed for app (pid: %d) "
+ "with ret %d", ua_event->attr.name, app->pid, ret);
+ } else {
+ /*
+ * This is normal behavior, an application can die during the
+ * creation process. Don't report an error so the execution can
+ * continue normally.
+ */
+ ret = 0;
+ DBG3("UST app event exclusion failed. Application is dead.");
+ }
+ goto error;
+ }
+
+ DBG2("UST exclusion set successfully for event %s", ua_event->name);
+
+error:
+ health_code_update();
+ return ret;
+}
+
/*
* Disable the specified event on to UST tracer for the UST session.
*/
}
}
+ /* Set exclusions for the event */
+ if (ua_event->exclusion) {
+ ret = set_ust_event_exclusion(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);
static void shadow_copy_event(struct ust_app_event *ua_event,
struct ltt_ust_event *uevent)
{
+ size_t exclusion_alloc_size;
+
strncpy(ua_event->name, uevent->attr.name, sizeof(ua_event->name));
ua_event->name[sizeof(ua_event->name) - 1] = '\0';
ua_event->filter = alloc_copy_ust_app_filter(uevent->filter);
/* Filter might be NULL here in case of ENONEM. */
}
+
+ /* Copy exclusion data */
+ if (uevent->exclusion) {
+ exclusion_alloc_size = sizeof(struct lttng_ust_event_exclusion) +
+ LTTNG_UST_SYM_NAME_LEN * uevent->exclusion->count;
+ ua_event->exclusion = zmalloc(exclusion_alloc_size);
+ if (ua_event->exclusion == NULL) {
+ PERROR("malloc");
+ } else {
+ memcpy(ua_event->exclusion, uevent->exclusion,
+ exclusion_alloc_size);
+ }
+ }
}
/*
/* Copy all events from ltt ust channel to ust app channel */
cds_lfht_for_each_entry(uchan->events->ht, &iter.iter, uevent, node.node) {
ua_event = find_ust_app_event(ua_chan->events, uevent->attr.name,
- uevent->filter, uevent->attr.loglevel);
+ uevent->filter, uevent->attr.loglevel, uevent->exclusion);
if (ua_event == NULL) {
DBG2("UST event %s not found on shadow copy channel",
uevent->attr.name);
/* Get event node */
ua_event = find_ust_app_event(ua_chan->events, uevent->attr.name,
- uevent->filter, uevent->attr.loglevel);
+ uevent->filter, uevent->attr.loglevel, uevent->exclusion);
if (ua_event != NULL) {
ret = -EEXIST;
goto end;
return ret;
}
-/*
- * Return pointer to traceable apps list.
- */
-struct lttng_ht *ust_app_get_ht(void)
-{
- return ust_app_ht;
-}
-
/*
* Return ust app pointer or NULL if not found. RCU read side lock MUST be
* acquired before calling this function.
return;
}
-/*
- * Return traceable_app_count
- */
-unsigned long ust_app_list_count(void)
-{
- unsigned long count;
-
- rcu_read_lock();
- count = lttng_ht_get_count(ust_app_ht);
- rcu_read_unlock();
-
- return count;
-}
-
/*
* Fill events array with all events name of all registered apps.
*/
&uiter)) != -LTTNG_UST_ERR_NOENT) {
/* Handle ustctl error. */
if (ret < 0) {
- free(tmp_event);
- if (ret != -LTTNG_UST_ERR_EXITING || ret != -EPIPE) {
+ if (ret != -LTTNG_UST_ERR_EXITING && ret != -EPIPE) {
ERR("UST app tp list get failed for app %d with ret %d",
app->sock, ret);
} else {
*/
break;
}
+ free(tmp_event);
goto rcu_error;
}
&uiter)) != -LTTNG_UST_ERR_NOENT) {
/* Handle ustctl error. */
if (ret < 0) {
- free(tmp_event);
- if (ret != -LTTNG_UST_ERR_EXITING || ret != -EPIPE) {
+ if (ret != -LTTNG_UST_ERR_EXITING && ret != -EPIPE) {
ERR("UST app tp list field failed for app %d with ret %d",
app->sock, ret);
} else {
/*
* This is normal behavior, an application can die during the
* creation process. Don't report an error so the execution can
- * continue normally.
+ * continue normally. Reset list and count for next app.
*/
break;
}
+ free(tmp_event);
goto rcu_error;
}
}
memcpy(tmp_event[count].field_name, uiter.field_name, LTTNG_UST_SYM_NAME_LEN);
- tmp_event[count].type = uiter.type;
+ /* Mapping between these enums matches 1 to 1. */
+ tmp_event[count].type = (enum lttng_event_field_type) uiter.type;
tmp_event[count].nowrite = uiter.nowrite;
memcpy(tmp_event[count].event.name, uiter.event_name, LTTNG_UST_SYM_NAME_LEN);
tmp_event[count].event.loglevel = uiter.loglevel;
- tmp_event[count].event.type = LTTNG_UST_TRACEPOINT;
+ tmp_event[count].event.type = LTTNG_EVENT_TRACEPOINT;
tmp_event[count].event.pid = app->pid;
tmp_event[count].event.enabled = -1;
count++;
return ret;
}
-/*
- * For a specific UST session and UST channel, the event for all
- * registered apps.
- */
-int ust_app_disable_all_event_glb(struct ltt_ust_session *usess,
- struct ltt_ust_channel *uchan)
-{
- int ret = 0;
- struct lttng_ht_iter iter, uiter;
- struct lttng_ht_node_str *ua_chan_node;
- struct ust_app *app;
- struct ust_app_session *ua_sess;
- struct ust_app_channel *ua_chan;
- struct ust_app_event *ua_event;
-
- DBG("UST app disabling all event for all apps in channel "
- "%s for session id %" PRIu64, uchan->name, usess->id);
-
- rcu_read_lock();
-
- /* For all registered applications */
- 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) {
- /* The application has problem or is probably dead. */
- 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 the channel is not found, there is a code flow error */
- assert(ua_chan_node);
-
- ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node);
-
- /* Disable each events of channel */
- cds_lfht_for_each_entry(ua_chan->events->ht, &uiter.iter, ua_event,
- node.node) {
- ret = disable_ust_app_event(ua_sess, ua_event, app);
- if (ret < 0) {
- /* XXX: Report error someday... */
- continue;
- }
- }
- }
-
- rcu_read_unlock();
-
- return ret;
-}
-
/*
* For a specific UST session, create the channel for all registered apps.
*/
/* Get event node */
ua_event = find_ust_app_event(ua_chan->events, uevent->attr.name,
- uevent->filter, uevent->attr.loglevel);
+ uevent->filter, uevent->attr.loglevel, uevent->exclusion);
if (ua_event == NULL) {
DBG3("UST app enable event %s not found for app PID %d."
"Skipping app", uevent->attr.name, app->pid);
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,
- uevent->filter, uevent->attr.loglevel);
+ uevent->filter, uevent->attr.loglevel, uevent->exclusion);
if (ua_event == NULL) {
ret = create_ust_app_event(ua_sess, ua_chan, uevent, app);
if (ret < 0) {
return ret;
}
-/*
- * Disable event for a channel from a UST session for a specific PID.
- */
-int ust_app_disable_event_pid(struct ltt_ust_session *usess,
- struct ltt_ust_channel *uchan, struct ltt_ust_event *uevent, pid_t pid)
-{
- int ret = 0;
- struct lttng_ht_iter iter;
- struct lttng_ht_node_str *ua_chan_node, *ua_event_node;
- struct ust_app *app;
- struct ust_app_session *ua_sess;
- struct ust_app_channel *ua_chan;
- struct ust_app_event *ua_event;
-
- DBG("UST app disabling event %s for PID %d", uevent->attr.name, pid);
-
- rcu_read_lock();
-
- app = ust_app_find_by_pid(pid);
- if (app == NULL) {
- ERR("UST app disable event per PID %d not found", pid);
- ret = -1;
- goto error;
- }
-
- if (!app->compatible) {
- ret = 0;
- goto error;
- }
-
- ua_sess = lookup_session_by_app(usess, app);
- if (!ua_sess) {
- /* The application has problem or is probably dead. */
- goto error;
- }
-
- /* Lookup channel in the ust app session */
- lttng_ht_lookup(ua_sess->channels, (void *)uchan->name, &iter);
- ua_chan_node = lttng_ht_iter_get_node_str(&iter);
- if (ua_chan_node == NULL) {
- /* Channel does not exist, skip disabling */
- goto error;
- }
- ua_chan = caa_container_of(ua_chan_node, struct ust_app_channel, node);
-
- lttng_ht_lookup(ua_chan->events, (void *)uevent->attr.name, &iter);
- ua_event_node = lttng_ht_iter_get_node_str(&iter);
- if (ua_event_node == NULL) {
- /* Event does not exist, skip disabling */
- goto error;
- }
- ua_event = caa_container_of(ua_event_node, struct ust_app_event, node);
-
- ret = disable_ust_app_event(ua_sess, ua_event, app);
- if (ret < 0) {
- goto error;
- }
-
-error:
- rcu_read_unlock();
- return ret;
-}
-
/*
* Calibrate registered applications.
*/
struct snapshot_output *output, int wait, unsigned int nb_streams)
{
int ret = 0;
+ unsigned int snapshot_done = 0;
struct lttng_ht_iter iter;
struct ust_app *app;
char pathname[PATH_MAX];
if (ret < 0) {
goto error;
}
+ snapshot_done = 1;
}
break;
}
if (ret < 0) {
goto error;
}
+ snapshot_done = 1;
}
break;
}
break;
}
+ if (!snapshot_done) {
+ /*
+ * If no snapshot was made and we are not in the error path, this means
+ * that there are no buffers thus no (prior) application to snapshot
+ * data from so we have simply NO data.
+ */
+ ret = -ENODATA;
+ }
+
error:
rcu_read_unlock();
return ret;