/*
* Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; only version 2 of the License.
+ * 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.
+ * 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., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307, USA.
+ * 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
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.
*/
kevent = trace_kernel_get_event_by_name(event_name, kchan);
if (kevent == NULL) {
- ret = LTTCOMM_NO_EVENT;
+ ret = LTTNG_ERR_NO_EVENT;
goto error;
}
ret = kernel_disable_event(kevent);
if (ret < 0) {
- ret = LTTCOMM_KERN_DISABLE_FAIL;
+ ret = LTTNG_ERR_KERN_DISABLE_FAIL;
goto error;
}
DBG("Kernel event %s disable for channel %s.",
kevent->event->name, kchan->channel->name);
- ret = LTTCOMM_OK;
+ ret = LTTNG_OK;
error:
return ret;
continue;
}
}
- ret = LTTCOMM_OK;
+ ret = LTTNG_OK;
return ret;
}
struct ltt_kernel_channel *kchan)
{
ERR("Cannot disable syscall tracing for existing session. Please destroy session instead.");
- return LTTCOMM_OK; /* Return OK so disable all succeeds */
+ return LTTNG_OK; /* Return OK so disable all succeeds */
}
/*
int ret;
ret = event_kernel_disable_all_tracepoints(ksession, kchan);
- if (ret != LTTCOMM_OK)
+ if (ret != LTTNG_OK)
return ret;
ret = event_kernel_disable_all_syscalls(ksession, kchan);
return ret;
if (kevent == NULL) {
ret = kernel_create_event(event, kchan);
if (ret < 0) {
- if (ret == -EEXIST) {
- ret = LTTCOMM_KERN_EVENT_EXIST;
- } else {
- ret = LTTCOMM_KERN_ENABLE_FAIL;
+ switch (-ret) {
+ case EEXIST:
+ ret = LTTNG_ERR_KERN_EVENT_EXIST;
+ break;
+ case ENOSYS:
+ ret = LTTNG_ERR_KERN_EVENT_ENOSYS;
+ break;
+ default:
+ ret = LTTNG_ERR_KERN_ENABLE_FAIL;
+ break;
}
goto end;
}
} else if (kevent->enabled == 0) {
ret = kernel_enable_event(kevent);
if (ret < 0) {
- ret = LTTCOMM_KERN_ENABLE_FAIL;
+ ret = LTTNG_ERR_KERN_ENABLE_FAIL;
goto end;
}
+ } else {
+ /* At this point, the event is considered enabled */
+ ret = LTTNG_ERR_KERN_EVENT_EXIST;
+ goto end;
}
- ret = LTTCOMM_OK;
+
+ ret = LTTNG_OK;
end:
return ret;
}
size = kernel_list_events(kernel_tracer_fd, &event_list);
if (size < 0) {
- ret = LTTCOMM_KERN_LIST_FAIL;
+ ret = LTTNG_ERR_KERN_LIST_FAIL;
goto end;
}
}
free(event_list);
- ret = LTTCOMM_OK;
+ ret = LTTNG_OK;
end:
return ret;
ret = kernel_create_event(&event, kchan);
if (ret < 0) {
if (ret == -EEXIST) {
- ret = LTTCOMM_KERN_EVENT_EXIST;
+ ret = LTTNG_ERR_KERN_EVENT_EXIST;
} else {
- ret = LTTCOMM_KERN_ENABLE_FAIL;
+ ret = LTTNG_ERR_KERN_ENABLE_FAIL;
}
goto end;
}
- ret = LTTCOMM_OK;
+ ret = LTTNG_OK;
end:
return ret;
}
int event_kernel_enable_all(struct ltt_kernel_session *ksession,
struct ltt_kernel_channel *kchan, int kernel_tracer_fd)
{
- int ret;
+ int tp_ret;
- ret = event_kernel_enable_all_tracepoints(ksession, kchan, kernel_tracer_fd);
- if (ret != LTTCOMM_OK) {
+ tp_ret = event_kernel_enable_all_tracepoints(ksession, kchan, kernel_tracer_fd);
+ if (tp_ret != LTTNG_OK) {
goto end;
}
- ret = event_kernel_enable_all_syscalls(ksession, kchan, kernel_tracer_fd);
+
+ /*
+ * Reaching this code path means that all tracepoints were enabled without
+ * errors so we ignore the error value of syscalls.
+ *
+ * At the moment, failing to enable syscalls on "lttng enable-event -a -k"
+ * is not considered an error that need to be returned to the client since
+ * 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(ksession, kchan, kernel_tracer_fd);
+
end:
- return ret;
+ return tp_ret;
}
/*
int event_ust_enable_all_tracepoints(struct ltt_ust_session *usess, int domain,
struct ltt_ust_channel *uchan)
{
- int ret, i;
- size_t size;
+ int ret, i, size;
struct lttng_ht_iter iter;
struct ltt_ust_event *uevent = NULL;
struct lttng_event *events = NULL;
/* Get all UST available events */
size = ust_app_list_events(&events);
if (size < 0) {
- ret = LTTCOMM_UST_LIST_FAIL;
+ ret = LTTNG_ERR_UST_LIST_FAIL;
goto error;
}
events[i].pid);
if (ret < 0) {
if (ret != -EEXIST) {
- ret = LTTCOMM_UST_ENABLE_FAIL;
+ ret = LTTNG_ERR_UST_ENABLE_FAIL;
goto error;
}
}
/* Create ust event */
uevent = trace_ust_create_event(&events[i]);
if (uevent == NULL) {
- ret = LTTCOMM_FATAL;
+ ret = LTTNG_ERR_FATAL;
goto error_destroy;
}
events[i].pid);
if (ret < 0) {
if (ret == -EEXIST) {
- ret = LTTCOMM_UST_EVENT_EXIST;
+ ret = LTTNG_ERR_UST_EVENT_EXIST;
goto error;
} else {
- ret = LTTCOMM_UST_ENABLE_FAIL;
+ ret = LTTNG_ERR_UST_ENABLE_FAIL;
goto error_destroy;
}
}
free(events);
break;
}
+#if 0
case LTTNG_DOMAIN_UST_EXEC_NAME:
case LTTNG_DOMAIN_UST_PID:
case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
+#endif
default:
- ret = LTTCOMM_NOT_IMPLEMENTED;
+ ret = LTTNG_ERR_UND;
goto error;
}
- return LTTCOMM_OK;
+ return LTTNG_OK;
error_destroy:
trace_ust_destroy_event(uevent);
int event_ust_enable_tracepoint(struct ltt_ust_session *usess, int domain,
struct ltt_ust_channel *uchan, struct lttng_event *event)
{
- int ret = LTTCOMM_OK, to_create = 0;
+ int ret = LTTNG_OK, to_create = 0;
struct ltt_ust_event *uevent;
uevent = trace_ust_find_event_by_name(uchan->events, event->name);
if (uevent == NULL) {
uevent = trace_ust_create_event(event);
if (uevent == NULL) {
- ret = LTTCOMM_FATAL;
+ 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;
goto end;
}
if (ret < 0) {
if (ret == -EEXIST) {
- ret = LTTCOMM_UST_EVENT_EXIST;
+ ret = LTTNG_ERR_UST_EVENT_EXIST;
goto end;
} else {
- ret = LTTCOMM_UST_ENABLE_FAIL;
+ ret = LTTNG_ERR_UST_ENABLE_FAIL;
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 = LTTCOMM_NOT_IMPLEMENTED;
+ ret = LTTNG_ERR_UND;
goto end;
}
DBG("Event UST %s %s in channel %s", uevent->attr.name,
to_create ? "created" : "enabled", uchan->name);
- ret = LTTCOMM_OK;
+ ret = LTTNG_OK;
end:
return ret;
uevent = trace_ust_find_event_by_name(uchan->events, event_name);
if (uevent == NULL) {
- ret = LTTCOMM_UST_EVENT_NOT_FOUND;
+ ret = LTTNG_ERR_UST_EVENT_NOT_FOUND;
goto error;
}
if (uevent->enabled == 0) {
/* It's already enabled so everything is OK */
- ret = LTTCOMM_OK;
+ ret = LTTNG_OK;
goto end;
}
case LTTNG_DOMAIN_UST:
ret = ust_app_disable_event_glb(usess, uchan, uevent);
if (ret < 0 && ret != -EEXIST) {
- ret = LTTCOMM_UST_DISABLE_FAIL;
+ ret = LTTNG_ERR_UST_DISABLE_FAIL;
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 = LTTCOMM_NOT_IMPLEMENTED;
+ ret = LTTNG_ERR_UND;
goto error;
}
uevent->enabled = 0;
- ret = LTTCOMM_OK;
+ ret = LTTNG_OK;
end:
DBG2("Event UST %s disabled in channel %s", uevent->attr.name,
int event_ust_disable_all_tracepoints(struct ltt_ust_session *usess, int domain,
struct ltt_ust_channel *uchan)
{
- int ret, i;
- size_t size;
+ int ret, i, size;
struct lttng_ht_iter iter;
struct ltt_ust_event *uevent = NULL;
struct lttng_event *events = NULL;
/* Get all UST available events */
size = ust_app_list_events(&events);
if (size < 0) {
- ret = LTTCOMM_UST_LIST_FAIL;
+ ret = LTTNG_ERR_UST_LIST_FAIL;
goto error;
}
ret = ust_app_disable_event_pid(usess, uchan, uevent,
events[i].pid);
if (ret < 0 && ret != -EEXIST) {
- ret = LTTCOMM_UST_DISABLE_FAIL;
+ ret = LTTNG_ERR_UST_DISABLE_FAIL;
goto error;
}
uevent->enabled = 0;
free(events);
break;
}
+#if 0
case LTTNG_DOMAIN_UST_EXEC_NAME:
case LTTNG_DOMAIN_UST_PID:
case LTTNG_DOMAIN_UST_PID_FOLLOW_CHILDREN:
+#endif
default:
- ret = LTTCOMM_NOT_IMPLEMENTED;
+ ret = LTTNG_ERR_UND;
goto error;
}
- return LTTCOMM_OK;
+ return LTTNG_OK;
error:
free(events);