fprintf(ofp, " '$ctx.procname == \"demo*\"'\n");
fprintf(ofp, " '$ctx.vpid >= 4433 && $ctx.vpid < 4455'\n");
fprintf(ofp, " '$ctx.vtid == 1234'\n");
+ fprintf(ofp, " -x, --exclude LIST\n");
+ fprintf(ofp, " Add exclusions to UST tracepoints:\n");
+ fprintf(ofp, " Events that match any of the items\n");
+ fprintf(ofp, " in the comma-separated LIST are not\n");
+ fprintf(ofp, " enabled, even if they match a wildcard\n");
+ fprintf(ofp, " definition of the event.\n");
fprintf(ofp, "\n");
}
return name ? : "<default>";
}
+/*
+ * Compare list of exclusions against an event name.
+ * Return a list of legal exclusion names.
+ * Produce an error or a warning about others (depending on the situation)
+ */
+static
+int check_exclusion_subsets(const char *event_name,
+ const char *exclusions,
+ int *exclusion_count_ptr,
+ char ***exclusion_list_ptr)
+{
+ const char *excluder_ptr;
+ const char *event_ptr;
+ const char *next_excluder;
+ int excluder_length;
+ int exclusion_count = 0;
+ char **exclusion_list = NULL;
+ int ret = CMD_SUCCESS;
+
+ if (event_name[strlen(event_name) - 1] != '*') {
+ ERR("Event %s: Excluders can only be used with wildcarded events", event_name);
+ goto error;
+ }
+
+ next_excluder = exclusions;
+ while (*next_excluder != 0) {
+ event_ptr = event_name;
+ excluder_ptr = next_excluder;
+ excluder_length = strcspn(next_excluder, ",");
+
+ /* Scan both the excluder and the event letter by letter */
+ while (1) {
+ char e, x;
+
+ e = *event_ptr;
+ x = *excluder_ptr;
+
+ if (x == '*') {
+ /* Event is a subset of the excluder */
+ ERR("Event %s: %.*s excludes all events from %s",
+ event_name,
+ excluder_length,
+ next_excluder,
+ event_name);
+ goto error;
+ }
+ if (e == '*') {
+ /* Excluder is a proper subset of event */
+ exclusion_count++;
+ exclusion_list = realloc(exclusion_list, sizeof(char **) * exclusion_count);
+ exclusion_list[exclusion_count - 1] = strndup(next_excluder, excluder_length);
+
+ break;
+ }
+ if (x != e) {
+ /* Excluder and event sets have no common elements */
+ WARN("Event %s: %.*s does not exclude any events from %s",
+ event_name,
+ excluder_length,
+ next_excluder,
+ event_name);
+ break;
+ }
+ excluder_ptr++;
+ event_ptr++;
+ }
+ /* next excluder */
+ next_excluder += excluder_length;
+ if (*next_excluder == ',') {
+ next_excluder++;
+ }
+ }
+ goto end;
+error:
+ while (exclusion_count--) {
+ free(exclusion_list[exclusion_count]);
+ }
+ if (exclusion_list != NULL) {
+ free(exclusion_list);
+ }
+ exclusion_list = NULL;
+ exclusion_count = 0;
+ ret = CMD_ERROR;
+end:
+ *exclusion_count_ptr = exclusion_count;
+ *exclusion_list_ptr = exclusion_list;
+ return ret;
+}
/*
* Enabling event using the lttng API.
*/
char *event_name, *channel_name = NULL;
struct lttng_event ev;
struct lttng_domain dom;
+ int exclusion_count = 0;
+ char **exclusion_list = NULL;
memset(&ev, 0, sizeof(ev));
memset(&dom, 0, sizeof(dom));
goto error;
}
+ if (opt_kernel && opt_exclude) {
+ ERR("Event name exclusions are not yet implemented for kernel events");
+ ret = CMD_ERROR;
+ goto error;
+ }
+
channel_name = opt_channel_name;
handle = lttng_create_handle(session_name, &dom);
}
}
+ if (opt_exclude) {
+ ret = check_exclusion_subsets("*", opt_exclude,
+ &exclusion_count, &exclusion_list);
+ if (ret == CMD_ERROR) {
+ goto error;
+ }
+ }
if (!opt_filter) {
- ret = lttng_enable_event(handle, &ev, channel_name);
+ ret = lttng_enable_event_with_exclusions(handle,
+ &ev, channel_name,
+ NULL,
+ exclusion_count, exclusion_list);
if (ret < 0) {
switch (-ret) {
case LTTNG_ERR_KERN_EVENT_EXIST:
}
}
if (opt_filter) {
- ret = lttng_enable_event_with_filter(handle, &ev, channel_name,
- opt_filter);
+ ret = lttng_enable_event_with_exclusions(handle, &ev, channel_name,
+ opt_filter, exclusion_count, exclusion_list);
if (ret < 0) {
switch (-ret) {
case LTTNG_ERR_FILTER_EXIST:
goto error;
}
+ if (opt_exclude) {
+ if (opt_event_type != LTTNG_EVENT_ALL && opt_event_type != LTTNG_EVENT_TRACEPOINT) {
+ ERR("Exclusion option can only be used with tracepoint events");
+ ret = CMD_ERROR;
+ goto error;
+ }
+ /* Free previously allocated items */
+ if (exclusion_list != NULL) {
+ while (exclusion_count--) {
+ free(exclusion_list[exclusion_count]);
+ }
+ free(exclusion_list);
+ exclusion_list = NULL;
+ }
+ /* Check for proper subsets */
+ ret = check_exclusion_subsets(event_name, opt_exclude,
+ &exclusion_count, &exclusion_list);
+ if (ret == CMD_ERROR) {
+ goto error;
+ }
+ }
+
ev.loglevel_type = opt_loglevel_type;
if (opt_loglevel) {
ev.loglevel = loglevel_str_to_value(opt_loglevel);
}
if (!opt_filter) {
- ret = lttng_enable_event(handle, &ev, channel_name);
+ ret = lttng_enable_event_with_exclusions(handle,
+ &ev, channel_name,
+ NULL, exclusion_count, exclusion_list);
if (ret < 0) {
/* Turn ret to positive value to handle the positive error code */
switch (-ret) {
}
if (opt_filter) {
- ret = lttng_enable_event_with_filter(handle, &ev, channel_name,
- opt_filter);
+ ret = lttng_enable_event_with_exclusions(handle, &ev, channel_name,
+ opt_filter, exclusion_count, exclusion_list);
if (ret < 0) {
switch (-ret) {
case LTTNG_ERR_FILTER_EXIST:
}
lttng_destroy_handle(handle);
+ if (exclusion_list != NULL) {
+ while (exclusion_count--) {
+ free(exclusion_list[exclusion_count]);
+ }
+ free(exclusion_list);
+ }
+
return ret;
}