extern int lttng_disable_event(struct lttng_handle *handle,
const char *name, const char *channel_name);
+/*
+ * Disable event(s) of a channel and domain.
+ *
+ * Takes a struct lttng_event as parameter.
+ * If channel_name is NULL, the default channel is used (channel0).
+ *
+ * Currently, @filter_expression must be NULL. (disabling specific
+ * filter expressions not implemented)
+ * Currently, only LTTNG_EVENT_ALL and LTTNG_EVENT_SYSCALL event types
+ * are implemented for field @ev.
+ *
+ * Return 0 on success else a negative LTTng error code.
+ */
+int lttng_disable_event_ext(struct lttng_handle *handle,
+ struct lttng_event *ev, const char *channel_name,
+ const char *filter_expression);
+
#ifdef __cplusplus
}
#endif
* Command LTTNG_DISABLE_EVENT processed by the client thread.
*/
int cmd_disable_event(struct ltt_session *session, int domain,
- char *channel_name, char *event_name)
+ char *channel_name,
+ struct lttng_event *event)
{
int ret;
+ char *event_name;
+
+ event_name = event->name;
+
+ if (event->loglevel_type || event->loglevel || event->enabled
+ || event->pid || event->filter || event->exclusion) {
+ return LTTNG_ERR_UNK;
+ }
rcu_read_lock();
goto error;
}
- ret = event_kernel_disable_tracepoint(kchan, event_name);
- if (ret != LTTNG_OK) {
+ switch (event->type) {
+ case LTTNG_EVENT_ALL:
+ case LTTNG_EVENT_TRACEPOINT:
+ ret = event_kernel_disable_tracepoint(kchan, event_name);
+ if (ret != LTTNG_OK) {
+ goto error;
+ }
+ break;
+ case LTTNG_EVENT_SYSCALL:
+ ret = event_kernel_disable_syscall(kchan, event_name);
+ break;
+ default:
+ ret = LTTNG_ERR_UNK;
goto error;
}
goto error;
}
- ret = event_ust_disable_tracepoint(usess, uchan, event_name);
- if (ret != LTTNG_OK) {
+ switch (event->type) {
+ case LTTNG_EVENT_ALL:
+ ret = event_ust_disable_tracepoint(usess, uchan, event_name);
+ if (ret != LTTNG_OK) {
+ goto error;
+ }
+ break;
+ default:
+ ret = LTTNG_ERR_UNK;
goto error;
}
assert(usess);
+ switch (event->type) {
+ case LTTNG_EVENT_ALL:
+ break;
+ default:
+ ret = LTTNG_ERR_UNK;
+ goto error;
+ }
+
agt = trace_ust_find_agent(usess, domain);
if (!agt) {
ret = -LTTNG_ERR_UST_EVENT_NOT_FOUND;
* Command LTTNG_DISABLE_ALL_EVENT processed by the client thread.
*/
int cmd_disable_event_all(struct ltt_session *session, int domain,
- char *channel_name)
+ char *channel_name,
+ struct lttng_event *event)
{
int ret;
+ char *event_name;
+
+ event_name = event->name;
rcu_read_lock();
goto error;
}
- ret = event_kernel_disable_all(kchan);
- if (ret != LTTNG_OK) {
+ switch (event->type) {
+ case LTTNG_EVENT_ALL:
+ ret = event_kernel_disable_all(kchan);
+ if (ret != LTTNG_OK) {
+ goto error;
+ }
+ break;
+ case LTTNG_EVENT_SYSCALL:
+ ret = event_kernel_disable_syscall(kchan, event_name);
+ break;
+ default:
+ ret = LTTNG_ERR_UNK;
goto error;
}
goto error;
}
- ret = event_ust_disable_all_tracepoints(usess, uchan);
- if (ret != 0) {
+ switch (event->type) {
+ case LTTNG_EVENT_ALL:
+ ret = event_ust_disable_all_tracepoints(usess, uchan);
+ if (ret != 0) {
+ goto error;
+ }
+ break;
+ default:
+ ret = LTTNG_ERR_UNK;
goto error;
}
assert(usess);
+ switch (event->type) {
+ case LTTNG_EVENT_ALL:
+ break;
+ default:
+ ret = LTTNG_ERR_UNK;
+ goto error;
+ }
+
agt = trace_ust_find_agent(usess, domain);
if (!agt) {
ret = -LTTNG_ERR_UST_EVENT_NOT_FOUND;
goto error;
}
- ret = event_kernel_enable_tracepoint(kchan, event);
- if (ret != LTTNG_OK) {
- if (channel_created) {
- /* Let's not leak a useless channel. */
- kernel_destroy_channel(kchan);
+ switch (event->type) {
+ case LTTNG_EVENT_ALL:
+ case LTTNG_EVENT_TRACEPOINT:
+ ret = event_kernel_enable_tracepoint(kchan, event);
+ if (ret != LTTNG_OK) {
+ if (channel_created) {
+ /* Let's not leak a useless channel. */
+ kernel_destroy_channel(kchan);
+ }
+ goto error;
}
+ break;
+ case LTTNG_EVENT_SYSCALL:
+ ret = event_kernel_enable_syscall(kchan, event->name);
+ break;
+ default:
+ ret = LTTNG_ERR_UNK;
goto error;
}
switch (event_type) {
case LTTNG_EVENT_SYSCALL:
- ret = event_kernel_enable_all_syscalls(kchan, kernel_tracer_fd);
+ ret = event_kernel_enable_syscall(kchan, "");
break;
case LTTNG_EVENT_TRACEPOINT:
/*
/* Event commands */
int cmd_disable_event(struct ltt_session *session, int domain,
- char *channel_name, char *event_name);
+ char *channel_name,
+ struct lttng_event *event);
int cmd_disable_event_all(struct ltt_session *session, int domain,
- char *channel_name);
+ char *channel_name,
+ struct lttng_event *event);
int cmd_add_context(struct ltt_session *session, int domain,
char *channel_name, struct lttng_event_context *ctx, int kwpipe);
int cmd_set_filter(struct ltt_session *session, int domain,
assert(node_ptr == &event->node.node);
}
-/*
- * Setup a lttng_event used to enable *all* syscall tracing.
- */
-static void init_syscalls_kernel_event(struct lttng_event *event)
-{
- assert(event);
-
- event->name[0] = '\0';
- /*
- * We use LTTNG_EVENT* here since the trace kernel creation will make the
- * right changes for the kernel.
- */
- event->type = LTTNG_EVENT_SYSCALL;
-}
-
/*
* Disable kernel tracepoint event for a channel from the kernel session.
*/
return ret;
}
+/*
+ * Enable kernel system call for a channel from the kernel session.
+ */
+int event_kernel_enable_syscall(struct ltt_kernel_channel *kchan,
+ char *syscall_name)
+{
+ int ret;
+
+ assert(kchan);
+
+ ret = kernel_enable_syscall(syscall_name, kchan);
+ if (ret < 0) {
+ ret = LTTNG_ERR_KERN_ENABLE_FAIL;
+ goto error;
+ }
+
+ DBG("Kernel event %s enable for channel %s.",
+ syscall_name, kchan->channel->name);
+
+ ret = LTTNG_OK;
+
+error:
+ return ret;
+}
+
+/*
+ * Disable kernel system call for a channel from the kernel session.
+ */
+int event_kernel_disable_syscall(struct ltt_kernel_channel *kchan,
+ char *syscall_name)
+{
+ int ret;
+
+ assert(kchan);
+
+ ret = kernel_disable_syscall(syscall_name, kchan);
+ if (ret < 0) {
+ ret = LTTNG_ERR_KERN_DISABLE_FAIL;
+ goto error;
+ }
+
+ DBG("Kernel syscall %s disable for channel %s.",
+ syscall_name[0] == '\0' ? "<all>" : syscall_name,
+ kchan->channel->name);
+
+ ret = LTTNG_OK;
+
+error:
+ return ret;
+}
+
/*
* Disable kernel tracepoint events for a channel from the kernel session.
*/
return ret;
}
-/*
- * Disable kernel syscall events for a channel from the kernel session.
- */
-int event_kernel_disable_all_syscalls(struct ltt_kernel_channel *kchan)
-{
- ERR("Cannot disable syscall tracing for existing session. Please destroy session instead.");
- return LTTNG_OK; /* Return OK so disable all succeeds */
-}
-
/*
* Disable all kernel event for a channel from the kernel session.
*/
ret = event_kernel_disable_all_tracepoints(kchan);
if (ret != LTTNG_OK)
return ret;
- ret = event_kernel_disable_all_syscalls(kchan);
+ ret = event_kernel_disable_syscall(kchan, "");
return ret;
}
return ret;
}
-/*
- * Enable all kernel sycalls events of a channel of the kernel session.
- */
-int event_kernel_enable_all_syscalls(struct ltt_kernel_channel *kchan,
- int kernel_tracer_fd)
-{
- int ret;
- struct lttng_event event;
-
- assert(kchan);
-
- init_syscalls_kernel_event(&event);
-
- DBG("Enabling all syscall tracing");
-
- ret = kernel_create_event(&event, kchan);
- if (ret < 0) {
- if (ret == -EEXIST) {
- ret = LTTNG_ERR_KERN_EVENT_EXIST;
- } else {
- ret = LTTNG_ERR_KERN_ENABLE_FAIL;
- }
- goto end;
- }
-
- ret = LTTNG_OK;
-end:
- return ret;
-}
-
/*
* Enable all kernel events of a channel of the kernel session.
*/
* tracepoints did not fail. Future work will allow us to send back
* multiple errors to the client in one API call.
*/
- (void) event_kernel_enable_all_syscalls(kchan, kernel_tracer_fd);
+ (void) event_kernel_enable_syscall(kchan, "");
end:
return tp_ret;
int event_kernel_disable_tracepoint(struct ltt_kernel_channel *kchan,
char *event_name);
-int event_kernel_disable_all_syscalls(struct ltt_kernel_channel *kchan);
+int event_kernel_disable_syscall(struct ltt_kernel_channel *kchan,
+ char *syscall_name);
int event_kernel_disable_all_tracepoints(struct ltt_kernel_channel *kchan);
int event_kernel_disable_all(struct ltt_kernel_channel *kchan);
int event_kernel_enable_tracepoint(struct ltt_kernel_channel *kchan,
struct lttng_event *event);
+int event_kernel_enable_syscall(struct ltt_kernel_channel *kchan,
+ char *syscall_name);
int event_kernel_enable_all_tracepoints(struct ltt_kernel_channel *kchan,
int kernel_tracer_fd);
-int event_kernel_enable_all_syscalls(struct ltt_kernel_channel *kchan,
- int kernel_tracer_fd);
int event_kernel_enable_all(struct ltt_kernel_channel *kchan,
int kernel_tracer_fd);
struct lttng_event_exclusion *exclusion);
int event_ust_disable_tracepoint(struct ltt_ust_session *usess,
struct ltt_ust_channel *uchan, char *event_name);
+
int event_ust_enable_all_tracepoints(struct ltt_ust_session *usess,
struct ltt_ust_channel *uchan,
char *filter_expression,
return ret;
}
+int kernel_enable_syscall(const char *syscall_name,
+ struct ltt_kernel_channel *channel)
+{
+ return kernctl_enable_syscall(channel->fd, syscall_name);
+}
+
+int kernel_disable_syscall(const char *syscall_name,
+ struct ltt_kernel_channel *channel)
+{
+ return kernctl_disable_syscall(channel->fd, syscall_name);
+}
+
/*
* Create kernel metadata, open from the kernel tracer and add it to the
* kernel session.
int kernel_disable_event(struct ltt_kernel_event *event);
int kernel_enable_event(struct ltt_kernel_event *event);
int kernel_enable_channel(struct ltt_kernel_channel *chan);
+int kernel_enable_syscall(const char *syscall_name,
+ struct ltt_kernel_channel *channel);
+int kernel_disable_syscall(const char *syscall_name,
+ struct ltt_kernel_channel *channel);
int kernel_open_metadata(struct ltt_kernel_session *session);
int kernel_open_metadata_stream(struct ltt_kernel_session *session);
int kernel_open_channel_stream(struct ltt_kernel_channel *channel);
}
case LTTNG_DISABLE_EVENT:
{
+ /* FIXME: passing packed structure to non-packed pointer */
+ /* TODO: handle filter */
ret = cmd_disable_event(cmd_ctx->session, cmd_ctx->lsm->domain.type,
cmd_ctx->lsm->u.disable.channel_name,
- cmd_ctx->lsm->u.disable.name);
+ &cmd_ctx->lsm->u.disable.event);
break;
}
case LTTNG_DISABLE_ALL_EVENT:
{
DBG("Disabling all events");
+ /* FIXME: passing packed structure to non-packed pointer */
ret = cmd_disable_event_all(cmd_ctx->session, cmd_ctx->lsm->domain.type,
- cmd_ctx->lsm->u.disable.channel_name);
+ cmd_ctx->lsm->u.disable.channel_name,
+ &cmd_ctx->lsm->u.disable.event);
break;
}
case LTTNG_ENABLE_CHANNEL:
static int opt_disable_all;
static int opt_jul;
static int opt_log4j;
+static int opt_event_type;
#if 0
/* Not implemented yet */
static char *opt_cmd_name;
enum {
OPT_HELP = 1,
OPT_USERSPACE,
+ OPT_SYSCALL,
OPT_LIST_OPTIONS,
};
{"jul", 'j', POPT_ARG_VAL, &opt_jul, 1, 0, 0},
{"log4j", 'l', POPT_ARG_VAL, &opt_log4j, 1, 0, 0},
{"kernel", 'k', POPT_ARG_VAL, &opt_kernel, 1, 0, 0},
+ {"syscall", 0, POPT_ARG_NONE, 0, OPT_SYSCALL, 0, 0},
#if 0
/* Not implemented yet */
{"userspace", 'u', POPT_ARG_STRING | POPT_ARGFLAG_OPTIONAL, &opt_cmd_name, OPT_USERSPACE, 0, 0},
fprintf(ofp, " -j, --jul Apply for Java application using JUL\n");
fprintf(ofp, " -l, --log4j Apply to Java application using LOG4j\n");
fprintf(ofp, "\n");
+ fprintf(ofp, "Event options:\n");
+ fprintf(ofp, " --syscall System call event\n");
+ fprintf(ofp, "\n");
}
static
int enabled = 1, success = 1;
char *event_name, *channel_name = NULL;
struct lttng_domain dom;
+ struct lttng_event event;
memset(&dom, 0, sizeof(dom));
}
}
+ memset(&event, 0, sizeof(event));
+ switch (opt_event_type) {
+ case LTTNG_EVENT_SYSCALL:
+ event.type = LTTNG_EVENT_SYSCALL;
+ break;
+ default:
+ event.type = LTTNG_EVENT_ALL;
+ break;
+ }
+
if (opt_disable_all) {
- command_ret = lttng_disable_event(handle, NULL, channel_name);
+ command_ret = lttng_disable_event_ext(handle, &event, channel_name, NULL);
if (command_ret < 0) {
ERR("%s", lttng_strerror(command_ret));
enabled = 1;
} else {
enabled = 0;
success = 1;
- MSG("All %s events are disabled in channel %s",
- get_domain_str(dom.type), print_channel_name(channel_name));
+ MSG("All %s %s are disabled in channel %s",
+ get_domain_str(dom.type),
+ opt_event_type == LTTNG_EVENT_SYSCALL ? "system calls" : "events",
+ print_channel_name(channel_name));
}
if (lttng_opt_mi) {
while (event_name != NULL) {
DBG("Disabling event %s", event_name);
- command_ret = lttng_disable_event(handle, event_name, channel_name);
+ strncpy(event.name, event_name, sizeof(event.name));
+ event.name[sizeof(event.name) - 1] = '\0';
+ command_ret = lttng_disable_event_ext(handle, &event, channel_name, NULL);
if (command_ret < 0) {
- ERR("Event %s: %s (channel %s, session %s)", event_name,
+ ERR("%s %s: %s (channel %s, session %s)",
+ opt_event_type == LTTNG_EVENT_SYSCALL ? "System call" : "Event",
+ event_name,
lttng_strerror(command_ret),
command_ret == -LTTNG_ERR_NEED_CHANNEL_NAME
? print_raw_channel_name(channel_name)
warn = 1;
success = 0;
/*
- * If an error occurred we assume that
- * the event is still enabled.
+ * If an error occurred we assume that the event is still
+ * enabled.
*/
enabled = 1;
} else {
- MSG("%s event %s disabled in channel %s for session %s",
- get_domain_str(dom.type), event_name,
+ MSG("%s %s %s disabled in channel %s for session %s",
+ get_domain_str(dom.type),
+ opt_event_type == LTTNG_EVENT_SYSCALL ? "system call" : "event",
+ event_name,
print_channel_name(channel_name),
session_name);
success = 1;
int opt, ret = CMD_SUCCESS, command_ret = CMD_SUCCESS, success = 1;
static poptContext pc;
char *session_name = NULL;
+ int event_type = -1;
pc = poptGetContext(NULL, argc, argv, long_options, 0);
poptReadDefaultConfig(pc, 0);
+ /* Default event type */
+ opt_event_type = LTTNG_EVENT_ALL;
+
while ((opt = poptGetNextOpt(pc)) != -1) {
switch (opt) {
case OPT_HELP:
case OPT_USERSPACE:
opt_userspace = 1;
break;
+ case OPT_SYSCALL:
+ opt_event_type = LTTNG_EVENT_SYSCALL;
+ break;
case OPT_LIST_OPTIONS:
list_cmd_options(stdout, long_options);
goto end;
ret = CMD_UNDEFINED;
goto end;
}
+
+ /* Validate event type. Multiple event type are not supported. */
+ if (event_type == -1) {
+ event_type = opt_event_type;
+ } else {
+ if (event_type != opt_event_type) {
+ ERR("Multiple event type not supported.");
+ ret = CMD_ERROR;
+ goto end;
+ }
+ }
}
opt_event_list = (char*) poptGetArg(pc);
break;
case LTTNG_EVENT_SYSCALL:
if (opt_kernel) {
- MSG("All kernel system calls are enabled in channel %s",
+ MSG("All %s system calls are enabled in channel %s",
+ get_domain_str(dom.type),
print_channel_name(channel_name));
}
break;
return ioctl(fd, LTTNG_KERNEL_CHANNEL, &channel);
}
+int kernctl_enable_syscall(int fd, const char *syscall_name)
+{
+ struct lttng_kernel_event event;
+
+ memset(&event, 0, sizeof(event));
+ strncpy(event.name, syscall_name, sizeof(event.name));
+ event.name[sizeof(event.name) - 1] = '\0';
+ event.instrumentation = LTTNG_KERNEL_SYSCALL;
+ event.u.syscall.disable = 0;
+ return ioctl(fd, LTTNG_KERNEL_EVENT, &event);
+}
+
+int kernctl_disable_syscall(int fd, const char *syscall_name)
+{
+ struct lttng_kernel_event event;
+
+ memset(&event, 0, sizeof(event));
+ strncpy(event.name, syscall_name, sizeof(event.name));
+ event.name[sizeof(event.name) - 1] = '\0';
+ event.instrumentation = LTTNG_KERNEL_SYSCALL;
+ event.u.syscall.disable = 1;
+ return ioctl(fd, LTTNG_KERNEL_EVENT, &event);
+}
+
int kernctl_create_stream(int fd)
{
return compat_ioctl_no_arg(fd, LTTNG_KERNEL_OLD_STREAM,
int kernctl_wait_quiescent(int fd);
int kernctl_calibrate(int fd, struct lttng_kernel_calibrate *calibrate);
+int kernctl_enable_syscall(int fd, const char *syscall_name);
+int kernctl_disable_syscall(int fd, const char *syscall_name);
/* Buffer operations */
char symbol_name[LTTNG_KERNEL_SYM_NAME_LEN];
} LTTNG_PACKED;
+struct lttng_kernel_syscall {
+ char disable;
+} __attribute__((packed));
+
#define LTTNG_KERNEL_EVENT_PADDING1 16
#define LTTNG_KERNEL_EVENT_PADDING2 LTTNG_KERNEL_SYM_NAME_LEN + 32
struct lttng_kernel_event {
struct lttng_kernel_kretprobe kretprobe;
struct lttng_kernel_kprobe kprobe;
struct lttng_kernel_function ftrace;
+ struct lttng_kernel_syscall syscall;
char padding[LTTNG_KERNEL_EVENT_PADDING2];
} u;
} LTTNG_PACKED;
struct lttng_session session;
struct lttng_domain domain;
union {
- struct {
- char channel_name[LTTNG_SYMBOL_NAME_LEN];
- char name[NAME_MAX];
- } LTTNG_PACKED disable;
/* Event data */
struct {
char channel_name[LTTNG_SYMBOL_NAME_LEN];
* - unsigned char filter_bytecode[bytecode_len]
*/
} LTTNG_PACKED enable;
+ struct {
+ char channel_name[LTTNG_SYMBOL_NAME_LEN];
+ struct lttng_event event LTTNG_PACKED;
+ /* Length of following filter expression. */
+ uint32_t expression_len;
+ /* Length of following bytecode for filter. */
+ uint32_t bytecode_len;
+ /*
+ * After this structure, the following variable-length
+ * items are transmitted:
+ * - unsigned char filter_expression[expression_len]
+ * - unsigned char filter_bytecode[bytecode_len]
+ */
+ } LTTNG_PACKED disable;
/* Create channel */
struct {
struct lttng_channel chan LTTNG_PACKED;
}
lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain);
+ /* FIXME: copying non-packed struct to packed struct. */
memcpy(&lsm.u.enable.event, ev, sizeof(lsm.u.enable.event));
lttng_ctl_copy_string(lsm.session.name, handle->session_name,
return ret;
}
-/*
- * Disable event(s) of a channel and domain.
- * If no event name is specified, all events are disabled.
- * If no channel name is specified, the default 'channel0' is used.
- * Returns size of returned session payload data or a negative error code.
- */
-int lttng_disable_event(struct lttng_handle *handle, const char *name,
- const char *channel_name)
+int lttng_disable_event_ext(struct lttng_handle *handle,
+ struct lttng_event *ev, const char *channel_name,
+ const char *original_filter_expression)
{
struct lttcomm_session_msg lsm;
+ char *varlen_data;
+ int ret = 0;
+ unsigned int free_filter_expression = 0;
+ struct filter_parser_ctx *ctx = NULL;
+ /*
+ * Cast as non-const since we may replace the filter expression
+ * by a dynamically allocated string. Otherwise, the original
+ * string is not modified.
+ */
+ char *filter_expression = (char *) original_filter_expression;
- if (handle == NULL) {
- return -LTTNG_ERR_INVALID;
+ if (handle == NULL || ev == NULL) {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ /* Empty filter string will always be rejected by the parser
+ * anyway, so treat this corner-case early to eliminate
+ * lttng_fmemopen error for 0-byte allocation.
+ */
+ if (filter_expression && filter_expression[0] == '\0') {
+ ret = -LTTNG_ERR_INVALID;
+ goto error;
}
memset(&lsm, 0, sizeof(lsm));
sizeof(lsm.u.disable.channel_name));
}
- lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain);
-
- if (name != NULL && *name != '*') {
- lttng_ctl_copy_string(lsm.u.disable.name, name,
- sizeof(lsm.u.disable.name));
+ if (ev->name[0] != '\0') {
lsm.cmd_type = LTTNG_DISABLE_EVENT;
} else {
lsm.cmd_type = LTTNG_DISABLE_ALL_EVENT;
}
+ lttng_ctl_copy_lttng_domain(&lsm.domain, &handle->domain);
+ /* FIXME: copying non-packed struct to packed struct. */
+ memcpy(&lsm.u.disable.event, ev, sizeof(lsm.u.disable.event));
+
lttng_ctl_copy_string(lsm.session.name, handle->session_name,
sizeof(lsm.session.name));
+ lsm.u.disable.bytecode_len = 0;
- return lttng_ctl_ask_sessiond(&lsm, NULL);
+ /*
+ * For the JUL domain, a filter is enforced except for the
+ * disable all event. This is done to avoid having the event in
+ * all sessions thus filtering by logger name.
+ */
+ if (filter_expression == NULL &&
+ (handle->domain.type != LTTNG_DOMAIN_JUL &&
+ handle->domain.type != LTTNG_DOMAIN_LOG4J)) {
+ goto ask_sessiond;
+ }
+
+ /*
+ * We have a filter, so we need to set up a variable-length
+ * memory block from where to send the data.
+ */
+
+ /* Parse filter expression */
+ if (filter_expression != NULL || handle->domain.type == LTTNG_DOMAIN_JUL
+ || handle->domain.type == LTTNG_DOMAIN_LOG4J) {
+ if (handle->domain.type == LTTNG_DOMAIN_JUL ||
+ handle->domain.type == LTTNG_DOMAIN_LOG4J) {
+ char *jul_filter;
+
+ /* Setup JUL filter if needed. */
+ jul_filter = set_jul_filter(filter_expression, ev);
+ if (!jul_filter) {
+ if (!filter_expression) {
+ /* No JUL and no filter, just skip everything below. */
+ goto ask_sessiond;
+ }
+ } else {
+ /*
+ * With a JUL filter, the original filter has been added to it
+ * thus replace the filter expression.
+ */
+ filter_expression = jul_filter;
+ free_filter_expression = 1;
+ }
+ }
+
+ ret = generate_filter(filter_expression, &lsm, &ctx);
+ if (ret) {
+ goto filter_error;
+ }
+ }
+
+ varlen_data = zmalloc(lsm.u.disable.bytecode_len
+ + lsm.u.disable.expression_len);
+ if (!varlen_data) {
+ ret = -LTTNG_ERR_EXCLUSION_NOMEM;
+ goto mem_error;
+ }
+
+ /* Add filter expression */
+ if (lsm.u.disable.expression_len != 0) {
+ memcpy(varlen_data,
+ filter_expression,
+ lsm.u.disable.expression_len);
+ }
+ /* Add filter bytecode next */
+ if (ctx && lsm.u.disable.bytecode_len != 0) {
+ memcpy(varlen_data
+ + lsm.u.disable.expression_len,
+ &ctx->bytecode->b,
+ lsm.u.disable.bytecode_len);
+ }
+
+ ret = lttng_ctl_ask_sessiond_varlen(&lsm, varlen_data,
+ lsm.u.disable.bytecode_len + lsm.u.disable.expression_len, NULL);
+ free(varlen_data);
+
+mem_error:
+ if (filter_expression && ctx) {
+ filter_bytecode_free(ctx);
+ filter_ir_free(ctx);
+ filter_parser_ctx_free(ctx);
+ }
+filter_error:
+ if (free_filter_expression) {
+ /*
+ * The filter expression has been replaced and must be freed as it is
+ * not the original filter expression received as a parameter.
+ */
+ free(filter_expression);
+ }
+error:
+ /*
+ * Return directly to the caller and don't ask the sessiond since something
+ * went wrong in the parsing of data above.
+ */
+ return ret;
+
+ask_sessiond:
+ ret = lttng_ctl_ask_sessiond(&lsm, NULL);
+ return ret;
+}
+
+/*
+ * Disable event(s) of a channel and domain.
+ * If no event name is specified, all events are disabled.
+ * If no channel name is specified, the default 'channel0' is used.
+ * Returns size of returned session payload data or a negative error code.
+ */
+int lttng_disable_event(struct lttng_handle *handle, const char *name,
+ const char *channel_name)
+{
+ struct lttng_event ev;
+
+ memset(&ev, 0, sizeof(ev));
+ ev.type = LTTNG_EVENT_ALL;
+ lttng_ctl_copy_string(ev.name, name, sizeof(ev.name));
+ return lttng_disable_event_ext(handle, &ev, channel_name, NULL);
}
/*