+ ret = config_writer_write_element_string(writer,
+ config_element_userspace_probe_function_location_function_name,
+ function_name);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ /* Close the userspace probe function attribute. */
+ ret = config_writer_close_element(writer);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+static
+int save_kernel_userspace_probe_event(struct config_writer *writer,
+ struct ltt_kernel_event *event)
+{
+ int ret;
+ struct lttng_userspace_probe_location *userspace_probe_location;
+
+ /* Get userspace probe location from the event. */
+ userspace_probe_location = event->userspace_probe_location;
+ if (!userspace_probe_location) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ switch(lttng_userspace_probe_location_get_type(userspace_probe_location)) {
+ case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_FUNCTION:
+ {
+ ret = save_kernel_userspace_probe_function_event(writer, event);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+ break;
+ }
+ case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_TRACEPOINT:
+ {
+ ret = save_kernel_userspace_probe_tracepoint_event(writer, event);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+ break;
+ }
+ case LTTNG_USERSPACE_PROBE_LOCATION_TYPE_UNKNOWN:
+ default:
+ ERR("Unsupported kernel userspace probe location type.");
+ ret = LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+static
+int save_kernel_event(struct config_writer *writer,
+ struct ltt_kernel_event *event)
+{
+ int ret;
+ const char *instrumentation_type;
+
+ ret = config_writer_open_element(writer, config_element_event);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ if (event->event->name[0]) {
+ ret = config_writer_write_element_string(writer,
+ config_element_name, event->event->name);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+ }
+
+ ret = config_writer_write_element_bool(writer, config_element_enabled,
+ event->enabled);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ instrumentation_type = get_kernel_instrumentation_string(
+ event->event->instrumentation);
+ if (!instrumentation_type) {
+ ret = LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ ret = config_writer_write_element_string(writer, config_element_type,
+ instrumentation_type);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ if (event->filter_expression) {
+ ret = config_writer_write_element_string(writer,
+ config_element_filter,
+ event->filter_expression);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+ }
+
+ if (event->event->instrumentation == LTTNG_KERNEL_FUNCTION ||
+ event->event->instrumentation == LTTNG_KERNEL_KPROBE ||
+ event->event->instrumentation == LTTNG_KERNEL_UPROBE ||
+ event->event->instrumentation == LTTNG_KERNEL_KRETPROBE) {
+
+ ret = config_writer_open_element(writer,
+ config_element_attributes);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ switch (event->event->instrumentation) {
+ case LTTNG_KERNEL_SYSCALL:
+ case LTTNG_KERNEL_FUNCTION:
+ ret = save_kernel_function_event(writer, event);
+ if (ret) {
+ goto end;
+ }
+ break;
+ case LTTNG_KERNEL_KPROBE:
+ case LTTNG_KERNEL_KRETPROBE:
+ ret = save_kernel_kprobe_event(writer, event);
+ if (ret) {
+ goto end;
+ }
+ break;
+ case LTTNG_KERNEL_UPROBE:
+ ret = save_kernel_userspace_probe_event(writer, event);
+ if (ret) {
+ goto end;
+ }
+ break;
+ default:
+ ERR("Unsupported kernel instrumentation type.");
+ ret = LTTNG_ERR_INVALID;
+ goto end;
+ }
+
+ /* /attributes */
+ ret = config_writer_close_element(writer);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+ }
+
+ /* /event */
+ ret = config_writer_close_element(writer);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ ret = LTTNG_OK;
+end:
+ return ret;
+}
+
+/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
+static
+int save_kernel_events(struct config_writer *writer,
+ struct ltt_kernel_channel *kchan)
+{
+ int ret;
+ struct ltt_kernel_event *event;
+
+ ret = config_writer_open_element(writer, config_element_events);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ cds_list_for_each_entry(event, &kchan->events_list.head, list) {
+ ret = save_kernel_event(writer, event);
+ if (ret != LTTNG_OK) {
+ goto end;
+ }
+ }
+
+ /* /events */
+ ret = config_writer_close_element(writer);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ ret = LTTNG_OK;
+end:
+ return ret;
+}
+
+/* Return LTTNG_OK on success else a LTTNG_ERR* code. */
+static
+int save_ust_event(struct config_writer *writer,
+ struct ltt_ust_event *event)
+{
+ int ret;
+ const char *loglevel_type_string;
+
+ ret = config_writer_open_element(writer, config_element_event);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ if (event->attr.name[0]) {
+ ret = config_writer_write_element_string(writer,
+ config_element_name, event->attr.name);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+ }
+
+ ret = config_writer_write_element_bool(writer, config_element_enabled,
+ event->enabled);
+ if (ret) {
+ ret = LTTNG_ERR_SAVE_IO_FAIL;
+ goto end;
+ }
+
+ if (event->attr.instrumentation != LTTNG_UST_TRACEPOINT) {
+ ERR("Unsupported UST instrumentation type.");
+ ret = LTTNG_ERR_INVALID;
+ goto end;
+ }
+ ret = config_writer_write_element_string(writer, config_element_type,
+ config_event_type_tracepoint);