+ rcu_read_lock();
+
+ /*
+ * Don't try to enable a channel if the session has been started at
+ * some point in time before. The tracer does not allow it.
+ */
+ if (session->has_been_started) {
+ ret = LTTNG_ERR_TRACE_ALREADY_STARTED;
+ goto error;
+ }
+
+ /*
+ * If the session is a live session, remove the switch timer, the
+ * live timer does the same thing but sends also synchronisation
+ * beacons for inactive streams.
+ */
+ if (session->live_timer > 0) {
+ attr->attr.live_timer_interval = session->live_timer;
+ attr->attr.switch_timer_interval = 0;
+ }
+
+ /*
+ * The ringbuffer (both in user space and kernel) behave badly in overwrite
+ * mode and with less than 2 subbuf so block it right away and send back an
+ * invalid attribute error.
+ */
+ if (attr->attr.overwrite && attr->attr.num_subbuf < 2) {
+ ret = LTTNG_ERR_INVALID;
+ goto error;
+ }
+
+ switch (domain->type) {
+ case LTTNG_DOMAIN_KERNEL:
+ {
+ struct ltt_kernel_channel *kchan;
+
+ kchan = trace_kernel_get_channel_by_name(attr->name,
+ session->kernel_session);
+ if (kchan == NULL) {
+ ret = channel_kernel_create(session->kernel_session, attr, wpipe);
+ if (attr->name[0] != '\0') {
+ session->kernel_session->has_non_default_channel = 1;
+ }
+ } else {
+ ret = channel_kernel_enable(session->kernel_session, kchan);
+ }
+
+ if (ret != LTTNG_OK) {
+ goto error;
+ }
+
+ kernel_wait_quiescent(kernel_tracer_fd);
+ break;
+ }
+ case LTTNG_DOMAIN_UST:
+ case LTTNG_DOMAIN_JUL:
+ case LTTNG_DOMAIN_LOG4J:
+ case LTTNG_DOMAIN_PYTHON:
+ {
+ struct ltt_ust_channel *uchan;
+
+ /*
+ * FIXME
+ *
+ * Current agent implementation limitations force us to allow
+ * only one channel at once in "agent" subdomains. Each
+ * subdomain has a default channel name which must be strictly
+ * adhered to.
+ */
+ if (domain->type == LTTNG_DOMAIN_JUL) {
+ if (strncmp(attr->name, DEFAULT_JUL_CHANNEL_NAME,
+ LTTNG_SYMBOL_NAME_LEN)) {
+ ret = LTTNG_ERR_INVALID_CHANNEL_NAME;
+ goto error;
+ }
+ } else if (domain->type == LTTNG_DOMAIN_LOG4J) {
+ if (strncmp(attr->name, DEFAULT_LOG4J_CHANNEL_NAME,
+ LTTNG_SYMBOL_NAME_LEN)) {
+ ret = LTTNG_ERR_INVALID_CHANNEL_NAME;
+ goto error;
+ }
+ } else if (domain->type == LTTNG_DOMAIN_PYTHON) {
+ if (strncmp(attr->name, DEFAULT_PYTHON_CHANNEL_NAME,
+ LTTNG_SYMBOL_NAME_LEN)) {
+ ret = LTTNG_ERR_INVALID_CHANNEL_NAME;
+ goto error;
+ }
+ }
+
+ chan_ht = usess->domain_global.channels;
+
+ uchan = trace_ust_find_channel_by_name(chan_ht, attr->name);
+ if (uchan == NULL) {
+ ret = channel_ust_create(usess, attr, domain->buf_type);
+ if (attr->name[0] != '\0') {
+ usess->has_non_default_channel = 1;
+ }
+ } else {
+ ret = channel_ust_enable(usess, uchan);
+ }
+ break;
+ }
+ default:
+ ret = LTTNG_ERR_UNKNOWN_DOMAIN;
+ goto error;
+ }
+
+error:
+ rcu_read_unlock();
+end:
+ return ret;
+}
+
+/*
+ * Command LTTNG_DISABLE_EVENT processed by the client thread.
+ */
+int cmd_disable_event(struct ltt_session *session,
+ enum lttng_domain_type domain, char *channel_name,
+ struct lttng_event *event)
+{
+ int ret;
+ char *event_name;
+
+ DBG("Disable event command for event \'%s\'", event->name);
+
+ event_name = event->name;
+ if (validate_event_name(event_name)) {
+ ret = LTTNG_ERR_INVALID_EVENT_NAME;
+ goto error;
+ }
+
+ /* Error out on unhandled search criteria */
+ if (event->loglevel_type || event->loglevel != -1 || event->enabled
+ || event->pid || event->filter || event->exclusion) {
+ ret = LTTNG_ERR_UNK;
+ goto error;
+ }
+
+ rcu_read_lock();
+
+ switch (domain) {
+ case LTTNG_DOMAIN_KERNEL:
+ {
+ struct ltt_kernel_channel *kchan;
+ struct ltt_kernel_session *ksess;
+
+ ksess = session->kernel_session;
+
+ /*
+ * If a non-default channel has been created in the
+ * session, explicitely require that -c chan_name needs
+ * to be provided.
+ */
+ if (ksess->has_non_default_channel && channel_name[0] == '\0') {
+ ret = LTTNG_ERR_NEED_CHANNEL_NAME;
+ goto error_unlock;
+ }
+
+ kchan = trace_kernel_get_channel_by_name(channel_name, ksess);
+ if (kchan == NULL) {
+ ret = LTTNG_ERR_KERN_CHAN_NOT_FOUND;
+ goto error_unlock;
+ }
+
+ switch (event->type) {
+ case LTTNG_EVENT_ALL:
+ case LTTNG_EVENT_TRACEPOINT:
+ case LTTNG_EVENT_SYSCALL:
+ case LTTNG_EVENT_PROBE:
+ case LTTNG_EVENT_FUNCTION:
+ case LTTNG_EVENT_FUNCTION_ENTRY:/* fall-through */
+ if (event_name[0] == '\0') {
+ ret = event_kernel_disable_event(kchan,
+ NULL, event->type);
+ } else {
+ ret = event_kernel_disable_event(kchan,
+ event_name, event->type);
+ }
+ if (ret != LTTNG_OK) {
+ goto error_unlock;
+ }
+ break;
+ default:
+ ret = LTTNG_ERR_UNK;
+ goto error_unlock;
+ }
+
+ kernel_wait_quiescent(kernel_tracer_fd);