Blame liblttng-ust-ctl/ustctl.c

Packit c04fcb
/*
Packit c04fcb
 * Copyright (C) 2011 - Julien Desfossez <julien.desfossez@polymtl.ca>
Packit c04fcb
 * Copyright (C) 2011-2013 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Packit c04fcb
 *
Packit c04fcb
 * This program is free software; you can redistribute it and/or modify
Packit c04fcb
 * it under the terms of the GNU General Public License as published by
Packit c04fcb
 * the Free Software Foundation; version 2 of the License only.
Packit c04fcb
 *
Packit c04fcb
 * This program is distributed in the hope that it will be useful,
Packit c04fcb
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit c04fcb
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit c04fcb
 * GNU General Public License for more details.
Packit c04fcb
 *
Packit c04fcb
 * You should have received a copy of the GNU General Public License along
Packit c04fcb
 * with this program; if not, write to the Free Software Foundation, Inc.,
Packit c04fcb
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Packit c04fcb
 */
Packit c04fcb
Packit c04fcb
#define _GNU_SOURCE
Packit c04fcb
#include <string.h>
Packit c04fcb
#include <lttng/ust-ctl.h>
Packit c04fcb
#include <lttng/ust-abi.h>
Packit c04fcb
#include <lttng/ust-events.h>
Packit c04fcb
#include <sys/mman.h>
Packit c04fcb
#include <byteswap.h>
Packit c04fcb
Packit c04fcb
#include <usterr-signal-safe.h>
Packit c04fcb
#include <ust-comm.h>
Packit c04fcb
#include <helper.h>
Packit c04fcb
Packit c04fcb
#include "../libringbuffer/backend.h"
Packit c04fcb
#include "../libringbuffer/frontend.h"
Packit c04fcb
#include "../liblttng-ust/wait.h"
Packit c04fcb
#include "../liblttng-ust/lttng-rb-clients.h"
Packit c04fcb
#include "../liblttng-ust/clock.h"
Packit c04fcb
Packit c04fcb
/*
Packit c04fcb
 * Number of milliseconds to retry before failing metadata writes on
Packit c04fcb
 * buffer full condition. (10 seconds)
Packit c04fcb
 */
Packit c04fcb
#define LTTNG_METADATA_TIMEOUT_MSEC	10000
Packit c04fcb
Packit c04fcb
/*
Packit c04fcb
 * Channel representation within consumer.
Packit c04fcb
 */
Packit c04fcb
struct ustctl_consumer_channel {
Packit c04fcb
	struct lttng_channel *chan;		/* lttng channel buffers */
Packit c04fcb
Packit c04fcb
	/* initial attributes */
Packit c04fcb
	struct ustctl_consumer_channel_attr attr;
Packit c04fcb
	int wait_fd;				/* monitor close() */
Packit c04fcb
	int wakeup_fd;				/* monitor close() */
Packit c04fcb
};
Packit c04fcb
Packit c04fcb
/*
Packit c04fcb
 * Stream representation within consumer.
Packit c04fcb
 */
Packit c04fcb
struct ustctl_consumer_stream {
Packit c04fcb
	struct lttng_ust_shm_handle *handle;	/* shared-memory handle */
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
	struct ustctl_consumer_channel *chan;
Packit c04fcb
	int shm_fd, wait_fd, wakeup_fd;
Packit c04fcb
	int cpu;
Packit c04fcb
	uint64_t memory_map_size;
Packit c04fcb
};
Packit c04fcb
Packit c04fcb
extern void lttng_ring_buffer_client_overwrite_init(void);
Packit c04fcb
extern void lttng_ring_buffer_client_overwrite_rt_init(void);
Packit c04fcb
extern void lttng_ring_buffer_client_discard_init(void);
Packit c04fcb
extern void lttng_ring_buffer_client_discard_rt_init(void);
Packit c04fcb
extern void lttng_ring_buffer_metadata_client_init(void);
Packit c04fcb
extern void lttng_ring_buffer_client_overwrite_exit(void);
Packit c04fcb
extern void lttng_ring_buffer_client_overwrite_rt_exit(void);
Packit c04fcb
extern void lttng_ring_buffer_client_discard_exit(void);
Packit c04fcb
extern void lttng_ring_buffer_client_discard_rt_exit(void);
Packit c04fcb
extern void lttng_ring_buffer_metadata_client_exit(void);
Packit c04fcb
Packit c04fcb
volatile enum ust_loglevel ust_loglevel;
Packit c04fcb
Packit c04fcb
int ustctl_release_handle(int sock, int handle)
Packit c04fcb
{
Packit c04fcb
	struct ustcomm_ust_msg lum;
Packit c04fcb
	struct ustcomm_ust_reply lur;
Packit c04fcb
Packit c04fcb
	if (sock < 0 || handle < 0)
Packit c04fcb
		return 0;
Packit c04fcb
	memset(&lum, 0, sizeof(lum));
Packit c04fcb
	lum.handle = handle;
Packit c04fcb
	lum.cmd = LTTNG_UST_RELEASE;
Packit c04fcb
	return ustcomm_send_app_cmd(sock, &lum, &lur);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
/*
Packit c04fcb
 * If sock is negative, it means we don't have to notify the other side
Packit c04fcb
 * (e.g. application has already vanished).
Packit c04fcb
 */
Packit c04fcb
int ustctl_release_object(int sock, struct lttng_ust_object_data *data)
Packit c04fcb
{
Packit c04fcb
	int ret;
Packit c04fcb
Packit c04fcb
	if (!data)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
Packit c04fcb
	switch (data->type) {
Packit c04fcb
	case LTTNG_UST_OBJECT_TYPE_CHANNEL:
Packit c04fcb
		if (data->u.channel.wakeup_fd >= 0) {
Packit c04fcb
			ret = close(data->u.channel.wakeup_fd);
Packit c04fcb
			if (ret < 0) {
Packit c04fcb
				ret = -errno;
Packit c04fcb
				return ret;
Packit c04fcb
			}
Packit c04fcb
		}
Packit c04fcb
		free(data->u.channel.data);
Packit c04fcb
		break;
Packit c04fcb
	case LTTNG_UST_OBJECT_TYPE_STREAM:
Packit c04fcb
		if (data->u.stream.shm_fd >= 0) {
Packit c04fcb
			ret = close(data->u.stream.shm_fd);
Packit c04fcb
			if (ret < 0) {
Packit c04fcb
				ret = -errno;
Packit c04fcb
				return ret;
Packit c04fcb
			}
Packit c04fcb
		}
Packit c04fcb
		if (data->u.stream.wakeup_fd >= 0) {
Packit c04fcb
			ret = close(data->u.stream.wakeup_fd);
Packit c04fcb
			if (ret < 0) {
Packit c04fcb
				ret = -errno;
Packit c04fcb
				return ret;
Packit c04fcb
			}
Packit c04fcb
		}
Packit c04fcb
		break;
Packit c04fcb
	case LTTNG_UST_OBJECT_TYPE_EVENT:
Packit c04fcb
	case LTTNG_UST_OBJECT_TYPE_CONTEXT:
Packit c04fcb
		break;
Packit c04fcb
	default:
Packit c04fcb
		assert(0);
Packit c04fcb
	}
Packit c04fcb
	return ustctl_release_handle(sock, data->handle);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
/*
Packit c04fcb
 * Send registration done packet to the application.
Packit c04fcb
 */
Packit c04fcb
int ustctl_register_done(int sock)
Packit c04fcb
{
Packit c04fcb
	struct ustcomm_ust_msg lum;
Packit c04fcb
	struct ustcomm_ust_reply lur;
Packit c04fcb
	int ret;
Packit c04fcb
Packit c04fcb
	DBG("Sending register done command to %d", sock);
Packit c04fcb
	memset(&lum, 0, sizeof(lum));
Packit c04fcb
	lum.handle = LTTNG_UST_ROOT_HANDLE;
Packit c04fcb
	lum.cmd = LTTNG_UST_REGISTER_DONE;
Packit c04fcb
	ret = ustcomm_send_app_cmd(sock, &lum, &lur);
Packit c04fcb
	if (ret)
Packit c04fcb
		return ret;
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
/*
Packit c04fcb
 * returns session handle.
Packit c04fcb
 */
Packit c04fcb
int ustctl_create_session(int sock)
Packit c04fcb
{
Packit c04fcb
	struct ustcomm_ust_msg lum;
Packit c04fcb
	struct ustcomm_ust_reply lur;
Packit c04fcb
	int ret, session_handle;
Packit c04fcb
Packit c04fcb
	/* Create session */
Packit c04fcb
	memset(&lum, 0, sizeof(lum));
Packit c04fcb
	lum.handle = LTTNG_UST_ROOT_HANDLE;
Packit c04fcb
	lum.cmd = LTTNG_UST_SESSION;
Packit c04fcb
	ret = ustcomm_send_app_cmd(sock, &lum, &lur);
Packit c04fcb
	if (ret)
Packit c04fcb
		return ret;
Packit c04fcb
	session_handle = lur.ret_val;
Packit c04fcb
	DBG("received session handle %u", session_handle);
Packit c04fcb
	return session_handle;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_create_event(int sock, struct lttng_ust_event *ev,
Packit c04fcb
		struct lttng_ust_object_data *channel_data,
Packit c04fcb
		struct lttng_ust_object_data **_event_data)
Packit c04fcb
{
Packit c04fcb
	struct ustcomm_ust_msg lum;
Packit c04fcb
	struct ustcomm_ust_reply lur;
Packit c04fcb
	struct lttng_ust_object_data *event_data;
Packit c04fcb
	int ret;
Packit c04fcb
Packit c04fcb
	if (!channel_data || !_event_data)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
Packit c04fcb
	event_data = zmalloc(sizeof(*event_data));
Packit c04fcb
	if (!event_data)
Packit c04fcb
		return -ENOMEM;
Packit c04fcb
	event_data->type = LTTNG_UST_OBJECT_TYPE_EVENT;
Packit c04fcb
	memset(&lum, 0, sizeof(lum));
Packit c04fcb
	lum.handle = channel_data->handle;
Packit c04fcb
	lum.cmd = LTTNG_UST_EVENT;
Packit c04fcb
	strncpy(lum.u.event.name, ev->name,
Packit c04fcb
		LTTNG_UST_SYM_NAME_LEN);
Packit c04fcb
	lum.u.event.instrumentation = ev->instrumentation;
Packit c04fcb
	lum.u.event.loglevel_type = ev->loglevel_type;
Packit c04fcb
	lum.u.event.loglevel = ev->loglevel;
Packit c04fcb
	ret = ustcomm_send_app_cmd(sock, &lum, &lur);
Packit c04fcb
	if (ret) {
Packit c04fcb
		free(event_data);
Packit c04fcb
		return ret;
Packit c04fcb
	}
Packit c04fcb
	event_data->handle = lur.ret_val;
Packit c04fcb
	DBG("received event handle %u", event_data->handle);
Packit c04fcb
	*_event_data = event_data;
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_add_context(int sock, struct lttng_ust_context_attr *ctx,
Packit c04fcb
		struct lttng_ust_object_data *obj_data,
Packit c04fcb
		struct lttng_ust_object_data **_context_data)
Packit c04fcb
{
Packit c04fcb
	struct ustcomm_ust_msg lum;
Packit c04fcb
	struct ustcomm_ust_reply lur;
Packit c04fcb
	struct lttng_ust_object_data *context_data = NULL;
Packit c04fcb
	char *buf = NULL;
Packit c04fcb
	size_t len;
Packit c04fcb
	int ret;
Packit c04fcb
Packit c04fcb
	if (!obj_data || !_context_data) {
Packit c04fcb
		ret = -EINVAL;
Packit c04fcb
		goto end;
Packit c04fcb
	}
Packit c04fcb
Packit c04fcb
	context_data = zmalloc(sizeof(*context_data));
Packit c04fcb
	if (!context_data) {
Packit c04fcb
		ret = -ENOMEM;
Packit c04fcb
		goto end;
Packit c04fcb
	}
Packit c04fcb
	context_data->type = LTTNG_UST_OBJECT_TYPE_CONTEXT;
Packit c04fcb
	memset(&lum, 0, sizeof(lum));
Packit c04fcb
	lum.handle = obj_data->handle;
Packit c04fcb
	lum.cmd = LTTNG_UST_CONTEXT;
Packit c04fcb
Packit c04fcb
	lum.u.context.ctx = ctx->ctx;
Packit c04fcb
	switch (ctx->ctx) {
Packit c04fcb
	case LTTNG_UST_CONTEXT_PERF_THREAD_COUNTER:
Packit c04fcb
		lum.u.context.u.perf_counter = ctx->u.perf_counter;
Packit c04fcb
		break;
Packit c04fcb
	case LTTNG_UST_CONTEXT_APP_CONTEXT:
Packit c04fcb
	{
Packit c04fcb
		size_t provider_name_len = strlen(
Packit c04fcb
				ctx->u.app_ctx.provider_name) + 1;
Packit c04fcb
		size_t ctx_name_len = strlen(ctx->u.app_ctx.ctx_name) + 1;
Packit c04fcb
Packit c04fcb
		lum.u.context.u.app_ctx.provider_name_len = provider_name_len;
Packit c04fcb
		lum.u.context.u.app_ctx.ctx_name_len = ctx_name_len;
Packit c04fcb
Packit c04fcb
		len = provider_name_len + ctx_name_len;
Packit c04fcb
		buf = zmalloc(len);
Packit c04fcb
		if (!buf) {
Packit c04fcb
			ret = -ENOMEM;
Packit c04fcb
			goto end;
Packit c04fcb
		}
Packit c04fcb
		memcpy(buf, ctx->u.app_ctx.provider_name,
Packit c04fcb
				provider_name_len);
Packit c04fcb
		memcpy(buf + provider_name_len, ctx->u.app_ctx.ctx_name,
Packit c04fcb
				ctx_name_len);
Packit c04fcb
		break;
Packit c04fcb
	}
Packit c04fcb
	default:
Packit c04fcb
		break;
Packit c04fcb
	}
Packit c04fcb
	ret = ustcomm_send_app_msg(sock, &lum;;
Packit c04fcb
	if (ret)
Packit c04fcb
		goto end;
Packit c04fcb
	if (buf) {
Packit c04fcb
		/* send var len ctx_name */
Packit c04fcb
		ret = ustcomm_send_unix_sock(sock, buf, len);
Packit c04fcb
		if (ret < 0) {
Packit c04fcb
			goto end;
Packit c04fcb
		}
Packit c04fcb
		if (ret != len) {
Packit c04fcb
			ret = -EINVAL;
Packit c04fcb
			goto end;
Packit c04fcb
		}
Packit c04fcb
	}
Packit c04fcb
	ret = ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd);
Packit c04fcb
	if (ret < 0) {
Packit c04fcb
		goto end;
Packit c04fcb
	}
Packit c04fcb
	context_data->handle = -1;
Packit c04fcb
	DBG("Context created successfully");
Packit c04fcb
	*_context_data = context_data;
Packit c04fcb
	context_data = NULL;
Packit c04fcb
end:
Packit c04fcb
	free(context_data);
Packit c04fcb
	free(buf);
Packit c04fcb
	return ret;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_set_filter(int sock, struct lttng_ust_filter_bytecode *bytecode,
Packit c04fcb
		struct lttng_ust_object_data *obj_data)
Packit c04fcb
{
Packit c04fcb
	struct ustcomm_ust_msg lum;
Packit c04fcb
	struct ustcomm_ust_reply lur;
Packit c04fcb
	int ret;
Packit c04fcb
Packit c04fcb
	if (!obj_data)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
Packit c04fcb
	memset(&lum, 0, sizeof(lum));
Packit c04fcb
	lum.handle = obj_data->handle;
Packit c04fcb
	lum.cmd = LTTNG_UST_FILTER;
Packit c04fcb
	lum.u.filter.data_size = bytecode->len;
Packit c04fcb
	lum.u.filter.reloc_offset = bytecode->reloc_offset;
Packit c04fcb
	lum.u.filter.seqnum = bytecode->seqnum;
Packit c04fcb
Packit c04fcb
	ret = ustcomm_send_app_msg(sock, &lum;;
Packit c04fcb
	if (ret)
Packit c04fcb
		return ret;
Packit c04fcb
	/* send var len bytecode */
Packit c04fcb
	ret = ustcomm_send_unix_sock(sock, bytecode->data,
Packit c04fcb
				bytecode->len);
Packit c04fcb
	if (ret < 0) {
Packit c04fcb
		return ret;
Packit c04fcb
	}
Packit c04fcb
	if (ret != bytecode->len)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	return ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_set_exclusion(int sock, struct lttng_ust_event_exclusion *exclusion,
Packit c04fcb
		struct lttng_ust_object_data *obj_data)
Packit c04fcb
{
Packit c04fcb
	struct ustcomm_ust_msg lum;
Packit c04fcb
	struct ustcomm_ust_reply lur;
Packit c04fcb
	int ret;
Packit c04fcb
Packit c04fcb
	if (!obj_data) {
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	}
Packit c04fcb
Packit c04fcb
	memset(&lum, 0, sizeof(lum));
Packit c04fcb
	lum.handle = obj_data->handle;
Packit c04fcb
	lum.cmd = LTTNG_UST_EXCLUSION;
Packit c04fcb
	lum.u.exclusion.count = exclusion->count;
Packit c04fcb
Packit c04fcb
	ret = ustcomm_send_app_msg(sock, &lum;;
Packit c04fcb
	if (ret) {
Packit c04fcb
		return ret;
Packit c04fcb
	}
Packit c04fcb
Packit c04fcb
	/* send var len exclusion names */
Packit c04fcb
	ret = ustcomm_send_unix_sock(sock,
Packit c04fcb
			exclusion->names,
Packit c04fcb
			exclusion->count * LTTNG_UST_SYM_NAME_LEN);
Packit c04fcb
	if (ret < 0) {
Packit c04fcb
		return ret;
Packit c04fcb
	}
Packit c04fcb
	if (ret != exclusion->count * LTTNG_UST_SYM_NAME_LEN) {
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	}
Packit c04fcb
	return ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
/* Enable event, channel and session ioctl */
Packit c04fcb
int ustctl_enable(int sock, struct lttng_ust_object_data *object)
Packit c04fcb
{
Packit c04fcb
	struct ustcomm_ust_msg lum;
Packit c04fcb
	struct ustcomm_ust_reply lur;
Packit c04fcb
	int ret;
Packit c04fcb
Packit c04fcb
	if (!object)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
Packit c04fcb
	memset(&lum, 0, sizeof(lum));
Packit c04fcb
	lum.handle = object->handle;
Packit c04fcb
	lum.cmd = LTTNG_UST_ENABLE;
Packit c04fcb
	ret = ustcomm_send_app_cmd(sock, &lum, &lur);
Packit c04fcb
	if (ret)
Packit c04fcb
		return ret;
Packit c04fcb
	DBG("enabled handle %u", object->handle);
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
/* Disable event, channel and session ioctl */
Packit c04fcb
int ustctl_disable(int sock, struct lttng_ust_object_data *object)
Packit c04fcb
{
Packit c04fcb
	struct ustcomm_ust_msg lum;
Packit c04fcb
	struct ustcomm_ust_reply lur;
Packit c04fcb
	int ret;
Packit c04fcb
Packit c04fcb
	if (!object)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
Packit c04fcb
	memset(&lum, 0, sizeof(lum));
Packit c04fcb
	lum.handle = object->handle;
Packit c04fcb
	lum.cmd = LTTNG_UST_DISABLE;
Packit c04fcb
	ret = ustcomm_send_app_cmd(sock, &lum, &lur);
Packit c04fcb
	if (ret)
Packit c04fcb
		return ret;
Packit c04fcb
	DBG("disable handle %u", object->handle);
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_start_session(int sock, int handle)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_object_data obj;
Packit c04fcb
Packit c04fcb
	obj.handle = handle;
Packit c04fcb
	return ustctl_enable(sock, &obj);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_stop_session(int sock, int handle)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_object_data obj;
Packit c04fcb
Packit c04fcb
	obj.handle = handle;
Packit c04fcb
	return ustctl_disable(sock, &obj);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_tracepoint_list(int sock)
Packit c04fcb
{
Packit c04fcb
	struct ustcomm_ust_msg lum;
Packit c04fcb
	struct ustcomm_ust_reply lur;
Packit c04fcb
	int ret, tp_list_handle;
Packit c04fcb
Packit c04fcb
	memset(&lum, 0, sizeof(lum));
Packit c04fcb
	lum.handle = LTTNG_UST_ROOT_HANDLE;
Packit c04fcb
	lum.cmd = LTTNG_UST_TRACEPOINT_LIST;
Packit c04fcb
	ret = ustcomm_send_app_cmd(sock, &lum, &lur);
Packit c04fcb
	if (ret)
Packit c04fcb
		return ret;
Packit c04fcb
	tp_list_handle = lur.ret_val;
Packit c04fcb
	DBG("received tracepoint list handle %u", tp_list_handle);
Packit c04fcb
	return tp_list_handle;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_tracepoint_list_get(int sock, int tp_list_handle,
Packit c04fcb
		struct lttng_ust_tracepoint_iter *iter)
Packit c04fcb
{
Packit c04fcb
	struct ustcomm_ust_msg lum;
Packit c04fcb
	struct ustcomm_ust_reply lur;
Packit c04fcb
	int ret;
Packit c04fcb
Packit c04fcb
	if (!iter)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
Packit c04fcb
	memset(&lum, 0, sizeof(lum));
Packit c04fcb
	lum.handle = tp_list_handle;
Packit c04fcb
	lum.cmd = LTTNG_UST_TRACEPOINT_LIST_GET;
Packit c04fcb
	ret = ustcomm_send_app_cmd(sock, &lum, &lur);
Packit c04fcb
	if (ret)
Packit c04fcb
		return ret;
Packit c04fcb
	DBG("received tracepoint list entry name %s loglevel %d",
Packit c04fcb
		lur.u.tracepoint.name,
Packit c04fcb
		lur.u.tracepoint.loglevel);
Packit c04fcb
	memcpy(iter, &lur.u.tracepoint, sizeof(*iter));
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_tracepoint_field_list(int sock)
Packit c04fcb
{
Packit c04fcb
	struct ustcomm_ust_msg lum;
Packit c04fcb
	struct ustcomm_ust_reply lur;
Packit c04fcb
	int ret, tp_field_list_handle;
Packit c04fcb
Packit c04fcb
	memset(&lum, 0, sizeof(lum));
Packit c04fcb
	lum.handle = LTTNG_UST_ROOT_HANDLE;
Packit c04fcb
	lum.cmd = LTTNG_UST_TRACEPOINT_FIELD_LIST;
Packit c04fcb
	ret = ustcomm_send_app_cmd(sock, &lum, &lur);
Packit c04fcb
	if (ret)
Packit c04fcb
		return ret;
Packit c04fcb
	tp_field_list_handle = lur.ret_val;
Packit c04fcb
	DBG("received tracepoint field list handle %u", tp_field_list_handle);
Packit c04fcb
	return tp_field_list_handle;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_tracepoint_field_list_get(int sock, int tp_field_list_handle,
Packit c04fcb
		struct lttng_ust_field_iter *iter)
Packit c04fcb
{
Packit c04fcb
	struct ustcomm_ust_msg lum;
Packit c04fcb
	struct ustcomm_ust_reply lur;
Packit c04fcb
	int ret;
Packit c04fcb
	ssize_t len;
Packit c04fcb
Packit c04fcb
	if (!iter)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
Packit c04fcb
	memset(&lum, 0, sizeof(lum));
Packit c04fcb
	lum.handle = tp_field_list_handle;
Packit c04fcb
	lum.cmd = LTTNG_UST_TRACEPOINT_FIELD_LIST_GET;
Packit c04fcb
	ret = ustcomm_send_app_cmd(sock, &lum, &lur);
Packit c04fcb
	if (ret)
Packit c04fcb
		return ret;
Packit c04fcb
	len = ustcomm_recv_unix_sock(sock, iter, sizeof(*iter));
Packit c04fcb
	if (len != sizeof(*iter)) {
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	}
Packit c04fcb
	DBG("received tracepoint field list entry event_name %s event_loglevel %d field_name %s field_type %d",
Packit c04fcb
		iter->event_name,
Packit c04fcb
		iter->loglevel,
Packit c04fcb
		iter->field_name,
Packit c04fcb
		iter->type);
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_tracer_version(int sock, struct lttng_ust_tracer_version *v)
Packit c04fcb
{
Packit c04fcb
	struct ustcomm_ust_msg lum;
Packit c04fcb
	struct ustcomm_ust_reply lur;
Packit c04fcb
	int ret;
Packit c04fcb
Packit c04fcb
	if (!v)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
Packit c04fcb
	memset(&lum, 0, sizeof(lum));
Packit c04fcb
	lum.handle = LTTNG_UST_ROOT_HANDLE;
Packit c04fcb
	lum.cmd = LTTNG_UST_TRACER_VERSION;
Packit c04fcb
	ret = ustcomm_send_app_cmd(sock, &lum, &lur);
Packit c04fcb
	if (ret)
Packit c04fcb
		return ret;
Packit c04fcb
	memcpy(v, &lur.u.version, sizeof(*v));
Packit c04fcb
	DBG("received tracer version");
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_wait_quiescent(int sock)
Packit c04fcb
{
Packit c04fcb
	struct ustcomm_ust_msg lum;
Packit c04fcb
	struct ustcomm_ust_reply lur;
Packit c04fcb
	int ret;
Packit c04fcb
Packit c04fcb
	memset(&lum, 0, sizeof(lum));
Packit c04fcb
	lum.handle = LTTNG_UST_ROOT_HANDLE;
Packit c04fcb
	lum.cmd = LTTNG_UST_WAIT_QUIESCENT;
Packit c04fcb
	ret = ustcomm_send_app_cmd(sock, &lum, &lur);
Packit c04fcb
	if (ret)
Packit c04fcb
		return ret;
Packit c04fcb
	DBG("waited for quiescent state");
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_calibrate(int sock, struct lttng_ust_calibrate *calibrate)
Packit c04fcb
{
Packit c04fcb
	if (!calibrate)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
Packit c04fcb
	return -ENOSYS;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_sock_flush_buffer(int sock, struct lttng_ust_object_data *object)
Packit c04fcb
{
Packit c04fcb
	struct ustcomm_ust_msg lum;
Packit c04fcb
	struct ustcomm_ust_reply lur;
Packit c04fcb
	int ret;
Packit c04fcb
Packit c04fcb
	if (!object)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
Packit c04fcb
	memset(&lum, 0, sizeof(lum));
Packit c04fcb
	lum.handle = object->handle;
Packit c04fcb
	lum.cmd = LTTNG_UST_FLUSH_BUFFER;
Packit c04fcb
	ret = ustcomm_send_app_cmd(sock, &lum, &lur);
Packit c04fcb
	if (ret)
Packit c04fcb
		return ret;
Packit c04fcb
	DBG("flushed buffer handle %u", object->handle);
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
static
Packit c04fcb
int ustctl_send_channel(int sock,
Packit c04fcb
		enum lttng_ust_chan_type type,
Packit c04fcb
		void *data,
Packit c04fcb
		uint64_t size,
Packit c04fcb
		int wakeup_fd,
Packit c04fcb
		int send_fd_only)
Packit c04fcb
{
Packit c04fcb
	ssize_t len;
Packit c04fcb
Packit c04fcb
	if (!send_fd_only) {
Packit c04fcb
		/* Send mmap size */
Packit c04fcb
		len = ustcomm_send_unix_sock(sock, &size, sizeof(size));
Packit c04fcb
		if (len != sizeof(size)) {
Packit c04fcb
			if (len < 0)
Packit c04fcb
				return len;
Packit c04fcb
			else
Packit c04fcb
				return -EIO;
Packit c04fcb
		}
Packit c04fcb
Packit c04fcb
		/* Send channel type */
Packit c04fcb
		len = ustcomm_send_unix_sock(sock, &type, sizeof(type));
Packit c04fcb
		if (len != sizeof(type)) {
Packit c04fcb
			if (len < 0)
Packit c04fcb
				return len;
Packit c04fcb
			else
Packit c04fcb
				return -EIO;
Packit c04fcb
		}
Packit c04fcb
	}
Packit c04fcb
Packit c04fcb
	/* Send channel data */
Packit c04fcb
	len = ustcomm_send_unix_sock(sock, data, size);
Packit c04fcb
	if (len != size) {
Packit c04fcb
		if (len < 0)
Packit c04fcb
			return len;
Packit c04fcb
		else
Packit c04fcb
			return -EIO;
Packit c04fcb
	}
Packit c04fcb
Packit c04fcb
	/* Send wakeup fd */
Packit c04fcb
	len = ustcomm_send_fds_unix_sock(sock, &wakeup_fd, 1);
Packit c04fcb
	if (len <= 0) {
Packit c04fcb
		if (len < 0)
Packit c04fcb
			return len;
Packit c04fcb
		else
Packit c04fcb
			return -EIO;
Packit c04fcb
	}
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
static
Packit c04fcb
int ustctl_send_stream(int sock,
Packit c04fcb
		uint32_t stream_nr,
Packit c04fcb
		uint64_t memory_map_size,
Packit c04fcb
		int shm_fd, int wakeup_fd,
Packit c04fcb
		int send_fd_only)
Packit c04fcb
{
Packit c04fcb
	ssize_t len;
Packit c04fcb
	int fds[2];
Packit c04fcb
Packit c04fcb
	if (!send_fd_only) {
Packit c04fcb
		if (shm_fd < 0) {
Packit c04fcb
			/* finish iteration */
Packit c04fcb
			uint64_t v = -1;
Packit c04fcb
Packit c04fcb
			len = ustcomm_send_unix_sock(sock, &v, sizeof(v));
Packit c04fcb
			if (len != sizeof(v)) {
Packit c04fcb
				if (len < 0)
Packit c04fcb
					return len;
Packit c04fcb
				else
Packit c04fcb
					return -EIO;
Packit c04fcb
			}
Packit c04fcb
			return 0;
Packit c04fcb
		}
Packit c04fcb
Packit c04fcb
		/* Send mmap size */
Packit c04fcb
		len = ustcomm_send_unix_sock(sock, &memory_map_size,
Packit c04fcb
			sizeof(memory_map_size));
Packit c04fcb
		if (len != sizeof(memory_map_size)) {
Packit c04fcb
			if (len < 0)
Packit c04fcb
				return len;
Packit c04fcb
			else
Packit c04fcb
				return -EIO;
Packit c04fcb
		}
Packit c04fcb
Packit c04fcb
		/* Send stream nr */
Packit c04fcb
		len = ustcomm_send_unix_sock(sock, &stream_nr,
Packit c04fcb
			sizeof(stream_nr));
Packit c04fcb
		if (len != sizeof(stream_nr)) {
Packit c04fcb
			if (len < 0)
Packit c04fcb
				return len;
Packit c04fcb
			else
Packit c04fcb
				return -EIO;
Packit c04fcb
		}
Packit c04fcb
	}
Packit c04fcb
Packit c04fcb
	/* Send shm fd and wakeup fd */
Packit c04fcb
	fds[0] = shm_fd;
Packit c04fcb
	fds[1] = wakeup_fd;
Packit c04fcb
	len = ustcomm_send_fds_unix_sock(sock, fds, 2);
Packit c04fcb
	if (len <= 0) {
Packit c04fcb
		if (len < 0)
Packit c04fcb
			return len;
Packit c04fcb
		else
Packit c04fcb
			return -EIO;
Packit c04fcb
	}
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_recv_channel_from_consumer(int sock,
Packit c04fcb
		struct lttng_ust_object_data **_channel_data)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_object_data *channel_data;
Packit c04fcb
	ssize_t len;
Packit c04fcb
	int wakeup_fd;
Packit c04fcb
	int ret;
Packit c04fcb
Packit c04fcb
	channel_data = zmalloc(sizeof(*channel_data));
Packit c04fcb
	if (!channel_data) {
Packit c04fcb
		ret = -ENOMEM;
Packit c04fcb
		goto error_alloc;
Packit c04fcb
	}
Packit c04fcb
	channel_data->type = LTTNG_UST_OBJECT_TYPE_CHANNEL;
Packit c04fcb
	channel_data->handle = -1;
Packit c04fcb
Packit c04fcb
	/* recv mmap size */
Packit c04fcb
	len = ustcomm_recv_unix_sock(sock, &channel_data->size,
Packit c04fcb
			sizeof(channel_data->size));
Packit c04fcb
	if (len != sizeof(channel_data->size)) {
Packit c04fcb
		if (len < 0)
Packit c04fcb
			ret = len;
Packit c04fcb
		else
Packit c04fcb
			ret = -EINVAL;
Packit c04fcb
		goto error;
Packit c04fcb
	}
Packit c04fcb
Packit c04fcb
	/* recv channel type */
Packit c04fcb
	len = ustcomm_recv_unix_sock(sock, &channel_data->u.channel.type,
Packit c04fcb
			sizeof(channel_data->u.channel.type));
Packit c04fcb
	if (len != sizeof(channel_data->u.channel.type)) {
Packit c04fcb
		if (len < 0)
Packit c04fcb
			ret = len;
Packit c04fcb
		else
Packit c04fcb
			ret = -EINVAL;
Packit c04fcb
		goto error;
Packit c04fcb
	}
Packit c04fcb
Packit c04fcb
	/* recv channel data */
Packit c04fcb
	channel_data->u.channel.data = zmalloc(channel_data->size);
Packit c04fcb
	if (!channel_data->u.channel.data) {
Packit c04fcb
		ret = -ENOMEM;
Packit c04fcb
		goto error;
Packit c04fcb
	}
Packit c04fcb
	len = ustcomm_recv_unix_sock(sock, channel_data->u.channel.data,
Packit c04fcb
			channel_data->size);
Packit c04fcb
	if (len != channel_data->size) {
Packit c04fcb
		if (len < 0)
Packit c04fcb
			ret = len;
Packit c04fcb
		else
Packit c04fcb
			ret = -EINVAL;
Packit c04fcb
		goto error_recv_data;
Packit c04fcb
	}
Packit c04fcb
	/* recv wakeup fd */
Packit c04fcb
	len = ustcomm_recv_fds_unix_sock(sock, &wakeup_fd, 1);
Packit c04fcb
	if (len <= 0) {
Packit c04fcb
		if (len < 0) {
Packit c04fcb
			ret = len;
Packit c04fcb
			goto error_recv_data;
Packit c04fcb
		} else {
Packit c04fcb
			ret = -EIO;
Packit c04fcb
			goto error_recv_data;
Packit c04fcb
		}
Packit c04fcb
	}
Packit c04fcb
	channel_data->u.channel.wakeup_fd = wakeup_fd;
Packit c04fcb
	*_channel_data = channel_data;
Packit c04fcb
	return 0;
Packit c04fcb
Packit c04fcb
error_recv_data:
Packit c04fcb
	free(channel_data->u.channel.data);
Packit c04fcb
error:
Packit c04fcb
	free(channel_data);
Packit c04fcb
error_alloc:
Packit c04fcb
	return ret;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_recv_stream_from_consumer(int sock,
Packit c04fcb
		struct lttng_ust_object_data **_stream_data)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_object_data *stream_data;
Packit c04fcb
	ssize_t len;
Packit c04fcb
	int ret;
Packit c04fcb
	int fds[2];
Packit c04fcb
Packit c04fcb
	stream_data = zmalloc(sizeof(*stream_data));
Packit c04fcb
	if (!stream_data) {
Packit c04fcb
		ret = -ENOMEM;
Packit c04fcb
		goto error_alloc;
Packit c04fcb
	}
Packit c04fcb
Packit c04fcb
	stream_data->type = LTTNG_UST_OBJECT_TYPE_STREAM;
Packit c04fcb
	stream_data->handle = -1;
Packit c04fcb
Packit c04fcb
	/* recv mmap size */
Packit c04fcb
	len = ustcomm_recv_unix_sock(sock, &stream_data->size,
Packit c04fcb
			sizeof(stream_data->size));
Packit c04fcb
	if (len != sizeof(stream_data->size)) {
Packit c04fcb
		if (len < 0)
Packit c04fcb
			ret = len;
Packit c04fcb
		else
Packit c04fcb
			ret = -EINVAL;
Packit c04fcb
		goto error;
Packit c04fcb
	}
Packit c04fcb
	if (stream_data->size == -1) {
Packit c04fcb
		ret = -LTTNG_UST_ERR_NOENT;
Packit c04fcb
		goto error;
Packit c04fcb
	}
Packit c04fcb
Packit c04fcb
	/* recv stream nr */
Packit c04fcb
	len = ustcomm_recv_unix_sock(sock, &stream_data->u.stream.stream_nr,
Packit c04fcb
			sizeof(stream_data->u.stream.stream_nr));
Packit c04fcb
	if (len != sizeof(stream_data->u.stream.stream_nr)) {
Packit c04fcb
		if (len < 0)
Packit c04fcb
			ret = len;
Packit c04fcb
		else
Packit c04fcb
			ret = -EINVAL;
Packit c04fcb
		goto error;
Packit c04fcb
	}
Packit c04fcb
Packit c04fcb
	/* recv shm fd and wakeup fd */
Packit c04fcb
	len = ustcomm_recv_fds_unix_sock(sock, fds, 2);
Packit c04fcb
	if (len <= 0) {
Packit c04fcb
		if (len < 0) {
Packit c04fcb
			ret = len;
Packit c04fcb
			goto error;
Packit c04fcb
		} else {
Packit c04fcb
			ret = -EIO;
Packit c04fcb
			goto error;
Packit c04fcb
		}
Packit c04fcb
	}
Packit c04fcb
	stream_data->u.stream.shm_fd = fds[0];
Packit c04fcb
	stream_data->u.stream.wakeup_fd = fds[1];
Packit c04fcb
	*_stream_data = stream_data;
Packit c04fcb
	return 0;
Packit c04fcb
Packit c04fcb
error:
Packit c04fcb
	free(stream_data);
Packit c04fcb
error_alloc:
Packit c04fcb
	return ret;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_send_channel_to_ust(int sock, int session_handle,
Packit c04fcb
		struct lttng_ust_object_data *channel_data)
Packit c04fcb
{
Packit c04fcb
	struct ustcomm_ust_msg lum;
Packit c04fcb
	struct ustcomm_ust_reply lur;
Packit c04fcb
	int ret;
Packit c04fcb
Packit c04fcb
	if (!channel_data)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
Packit c04fcb
	memset(&lum, 0, sizeof(lum));
Packit c04fcb
	lum.handle = session_handle;
Packit c04fcb
	lum.cmd = LTTNG_UST_CHANNEL;
Packit c04fcb
	lum.u.channel.len = channel_data->size;
Packit c04fcb
	lum.u.channel.type = channel_data->u.channel.type;
Packit c04fcb
	ret = ustcomm_send_app_msg(sock, &lum;;
Packit c04fcb
	if (ret)
Packit c04fcb
		return ret;
Packit c04fcb
Packit c04fcb
	ret = ustctl_send_channel(sock,
Packit c04fcb
			channel_data->u.channel.type,
Packit c04fcb
			channel_data->u.channel.data,
Packit c04fcb
			channel_data->size,
Packit c04fcb
			channel_data->u.channel.wakeup_fd,
Packit c04fcb
			1);
Packit c04fcb
	if (ret)
Packit c04fcb
		return ret;
Packit c04fcb
	ret = ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd);
Packit c04fcb
	if (!ret) {
Packit c04fcb
		channel_data->handle = lur.ret_val;
Packit c04fcb
	}
Packit c04fcb
	return ret;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_send_stream_to_ust(int sock,
Packit c04fcb
		struct lttng_ust_object_data *channel_data,
Packit c04fcb
		struct lttng_ust_object_data *stream_data)
Packit c04fcb
{
Packit c04fcb
	struct ustcomm_ust_msg lum;
Packit c04fcb
	struct ustcomm_ust_reply lur;
Packit c04fcb
	int ret;
Packit c04fcb
Packit c04fcb
	memset(&lum, 0, sizeof(lum));
Packit c04fcb
	lum.handle = channel_data->handle;
Packit c04fcb
	lum.cmd = LTTNG_UST_STREAM;
Packit c04fcb
	lum.u.stream.len = stream_data->size;
Packit c04fcb
	lum.u.stream.stream_nr = stream_data->u.stream.stream_nr;
Packit c04fcb
	ret = ustcomm_send_app_msg(sock, &lum;;
Packit c04fcb
	if (ret)
Packit c04fcb
		return ret;
Packit c04fcb
Packit c04fcb
	assert(stream_data);
Packit c04fcb
	assert(stream_data->type == LTTNG_UST_OBJECT_TYPE_STREAM);
Packit c04fcb
Packit c04fcb
	ret = ustctl_send_stream(sock,
Packit c04fcb
			stream_data->u.stream.stream_nr,
Packit c04fcb
			stream_data->size,
Packit c04fcb
			stream_data->u.stream.shm_fd,
Packit c04fcb
			stream_data->u.stream.wakeup_fd, 1);
Packit c04fcb
	if (ret)
Packit c04fcb
		return ret;
Packit c04fcb
	return ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_duplicate_ust_object_data(struct lttng_ust_object_data **dest,
Packit c04fcb
                struct lttng_ust_object_data *src)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_object_data *obj;
Packit c04fcb
	int ret;
Packit c04fcb
Packit c04fcb
	if (src->handle != -1) {
Packit c04fcb
		ret = -EINVAL;
Packit c04fcb
		goto error;
Packit c04fcb
	}
Packit c04fcb
Packit c04fcb
	obj = zmalloc(sizeof(*obj));
Packit c04fcb
	if (!obj) {
Packit c04fcb
		ret = -ENOMEM;
Packit c04fcb
		goto error;
Packit c04fcb
	}
Packit c04fcb
Packit c04fcb
	obj->type = src->type;
Packit c04fcb
	obj->handle = src->handle;
Packit c04fcb
	obj->size = src->size;
Packit c04fcb
Packit c04fcb
	switch (obj->type) {
Packit c04fcb
	case LTTNG_UST_OBJECT_TYPE_CHANNEL:
Packit c04fcb
	{
Packit c04fcb
		obj->u.channel.type = src->u.channel.type;
Packit c04fcb
		if (src->u.channel.wakeup_fd >= 0) {
Packit c04fcb
			obj->u.channel.wakeup_fd =
Packit c04fcb
				dup(src->u.channel.wakeup_fd);
Packit c04fcb
			if (obj->u.channel.wakeup_fd < 0) {
Packit c04fcb
				ret = errno;
Packit c04fcb
				goto chan_error_wakeup_fd;
Packit c04fcb
			}
Packit c04fcb
		} else {
Packit c04fcb
			obj->u.channel.wakeup_fd =
Packit c04fcb
				src->u.channel.wakeup_fd;
Packit c04fcb
		}
Packit c04fcb
		obj->u.channel.data = zmalloc(obj->size);
Packit c04fcb
		if (!obj->u.channel.data) {
Packit c04fcb
			ret = -ENOMEM;
Packit c04fcb
			goto chan_error_alloc;
Packit c04fcb
		}
Packit c04fcb
		memcpy(obj->u.channel.data, src->u.channel.data, obj->size);
Packit c04fcb
		break;
Packit c04fcb
Packit c04fcb
	chan_error_alloc:
Packit c04fcb
		if (src->u.channel.wakeup_fd >= 0) {
Packit c04fcb
			int closeret;
Packit c04fcb
Packit c04fcb
			closeret = close(obj->u.channel.wakeup_fd);
Packit c04fcb
			if (closeret) {
Packit c04fcb
				PERROR("close");
Packit c04fcb
			}
Packit c04fcb
		}
Packit c04fcb
	chan_error_wakeup_fd:
Packit c04fcb
		goto error_type;
Packit c04fcb
Packit c04fcb
	}
Packit c04fcb
Packit c04fcb
	case LTTNG_UST_OBJECT_TYPE_STREAM:
Packit c04fcb
	{
Packit c04fcb
		obj->u.stream.stream_nr = src->u.stream.stream_nr;
Packit c04fcb
		if (src->u.stream.wakeup_fd >= 0) {
Packit c04fcb
			obj->u.stream.wakeup_fd =
Packit c04fcb
				dup(src->u.stream.wakeup_fd);
Packit c04fcb
			if (obj->u.stream.wakeup_fd < 0) {
Packit c04fcb
				ret = errno;
Packit c04fcb
				goto stream_error_wakeup_fd;
Packit c04fcb
			}
Packit c04fcb
		} else {
Packit c04fcb
			obj->u.stream.wakeup_fd =
Packit c04fcb
				src->u.stream.wakeup_fd;
Packit c04fcb
		}
Packit c04fcb
Packit c04fcb
		if (src->u.stream.shm_fd >= 0) {
Packit c04fcb
			obj->u.stream.shm_fd =
Packit c04fcb
				dup(src->u.stream.shm_fd);
Packit c04fcb
			if (obj->u.stream.shm_fd < 0) {
Packit c04fcb
				ret = errno;
Packit c04fcb
				goto stream_error_shm_fd;
Packit c04fcb
			}
Packit c04fcb
		} else {
Packit c04fcb
			obj->u.stream.shm_fd =
Packit c04fcb
				src->u.stream.shm_fd;
Packit c04fcb
		}
Packit c04fcb
		break;
Packit c04fcb
Packit c04fcb
	stream_error_shm_fd:
Packit c04fcb
		if (src->u.stream.wakeup_fd >= 0) {
Packit c04fcb
			int closeret;
Packit c04fcb
Packit c04fcb
			closeret = close(obj->u.stream.wakeup_fd);
Packit c04fcb
			if (closeret) {
Packit c04fcb
				PERROR("close");
Packit c04fcb
			}
Packit c04fcb
		}
Packit c04fcb
	stream_error_wakeup_fd:
Packit c04fcb
		goto error_type;
Packit c04fcb
	}
Packit c04fcb
Packit c04fcb
	default:
Packit c04fcb
		ret = -EINVAL;
Packit c04fcb
		goto error_type;
Packit c04fcb
	}
Packit c04fcb
Packit c04fcb
	*dest = obj;
Packit c04fcb
	return 0;
Packit c04fcb
Packit c04fcb
error_type:
Packit c04fcb
	free(obj);
Packit c04fcb
error:
Packit c04fcb
	return ret;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
Packit c04fcb
/* Buffer operations */
Packit c04fcb
Packit c04fcb
int ustctl_get_nr_stream_per_channel(void)
Packit c04fcb
{
Packit c04fcb
	return num_possible_cpus();
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
struct ustctl_consumer_channel *
Packit c04fcb
	ustctl_create_channel(struct ustctl_consumer_channel_attr *attr,
Packit c04fcb
		const int *stream_fds, int nr_stream_fds)
Packit c04fcb
{
Packit c04fcb
	struct ustctl_consumer_channel *chan;
Packit c04fcb
	const char *transport_name;
Packit c04fcb
	struct lttng_transport *transport;
Packit c04fcb
Packit c04fcb
	switch (attr->type) {
Packit c04fcb
	case LTTNG_UST_CHAN_PER_CPU:
Packit c04fcb
		if (attr->output == LTTNG_UST_MMAP) {
Packit c04fcb
			if (attr->overwrite) {
Packit c04fcb
				if (attr->read_timer_interval == 0) {
Packit c04fcb
					transport_name = "relay-overwrite-mmap";
Packit c04fcb
				} else {
Packit c04fcb
					transport_name = "relay-overwrite-rt-mmap";
Packit c04fcb
				}
Packit c04fcb
			} else {
Packit c04fcb
				if (attr->read_timer_interval == 0) {
Packit c04fcb
					transport_name = "relay-discard-mmap";
Packit c04fcb
				} else {
Packit c04fcb
					transport_name = "relay-discard-rt-mmap";
Packit c04fcb
				}
Packit c04fcb
			}
Packit c04fcb
		} else {
Packit c04fcb
			return NULL;
Packit c04fcb
		}
Packit c04fcb
		break;
Packit c04fcb
	case LTTNG_UST_CHAN_METADATA:
Packit c04fcb
		if (attr->output == LTTNG_UST_MMAP)
Packit c04fcb
			transport_name = "relay-metadata-mmap";
Packit c04fcb
		else
Packit c04fcb
			return NULL;
Packit c04fcb
		break;
Packit c04fcb
	default:
Packit c04fcb
		transport_name = "<unknown>";
Packit c04fcb
		return NULL;
Packit c04fcb
	}
Packit c04fcb
Packit c04fcb
	transport = lttng_transport_find(transport_name);
Packit c04fcb
	if (!transport) {
Packit c04fcb
		DBG("LTTng transport %s not found\n",
Packit c04fcb
			transport_name);
Packit c04fcb
		return NULL;
Packit c04fcb
	}
Packit c04fcb
Packit c04fcb
	chan = zmalloc(sizeof(*chan));
Packit c04fcb
	if (!chan)
Packit c04fcb
		return NULL;
Packit c04fcb
Packit c04fcb
	chan->chan = transport->ops.channel_create(transport_name, NULL,
Packit c04fcb
			attr->subbuf_size, attr->num_subbuf,
Packit c04fcb
			attr->switch_timer_interval,
Packit c04fcb
			attr->read_timer_interval,
Packit c04fcb
			attr->uuid, attr->chan_id,
Packit c04fcb
			stream_fds, nr_stream_fds);
Packit c04fcb
	if (!chan->chan) {
Packit c04fcb
		goto chan_error;
Packit c04fcb
	}
Packit c04fcb
	chan->chan->ops = &transport->ops;
Packit c04fcb
	memcpy(&chan->attr, attr, sizeof(chan->attr));
Packit c04fcb
	chan->wait_fd = ustctl_channel_get_wait_fd(chan);
Packit c04fcb
	chan->wakeup_fd = ustctl_channel_get_wakeup_fd(chan);
Packit c04fcb
	return chan;
Packit c04fcb
Packit c04fcb
chan_error:
Packit c04fcb
	free(chan);
Packit c04fcb
	return NULL;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
void ustctl_destroy_channel(struct ustctl_consumer_channel *chan)
Packit c04fcb
{
Packit c04fcb
	(void) ustctl_channel_close_wait_fd(chan);
Packit c04fcb
	(void) ustctl_channel_close_wakeup_fd(chan);
Packit c04fcb
	chan->chan->ops->channel_destroy(chan->chan);
Packit c04fcb
	free(chan);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_send_channel_to_sessiond(int sock,
Packit c04fcb
		struct ustctl_consumer_channel *channel)
Packit c04fcb
{
Packit c04fcb
	struct shm_object_table *table;
Packit c04fcb
Packit c04fcb
	table = channel->chan->handle->table;
Packit c04fcb
	if (table->size <= 0)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	return ustctl_send_channel(sock,
Packit c04fcb
			channel->attr.type,
Packit c04fcb
			table->objects[0].memory_map,
Packit c04fcb
			table->objects[0].memory_map_size,
Packit c04fcb
			channel->wakeup_fd,
Packit c04fcb
			0);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_send_stream_to_sessiond(int sock,
Packit c04fcb
		struct ustctl_consumer_stream *stream)
Packit c04fcb
{
Packit c04fcb
	if (!stream)
Packit c04fcb
		return ustctl_send_stream(sock, -1U, -1U, -1, -1, 0);
Packit c04fcb
Packit c04fcb
	return ustctl_send_stream(sock,
Packit c04fcb
			stream->cpu,
Packit c04fcb
			stream->memory_map_size,
Packit c04fcb
			stream->shm_fd, stream->wakeup_fd,
Packit c04fcb
			0);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_write_metadata_to_channel(
Packit c04fcb
		struct ustctl_consumer_channel *channel,
Packit c04fcb
		const char *metadata_str,	/* NOT null-terminated */
Packit c04fcb
		size_t len)			/* metadata length */
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_lib_ring_buffer_ctx ctx;
Packit c04fcb
	struct lttng_channel *chan = channel->chan;
Packit c04fcb
	const char *str = metadata_str;
Packit c04fcb
	int ret = 0, waitret;
Packit c04fcb
	size_t reserve_len, pos;
Packit c04fcb
Packit c04fcb
	for (pos = 0; pos < len; pos += reserve_len) {
Packit c04fcb
		reserve_len = min_t(size_t,
Packit c04fcb
				chan->ops->packet_avail_size(chan->chan, chan->handle),
Packit c04fcb
				len - pos);
Packit c04fcb
		lib_ring_buffer_ctx_init(&ctx, chan->chan, NULL, reserve_len,
Packit c04fcb
					 sizeof(char), -1, chan->handle, NULL);
Packit c04fcb
		/*
Packit c04fcb
		 * We don't care about metadata buffer's records lost
Packit c04fcb
		 * count, because we always retry here. Report error if
Packit c04fcb
		 * we need to bail out after timeout or being
Packit c04fcb
		 * interrupted.
Packit c04fcb
		 */
Packit c04fcb
		waitret = wait_cond_interruptible_timeout(
Packit c04fcb
			({
Packit c04fcb
				ret = chan->ops->event_reserve(&ctx, 0);
Packit c04fcb
				ret != -ENOBUFS || !ret;
Packit c04fcb
			}),
Packit c04fcb
			LTTNG_METADATA_TIMEOUT_MSEC);
Packit c04fcb
		if (waitret == -ETIMEDOUT || waitret == -EINTR || ret) {
Packit c04fcb
			DBG("LTTng: Failure to write metadata to buffers (%s)\n",
Packit c04fcb
				waitret == -EINTR ? "interrupted" :
Packit c04fcb
					(ret == -ENOBUFS ? "timeout" : "I/O error"));
Packit c04fcb
			if (waitret == -EINTR)
Packit c04fcb
				ret = waitret;
Packit c04fcb
			goto end;
Packit c04fcb
		}
Packit c04fcb
		chan->ops->event_write(&ctx, &str[pos], reserve_len);
Packit c04fcb
		chan->ops->event_commit(&ctx;;
Packit c04fcb
	}
Packit c04fcb
end:
Packit c04fcb
	return ret;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
/*
Packit c04fcb
 * Write at most one packet in the channel.
Packit c04fcb
 * Returns the number of bytes written on success, < 0 on error.
Packit c04fcb
 */
Packit c04fcb
ssize_t ustctl_write_one_packet_to_channel(
Packit c04fcb
		struct ustctl_consumer_channel *channel,
Packit c04fcb
		const char *metadata_str,	/* NOT null-terminated */
Packit c04fcb
		size_t len)			/* metadata length */
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_lib_ring_buffer_ctx ctx;
Packit c04fcb
	struct lttng_channel *chan = channel->chan;
Packit c04fcb
	const char *str = metadata_str;
Packit c04fcb
	ssize_t reserve_len;
Packit c04fcb
	int ret;
Packit c04fcb
Packit c04fcb
	reserve_len = min_t(ssize_t,
Packit c04fcb
			chan->ops->packet_avail_size(chan->chan, chan->handle),
Packit c04fcb
			len);
Packit c04fcb
	lib_ring_buffer_ctx_init(&ctx, chan->chan, NULL, reserve_len,
Packit c04fcb
			sizeof(char), -1, chan->handle, NULL);
Packit c04fcb
	ret = chan->ops->event_reserve(&ctx, 0);
Packit c04fcb
	if (ret != 0) {
Packit c04fcb
		DBG("LTTng: event reservation failed");
Packit c04fcb
		assert(ret < 0);
Packit c04fcb
		reserve_len = ret;
Packit c04fcb
		goto end;
Packit c04fcb
	}
Packit c04fcb
	chan->ops->event_write(&ctx, str, reserve_len);
Packit c04fcb
	chan->ops->event_commit(&ctx;;
Packit c04fcb
Packit c04fcb
end:
Packit c04fcb
	return reserve_len;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_channel_close_wait_fd(struct ustctl_consumer_channel *consumer_chan)
Packit c04fcb
{
Packit c04fcb
	struct channel *chan;
Packit c04fcb
	int ret;
Packit c04fcb
Packit c04fcb
	chan = consumer_chan->chan->chan;
Packit c04fcb
	ret = ring_buffer_channel_close_wait_fd(&chan->backend.config,
Packit c04fcb
			chan, chan->handle);
Packit c04fcb
	if (!ret)
Packit c04fcb
		consumer_chan->wait_fd = -1;
Packit c04fcb
	return ret;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_channel_close_wakeup_fd(struct ustctl_consumer_channel *consumer_chan)
Packit c04fcb
{
Packit c04fcb
	struct channel *chan;
Packit c04fcb
	int ret;
Packit c04fcb
Packit c04fcb
	chan = consumer_chan->chan->chan;
Packit c04fcb
	ret = ring_buffer_channel_close_wakeup_fd(&chan->backend.config,
Packit c04fcb
			chan, chan->handle);
Packit c04fcb
	if (!ret)
Packit c04fcb
		consumer_chan->wakeup_fd = -1;
Packit c04fcb
	return ret;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_stream_close_wait_fd(struct ustctl_consumer_stream *stream)
Packit c04fcb
{
Packit c04fcb
	struct channel *chan;
Packit c04fcb
Packit c04fcb
	chan = stream->chan->chan->chan;
Packit c04fcb
	return ring_buffer_stream_close_wait_fd(&chan->backend.config,
Packit c04fcb
			chan, stream->handle, stream->cpu);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_stream_close_wakeup_fd(struct ustctl_consumer_stream *stream)
Packit c04fcb
{
Packit c04fcb
	struct channel *chan;
Packit c04fcb
Packit c04fcb
	chan = stream->chan->chan->chan;
Packit c04fcb
	return ring_buffer_stream_close_wakeup_fd(&chan->backend.config,
Packit c04fcb
			chan, stream->handle, stream->cpu);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
struct ustctl_consumer_stream *
Packit c04fcb
	ustctl_create_stream(struct ustctl_consumer_channel *channel,
Packit c04fcb
			int cpu)
Packit c04fcb
{
Packit c04fcb
	struct ustctl_consumer_stream *stream;
Packit c04fcb
	struct lttng_ust_shm_handle *handle;
Packit c04fcb
	struct channel *chan;
Packit c04fcb
	int shm_fd, wait_fd, wakeup_fd;
Packit c04fcb
	uint64_t memory_map_size;
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
	int ret;
Packit c04fcb
Packit c04fcb
	if (!channel)
Packit c04fcb
		return NULL;
Packit c04fcb
	handle = channel->chan->handle;
Packit c04fcb
	if (!handle)
Packit c04fcb
		return NULL;
Packit c04fcb
Packit c04fcb
	chan = channel->chan->chan;
Packit c04fcb
	buf = channel_get_ring_buffer(&chan->backend.config,
Packit c04fcb
		chan, cpu, handle, &shm_fd, &wait_fd,
Packit c04fcb
		&wakeup_fd, &memory_map_size);
Packit c04fcb
	if (!buf)
Packit c04fcb
		return NULL;
Packit c04fcb
	ret = lib_ring_buffer_open_read(buf, handle);
Packit c04fcb
	if (ret)
Packit c04fcb
		return NULL;
Packit c04fcb
Packit c04fcb
	stream = zmalloc(sizeof(*stream));
Packit c04fcb
	if (!stream)
Packit c04fcb
		goto alloc_error;
Packit c04fcb
	stream->handle = handle;
Packit c04fcb
	stream->buf = buf;
Packit c04fcb
	stream->chan = channel;
Packit c04fcb
	stream->shm_fd = shm_fd;
Packit c04fcb
	stream->wait_fd = wait_fd;
Packit c04fcb
	stream->wakeup_fd = wakeup_fd;
Packit c04fcb
	stream->memory_map_size = memory_map_size;
Packit c04fcb
	stream->cpu = cpu;
Packit c04fcb
	return stream;
Packit c04fcb
Packit c04fcb
alloc_error:
Packit c04fcb
	return NULL;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
void ustctl_destroy_stream(struct ustctl_consumer_stream *stream)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
	struct ustctl_consumer_channel *consumer_chan;
Packit c04fcb
Packit c04fcb
	assert(stream);
Packit c04fcb
	buf = stream->buf;
Packit c04fcb
	consumer_chan = stream->chan;
Packit c04fcb
	(void) ustctl_stream_close_wait_fd(stream);
Packit c04fcb
	(void) ustctl_stream_close_wakeup_fd(stream);
Packit c04fcb
	lib_ring_buffer_release_read(buf, consumer_chan->chan->handle);
Packit c04fcb
	free(stream);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_channel_get_wait_fd(struct ustctl_consumer_channel *chan)
Packit c04fcb
{
Packit c04fcb
	if (!chan)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	return shm_get_wait_fd(chan->chan->handle,
Packit c04fcb
		&chan->chan->handle->chan._ref);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_channel_get_wakeup_fd(struct ustctl_consumer_channel *chan)
Packit c04fcb
{
Packit c04fcb
	if (!chan)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	return shm_get_wakeup_fd(chan->chan->handle,
Packit c04fcb
		&chan->chan->handle->chan._ref);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_stream_get_wait_fd(struct ustctl_consumer_stream *stream)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
	struct ustctl_consumer_channel *consumer_chan;
Packit c04fcb
Packit c04fcb
	if (!stream)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	buf = stream->buf;
Packit c04fcb
	consumer_chan = stream->chan;
Packit c04fcb
	return shm_get_wait_fd(consumer_chan->chan->handle, &buf->self._ref);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_stream_get_wakeup_fd(struct ustctl_consumer_stream *stream)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
	struct ustctl_consumer_channel *consumer_chan;
Packit c04fcb
Packit c04fcb
	if (!stream)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	buf = stream->buf;
Packit c04fcb
	consumer_chan = stream->chan;
Packit c04fcb
	return shm_get_wakeup_fd(consumer_chan->chan->handle, &buf->self._ref);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
/* For mmap mode, readable without "get" operation */
Packit c04fcb
Packit c04fcb
void *ustctl_get_mmap_base(struct ustctl_consumer_stream *stream)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
	struct ustctl_consumer_channel *consumer_chan;
Packit c04fcb
Packit c04fcb
	if (!stream)
Packit c04fcb
		return NULL;
Packit c04fcb
	buf = stream->buf;
Packit c04fcb
	consumer_chan = stream->chan;
Packit c04fcb
	return shmp(consumer_chan->chan->handle, buf->backend.memory_map);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
/* returns the length to mmap. */
Packit c04fcb
int ustctl_get_mmap_len(struct ustctl_consumer_stream *stream,
Packit c04fcb
		unsigned long *len)
Packit c04fcb
{
Packit c04fcb
	struct ustctl_consumer_channel *consumer_chan;
Packit c04fcb
	unsigned long mmap_buf_len;
Packit c04fcb
	struct channel *chan;
Packit c04fcb
Packit c04fcb
	if (!stream)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	consumer_chan = stream->chan;
Packit c04fcb
	chan = consumer_chan->chan->chan;
Packit c04fcb
	if (chan->backend.config.output != RING_BUFFER_MMAP)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	mmap_buf_len = chan->backend.buf_size;
Packit c04fcb
	if (chan->backend.extra_reader_sb)
Packit c04fcb
		mmap_buf_len += chan->backend.subbuf_size;
Packit c04fcb
	if (mmap_buf_len > INT_MAX)
Packit c04fcb
		return -EFBIG;
Packit c04fcb
	*len = mmap_buf_len;
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
/* returns the maximum size for sub-buffers. */
Packit c04fcb
int ustctl_get_max_subbuf_size(struct ustctl_consumer_stream *stream,
Packit c04fcb
		unsigned long *len)
Packit c04fcb
{
Packit c04fcb
	struct ustctl_consumer_channel *consumer_chan;
Packit c04fcb
	struct channel *chan;
Packit c04fcb
Packit c04fcb
	if (!stream)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	consumer_chan = stream->chan;
Packit c04fcb
	chan = consumer_chan->chan->chan;
Packit c04fcb
	*len = chan->backend.subbuf_size;
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
/*
Packit c04fcb
 * For mmap mode, operate on the current packet (between get/put or
Packit c04fcb
 * get_next/put_next).
Packit c04fcb
 */
Packit c04fcb
Packit c04fcb
/* returns the offset of the subbuffer belonging to the mmap reader. */
Packit c04fcb
int ustctl_get_mmap_read_offset(struct ustctl_consumer_stream *stream,
Packit c04fcb
		unsigned long *off)
Packit c04fcb
{
Packit c04fcb
	struct channel *chan;
Packit c04fcb
	unsigned long sb_bindex;
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
	struct ustctl_consumer_channel *consumer_chan;
Packit c04fcb
	struct lttng_ust_lib_ring_buffer_backend_pages_shmp *barray_idx;
Packit c04fcb
	struct lttng_ust_lib_ring_buffer_backend_pages *pages;
Packit c04fcb
Packit c04fcb
	if (!stream)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	buf = stream->buf;
Packit c04fcb
	consumer_chan = stream->chan;
Packit c04fcb
	chan = consumer_chan->chan->chan;
Packit c04fcb
	if (chan->backend.config.output != RING_BUFFER_MMAP)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	sb_bindex = subbuffer_id_get_index(&chan->backend.config,
Packit c04fcb
					buf->backend.buf_rsb.id);
Packit c04fcb
	barray_idx = shmp_index(consumer_chan->chan->handle, buf->backend.array,
Packit c04fcb
			sb_bindex);
Packit c04fcb
	if (!barray_idx)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	pages = shmp(consumer_chan->chan->handle, barray_idx->shmp);
Packit c04fcb
	if (!pages)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	*off = pages->mmap_offset;
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
/* returns the size of the current sub-buffer, without padding (for mmap). */
Packit c04fcb
int ustctl_get_subbuf_size(struct ustctl_consumer_stream *stream,
Packit c04fcb
		unsigned long *len)
Packit c04fcb
{
Packit c04fcb
	struct ustctl_consumer_channel *consumer_chan;
Packit c04fcb
	struct channel *chan;
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
Packit c04fcb
	if (!stream)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
Packit c04fcb
	buf = stream->buf;
Packit c04fcb
	consumer_chan = stream->chan;
Packit c04fcb
	chan = consumer_chan->chan->chan;
Packit c04fcb
	*len = lib_ring_buffer_get_read_data_size(&chan->backend.config, buf,
Packit c04fcb
		consumer_chan->chan->handle);
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
/* returns the size of the current sub-buffer, without padding (for mmap). */
Packit c04fcb
int ustctl_get_padded_subbuf_size(struct ustctl_consumer_stream *stream,
Packit c04fcb
		unsigned long *len)
Packit c04fcb
{
Packit c04fcb
	struct ustctl_consumer_channel *consumer_chan;
Packit c04fcb
	struct channel *chan;
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
Packit c04fcb
	if (!stream)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	buf = stream->buf;
Packit c04fcb
	consumer_chan = stream->chan;
Packit c04fcb
	chan = consumer_chan->chan->chan;
Packit c04fcb
	*len = lib_ring_buffer_get_read_data_size(&chan->backend.config, buf,
Packit c04fcb
		consumer_chan->chan->handle);
Packit c04fcb
	*len = PAGE_ALIGN(*len);
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
/* Get exclusive read access to the next sub-buffer that can be read. */
Packit c04fcb
int ustctl_get_next_subbuf(struct ustctl_consumer_stream *stream)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
	struct ustctl_consumer_channel *consumer_chan;
Packit c04fcb
Packit c04fcb
	if (!stream)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	buf = stream->buf;
Packit c04fcb
	consumer_chan = stream->chan;
Packit c04fcb
	return lib_ring_buffer_get_next_subbuf(buf,
Packit c04fcb
			consumer_chan->chan->handle);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
Packit c04fcb
/* Release exclusive sub-buffer access, move consumer forward. */
Packit c04fcb
int ustctl_put_next_subbuf(struct ustctl_consumer_stream *stream)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
	struct ustctl_consumer_channel *consumer_chan;
Packit c04fcb
Packit c04fcb
	if (!stream)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	buf = stream->buf;
Packit c04fcb
	consumer_chan = stream->chan;
Packit c04fcb
	lib_ring_buffer_put_next_subbuf(buf, consumer_chan->chan->handle);
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
/* snapshot */
Packit c04fcb
Packit c04fcb
/* Get a snapshot of the current ring buffer producer and consumer positions */
Packit c04fcb
int ustctl_snapshot(struct ustctl_consumer_stream *stream)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
	struct ustctl_consumer_channel *consumer_chan;
Packit c04fcb
Packit c04fcb
	if (!stream)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	buf = stream->buf;
Packit c04fcb
	consumer_chan = stream->chan;
Packit c04fcb
	return lib_ring_buffer_snapshot(buf, &buf->cons_snapshot,
Packit c04fcb
			&buf->prod_snapshot, consumer_chan->chan->handle);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
/* Get the consumer position (iteration start) */
Packit c04fcb
int ustctl_snapshot_get_consumed(struct ustctl_consumer_stream *stream,
Packit c04fcb
		unsigned long *pos)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
Packit c04fcb
	if (!stream)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	buf = stream->buf;
Packit c04fcb
	*pos = buf->cons_snapshot;
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
/* Get the producer position (iteration end) */
Packit c04fcb
int ustctl_snapshot_get_produced(struct ustctl_consumer_stream *stream,
Packit c04fcb
		unsigned long *pos)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
Packit c04fcb
	if (!stream)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	buf = stream->buf;
Packit c04fcb
	*pos = buf->prod_snapshot;
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
/* Get exclusive read access to the specified sub-buffer position */
Packit c04fcb
int ustctl_get_subbuf(struct ustctl_consumer_stream *stream,
Packit c04fcb
		unsigned long *pos)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
	struct ustctl_consumer_channel *consumer_chan;
Packit c04fcb
Packit c04fcb
	if (!stream)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	buf = stream->buf;
Packit c04fcb
	consumer_chan = stream->chan;
Packit c04fcb
	return lib_ring_buffer_get_subbuf(buf, *pos,
Packit c04fcb
			consumer_chan->chan->handle);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
/* Release exclusive sub-buffer access */
Packit c04fcb
int ustctl_put_subbuf(struct ustctl_consumer_stream *stream)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
	struct ustctl_consumer_channel *consumer_chan;
Packit c04fcb
Packit c04fcb
	if (!stream)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	buf = stream->buf;
Packit c04fcb
	consumer_chan = stream->chan;
Packit c04fcb
	lib_ring_buffer_put_subbuf(buf, consumer_chan->chan->handle);
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
void ustctl_flush_buffer(struct ustctl_consumer_stream *stream,
Packit c04fcb
		int producer_active)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
	struct ustctl_consumer_channel *consumer_chan;
Packit c04fcb
Packit c04fcb
	assert(stream);
Packit c04fcb
	buf = stream->buf;
Packit c04fcb
	consumer_chan = stream->chan;
Packit c04fcb
	lib_ring_buffer_switch_slow(buf,
Packit c04fcb
		producer_active ? SWITCH_ACTIVE : SWITCH_FLUSH,
Packit c04fcb
		consumer_chan->chan->handle);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
static
Packit c04fcb
struct lttng_ust_client_lib_ring_buffer_client_cb *get_client_cb(
Packit c04fcb
		struct lttng_ust_lib_ring_buffer *buf,
Packit c04fcb
		struct lttng_ust_shm_handle *handle)
Packit c04fcb
{
Packit c04fcb
	struct channel *chan;
Packit c04fcb
	const struct lttng_ust_lib_ring_buffer_config *config;
Packit c04fcb
	struct lttng_ust_client_lib_ring_buffer_client_cb *client_cb;
Packit c04fcb
Packit c04fcb
	chan = shmp(handle, buf->backend.chan);
Packit c04fcb
	if (!chan)
Packit c04fcb
		return NULL;
Packit c04fcb
	config = &chan->backend.config;
Packit c04fcb
	if (!config->cb_ptr)
Packit c04fcb
		return NULL;
Packit c04fcb
	client_cb = caa_container_of(config->cb_ptr,
Packit c04fcb
			struct lttng_ust_client_lib_ring_buffer_client_cb,
Packit c04fcb
			parent);
Packit c04fcb
	return client_cb;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_get_timestamp_begin(struct ustctl_consumer_stream *stream,
Packit c04fcb
		uint64_t *timestamp_begin)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_client_lib_ring_buffer_client_cb *client_cb;
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
	struct lttng_ust_shm_handle *handle;
Packit c04fcb
Packit c04fcb
	if (!stream || !timestamp_begin)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	buf = stream->buf;
Packit c04fcb
	handle = stream->chan->chan->handle;
Packit c04fcb
	client_cb = get_client_cb(buf, handle);
Packit c04fcb
	if (!client_cb)
Packit c04fcb
		return -ENOSYS;
Packit c04fcb
	return client_cb->timestamp_begin(buf, handle, timestamp_begin);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_get_timestamp_end(struct ustctl_consumer_stream *stream,
Packit c04fcb
	uint64_t *timestamp_end)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_client_lib_ring_buffer_client_cb *client_cb;
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
	struct lttng_ust_shm_handle *handle;
Packit c04fcb
Packit c04fcb
	if (!stream || !timestamp_end)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	buf = stream->buf;
Packit c04fcb
	handle = stream->chan->chan->handle;
Packit c04fcb
	client_cb = get_client_cb(buf, handle);
Packit c04fcb
	if (!client_cb)
Packit c04fcb
		return -ENOSYS;
Packit c04fcb
	return client_cb->timestamp_end(buf, handle, timestamp_end);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_get_events_discarded(struct ustctl_consumer_stream *stream,
Packit c04fcb
	uint64_t *events_discarded)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_client_lib_ring_buffer_client_cb *client_cb;
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
	struct lttng_ust_shm_handle *handle;
Packit c04fcb
Packit c04fcb
	if (!stream || !events_discarded)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	buf = stream->buf;
Packit c04fcb
	handle = stream->chan->chan->handle;
Packit c04fcb
	client_cb = get_client_cb(buf, handle);
Packit c04fcb
	if (!client_cb)
Packit c04fcb
		return -ENOSYS;
Packit c04fcb
	return client_cb->events_discarded(buf, handle, events_discarded);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_get_content_size(struct ustctl_consumer_stream *stream,
Packit c04fcb
	uint64_t *content_size)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_client_lib_ring_buffer_client_cb *client_cb;
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
	struct lttng_ust_shm_handle *handle;
Packit c04fcb
Packit c04fcb
	if (!stream || !content_size)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	buf = stream->buf;
Packit c04fcb
	handle = stream->chan->chan->handle;
Packit c04fcb
	client_cb = get_client_cb(buf, handle);
Packit c04fcb
	if (!client_cb)
Packit c04fcb
		return -ENOSYS;
Packit c04fcb
	return client_cb->content_size(buf, handle, content_size);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_get_packet_size(struct ustctl_consumer_stream *stream,
Packit c04fcb
	uint64_t *packet_size)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_client_lib_ring_buffer_client_cb *client_cb;
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
	struct lttng_ust_shm_handle *handle;
Packit c04fcb
Packit c04fcb
	if (!stream || !packet_size)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	buf = stream->buf;
Packit c04fcb
	handle = stream->chan->chan->handle;
Packit c04fcb
	client_cb = get_client_cb(buf, handle);
Packit c04fcb
	if (!client_cb)
Packit c04fcb
		return -ENOSYS;
Packit c04fcb
	return client_cb->packet_size(buf, handle, packet_size);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_get_stream_id(struct ustctl_consumer_stream *stream,
Packit c04fcb
		uint64_t *stream_id)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_client_lib_ring_buffer_client_cb *client_cb;
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
	struct lttng_ust_shm_handle *handle;
Packit c04fcb
Packit c04fcb
	if (!stream || !stream_id)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	buf = stream->buf;
Packit c04fcb
	handle = stream->chan->chan->handle;
Packit c04fcb
	client_cb = get_client_cb(buf, handle);
Packit c04fcb
	if (!client_cb)
Packit c04fcb
		return -ENOSYS;
Packit c04fcb
	return client_cb->stream_id(buf, handle, stream_id);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_get_current_timestamp(struct ustctl_consumer_stream *stream,
Packit c04fcb
		uint64_t *ts)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_client_lib_ring_buffer_client_cb *client_cb;
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
	struct lttng_ust_shm_handle *handle;
Packit c04fcb
Packit c04fcb
	if (!stream || !ts)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	buf = stream->buf;
Packit c04fcb
	handle = stream->chan->chan->handle;
Packit c04fcb
	client_cb = get_client_cb(buf, handle);
Packit c04fcb
	if (!client_cb || !client_cb->current_timestamp)
Packit c04fcb
		return -ENOSYS;
Packit c04fcb
	return client_cb->current_timestamp(buf, handle, ts);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_get_sequence_number(struct ustctl_consumer_stream *stream,
Packit c04fcb
		uint64_t *seq)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_client_lib_ring_buffer_client_cb *client_cb;
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
	struct lttng_ust_shm_handle *handle;
Packit c04fcb
Packit c04fcb
	if (!stream || !seq)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	buf = stream->buf;
Packit c04fcb
	handle = stream->chan->chan->handle;
Packit c04fcb
	client_cb = get_client_cb(buf, handle);
Packit c04fcb
	if (!client_cb || !client_cb->sequence_number)
Packit c04fcb
		return -ENOSYS;
Packit c04fcb
	return client_cb->sequence_number(buf, handle, seq);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_get_instance_id(struct ustctl_consumer_stream *stream,
Packit c04fcb
		uint64_t *id)
Packit c04fcb
{
Packit c04fcb
	struct lttng_ust_client_lib_ring_buffer_client_cb *client_cb;
Packit c04fcb
	struct lttng_ust_lib_ring_buffer *buf;
Packit c04fcb
	struct lttng_ust_shm_handle *handle;
Packit c04fcb
Packit c04fcb
	if (!stream || !id)
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	buf = stream->buf;
Packit c04fcb
	handle = stream->chan->chan->handle;
Packit c04fcb
	client_cb = get_client_cb(buf, handle);
Packit c04fcb
	if (!client_cb)
Packit c04fcb
		return -ENOSYS;
Packit c04fcb
	return client_cb->instance_id(buf, handle, id);
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
#if defined(__x86_64__) || defined(__i386__)
Packit c04fcb
Packit c04fcb
int ustctl_has_perf_counters(void)
Packit c04fcb
{
Packit c04fcb
	return 1;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
#else
Packit c04fcb
Packit c04fcb
int ustctl_has_perf_counters(void)
Packit c04fcb
{
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
#endif
Packit c04fcb
Packit c04fcb
/*
Packit c04fcb
 * Returns 0 on success, negative error value on error.
Packit c04fcb
 */
Packit c04fcb
int ustctl_recv_reg_msg(int sock,
Packit c04fcb
	enum ustctl_socket_type *type,
Packit c04fcb
	uint32_t *major,
Packit c04fcb
	uint32_t *minor,
Packit c04fcb
	uint32_t *pid,
Packit c04fcb
	uint32_t *ppid,
Packit c04fcb
	uint32_t *uid,
Packit c04fcb
	uint32_t *gid,
Packit c04fcb
	uint32_t *bits_per_long,
Packit c04fcb
	uint32_t *uint8_t_alignment,
Packit c04fcb
	uint32_t *uint16_t_alignment,
Packit c04fcb
	uint32_t *uint32_t_alignment,
Packit c04fcb
	uint32_t *uint64_t_alignment,
Packit c04fcb
	uint32_t *long_alignment,
Packit c04fcb
	int *byte_order,
Packit c04fcb
	char *name)
Packit c04fcb
{
Packit c04fcb
	ssize_t len;
Packit c04fcb
	struct ustctl_reg_msg reg_msg;
Packit c04fcb
Packit c04fcb
	len = ustcomm_recv_unix_sock(sock, &reg_msg, sizeof(reg_msg));
Packit c04fcb
	if (len > 0 && len != sizeof(reg_msg))
Packit c04fcb
		return -EIO;
Packit c04fcb
	if (len == 0)
Packit c04fcb
		return -EPIPE;
Packit c04fcb
	if (len < 0)
Packit c04fcb
		return len;
Packit c04fcb
Packit c04fcb
	if (reg_msg.magic == LTTNG_UST_COMM_MAGIC) {
Packit c04fcb
		*byte_order = BYTE_ORDER == BIG_ENDIAN ?
Packit c04fcb
				BIG_ENDIAN : LITTLE_ENDIAN;
Packit c04fcb
	} else if (reg_msg.magic == bswap_32(LTTNG_UST_COMM_MAGIC)) {
Packit c04fcb
		*byte_order = BYTE_ORDER == BIG_ENDIAN ?
Packit c04fcb
				LITTLE_ENDIAN : BIG_ENDIAN;
Packit c04fcb
	} else {
Packit c04fcb
		return -LTTNG_UST_ERR_INVAL_MAGIC;
Packit c04fcb
	}
Packit c04fcb
	switch (reg_msg.socket_type) {
Packit c04fcb
	case 0:	*type = USTCTL_SOCKET_CMD;
Packit c04fcb
		break;
Packit c04fcb
	case 1:	*type = USTCTL_SOCKET_NOTIFY;
Packit c04fcb
		break;
Packit c04fcb
	default:
Packit c04fcb
		return -LTTNG_UST_ERR_INVAL_SOCKET_TYPE;
Packit c04fcb
	}
Packit c04fcb
	*major = reg_msg.major;
Packit c04fcb
	*minor = reg_msg.minor;
Packit c04fcb
	*pid = reg_msg.pid;
Packit c04fcb
	*ppid = reg_msg.ppid;
Packit c04fcb
	*uid = reg_msg.uid;
Packit c04fcb
	*gid = reg_msg.gid;
Packit c04fcb
	*bits_per_long = reg_msg.bits_per_long;
Packit c04fcb
	*uint8_t_alignment = reg_msg.uint8_t_alignment;
Packit c04fcb
	*uint16_t_alignment = reg_msg.uint16_t_alignment;
Packit c04fcb
	*uint32_t_alignment = reg_msg.uint32_t_alignment;
Packit c04fcb
	*uint64_t_alignment = reg_msg.uint64_t_alignment;
Packit c04fcb
	*long_alignment = reg_msg.long_alignment;
Packit c04fcb
	memcpy(name, reg_msg.name, LTTNG_UST_ABI_PROCNAME_LEN);
Packit c04fcb
	if (reg_msg.major != LTTNG_UST_ABI_MAJOR_VERSION) {
Packit c04fcb
		return -LTTNG_UST_ERR_UNSUP_MAJOR;
Packit c04fcb
	}
Packit c04fcb
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
int ustctl_recv_notify(int sock, enum ustctl_notify_cmd *notify_cmd)
Packit c04fcb
{
Packit c04fcb
	struct ustcomm_notify_hdr header;
Packit c04fcb
	ssize_t len;
Packit c04fcb
Packit c04fcb
	len = ustcomm_recv_unix_sock(sock, &header, sizeof(header));
Packit c04fcb
	if (len > 0 && len != sizeof(header))
Packit c04fcb
		return -EIO;
Packit c04fcb
	if (len == 0)
Packit c04fcb
		return -EPIPE;
Packit c04fcb
	if (len < 0)
Packit c04fcb
		return len;
Packit c04fcb
	switch (header.notify_cmd) {
Packit c04fcb
	case 0:
Packit c04fcb
		*notify_cmd = USTCTL_NOTIFY_CMD_EVENT;
Packit c04fcb
		break;
Packit c04fcb
	case 1:
Packit c04fcb
		*notify_cmd = USTCTL_NOTIFY_CMD_CHANNEL;
Packit c04fcb
		break;
Packit c04fcb
	case 2:
Packit c04fcb
		*notify_cmd = USTCTL_NOTIFY_CMD_ENUM;
Packit c04fcb
		break;
Packit c04fcb
	default:
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	}
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
/*
Packit c04fcb
 * Returns 0 on success, negative error value on error.
Packit c04fcb
 */
Packit c04fcb
int ustctl_recv_register_event(int sock,
Packit c04fcb
	int *session_objd,
Packit c04fcb
	int *channel_objd,
Packit c04fcb
	char *event_name,
Packit c04fcb
	int *loglevel,
Packit c04fcb
	char **signature,
Packit c04fcb
	size_t *nr_fields,
Packit c04fcb
	struct ustctl_field **fields,
Packit c04fcb
	char **model_emf_uri)
Packit c04fcb
{
Packit c04fcb
	ssize_t len;
Packit c04fcb
	struct ustcomm_notify_event_msg msg;
Packit c04fcb
	size_t signature_len, fields_len, model_emf_uri_len;
Packit c04fcb
	char *a_sign = NULL, *a_model_emf_uri = NULL;
Packit c04fcb
	struct ustctl_field *a_fields = NULL;
Packit c04fcb
Packit c04fcb
	len = ustcomm_recv_unix_sock(sock, &msg, sizeof(msg));
Packit c04fcb
	if (len > 0 && len != sizeof(msg))
Packit c04fcb
		return -EIO;
Packit c04fcb
	if (len == 0)
Packit c04fcb
		return -EPIPE;
Packit c04fcb
	if (len < 0)
Packit c04fcb
		return len;
Packit c04fcb
Packit c04fcb
	*session_objd = msg.session_objd;
Packit c04fcb
	*channel_objd = msg.channel_objd;
Packit c04fcb
	strncpy(event_name, msg.event_name, LTTNG_UST_SYM_NAME_LEN);
Packit c04fcb
	event_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
Packit c04fcb
	*loglevel = msg.loglevel;
Packit c04fcb
	signature_len = msg.signature_len;
Packit c04fcb
	fields_len = msg.fields_len;
Packit c04fcb
Packit c04fcb
	if (fields_len % sizeof(*a_fields) != 0) {
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	}
Packit c04fcb
Packit c04fcb
	model_emf_uri_len = msg.model_emf_uri_len;
Packit c04fcb
Packit c04fcb
	/* recv signature. contains at least \0. */
Packit c04fcb
	a_sign = zmalloc(signature_len);
Packit c04fcb
	if (!a_sign)
Packit c04fcb
		return -ENOMEM;
Packit c04fcb
	len = ustcomm_recv_unix_sock(sock, a_sign, signature_len);
Packit c04fcb
	if (len > 0 && len != signature_len) {
Packit c04fcb
		len = -EIO;
Packit c04fcb
		goto signature_error;
Packit c04fcb
	}
Packit c04fcb
	if (len == 0) {
Packit c04fcb
		len = -EPIPE;
Packit c04fcb
		goto signature_error;
Packit c04fcb
	}
Packit c04fcb
	if (len < 0) {
Packit c04fcb
		goto signature_error;
Packit c04fcb
	}
Packit c04fcb
	/* Enforce end of string */
Packit c04fcb
	a_sign[signature_len - 1] = '\0';
Packit c04fcb
Packit c04fcb
	/* recv fields */
Packit c04fcb
	if (fields_len) {
Packit c04fcb
		a_fields = zmalloc(fields_len);
Packit c04fcb
		if (!a_fields) {
Packit c04fcb
			len = -ENOMEM;
Packit c04fcb
			goto signature_error;
Packit c04fcb
		}
Packit c04fcb
		len = ustcomm_recv_unix_sock(sock, a_fields, fields_len);
Packit c04fcb
		if (len > 0 && len != fields_len) {
Packit c04fcb
			len = -EIO;
Packit c04fcb
			goto fields_error;
Packit c04fcb
		}
Packit c04fcb
		if (len == 0) {
Packit c04fcb
			len = -EPIPE;
Packit c04fcb
			goto fields_error;
Packit c04fcb
		}
Packit c04fcb
		if (len < 0) {
Packit c04fcb
			goto fields_error;
Packit c04fcb
		}
Packit c04fcb
	}
Packit c04fcb
Packit c04fcb
	if (model_emf_uri_len) {
Packit c04fcb
		/* recv model_emf_uri_len */
Packit c04fcb
		a_model_emf_uri = zmalloc(model_emf_uri_len);
Packit c04fcb
		if (!a_model_emf_uri) {
Packit c04fcb
			len = -ENOMEM;
Packit c04fcb
			goto fields_error;
Packit c04fcb
		}
Packit c04fcb
		len = ustcomm_recv_unix_sock(sock, a_model_emf_uri,
Packit c04fcb
				model_emf_uri_len);
Packit c04fcb
		if (len > 0 && len != model_emf_uri_len) {
Packit c04fcb
			len = -EIO;
Packit c04fcb
			goto model_error;
Packit c04fcb
		}
Packit c04fcb
		if (len == 0) {
Packit c04fcb
			len = -EPIPE;
Packit c04fcb
			goto model_error;
Packit c04fcb
		}
Packit c04fcb
		if (len < 0) {
Packit c04fcb
			goto model_error;
Packit c04fcb
		}
Packit c04fcb
		/* Enforce end of string */
Packit c04fcb
		a_model_emf_uri[model_emf_uri_len - 1] = '\0';
Packit c04fcb
	}
Packit c04fcb
Packit c04fcb
	*signature = a_sign;
Packit c04fcb
	*nr_fields = fields_len / sizeof(*a_fields);
Packit c04fcb
	*fields = a_fields;
Packit c04fcb
	*model_emf_uri = a_model_emf_uri;
Packit c04fcb
Packit c04fcb
	return 0;
Packit c04fcb
Packit c04fcb
model_error:
Packit c04fcb
	free(a_model_emf_uri);
Packit c04fcb
fields_error:
Packit c04fcb
	free(a_fields);
Packit c04fcb
signature_error:
Packit c04fcb
	free(a_sign);
Packit c04fcb
	return len;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
/*
Packit c04fcb
 * Returns 0 on success, negative error value on error.
Packit c04fcb
 */
Packit c04fcb
int ustctl_reply_register_event(int sock,
Packit c04fcb
	uint32_t id,
Packit c04fcb
	int ret_code)
Packit c04fcb
{
Packit c04fcb
	ssize_t len;
Packit c04fcb
	struct {
Packit c04fcb
		struct ustcomm_notify_hdr header;
Packit c04fcb
		struct ustcomm_notify_event_reply r;
Packit c04fcb
	} reply;
Packit c04fcb
Packit c04fcb
	memset(&reply, 0, sizeof(reply));
Packit c04fcb
	reply.header.notify_cmd = USTCTL_NOTIFY_CMD_EVENT;
Packit c04fcb
	reply.r.ret_code = ret_code;
Packit c04fcb
	reply.r.event_id = id;
Packit c04fcb
	len = ustcomm_send_unix_sock(sock, &reply, sizeof(reply));
Packit c04fcb
	if (len > 0 && len != sizeof(reply))
Packit c04fcb
		return -EIO;
Packit c04fcb
	if (len < 0)
Packit c04fcb
		return len;
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
/*
Packit c04fcb
 * Returns 0 on success, negative UST or system error value on error.
Packit c04fcb
 */
Packit c04fcb
int ustctl_recv_register_enum(int sock,
Packit c04fcb
	int *session_objd,
Packit c04fcb
	char *enum_name,
Packit c04fcb
	struct ustctl_enum_entry **entries,
Packit c04fcb
	size_t *nr_entries)
Packit c04fcb
{
Packit c04fcb
	ssize_t len;
Packit c04fcb
	struct ustcomm_notify_enum_msg msg;
Packit c04fcb
	size_t entries_len;
Packit c04fcb
	struct ustctl_enum_entry *a_entries = NULL;
Packit c04fcb
Packit c04fcb
	len = ustcomm_recv_unix_sock(sock, &msg, sizeof(msg));
Packit c04fcb
	if (len > 0 && len != sizeof(msg))
Packit c04fcb
		return -EIO;
Packit c04fcb
	if (len == 0)
Packit c04fcb
		return -EPIPE;
Packit c04fcb
	if (len < 0)
Packit c04fcb
		return len;
Packit c04fcb
Packit c04fcb
	*session_objd = msg.session_objd;
Packit c04fcb
	strncpy(enum_name, msg.enum_name, LTTNG_UST_SYM_NAME_LEN);
Packit c04fcb
	enum_name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
Packit c04fcb
	entries_len = msg.entries_len;
Packit c04fcb
Packit c04fcb
	if (entries_len % sizeof(*a_entries) != 0) {
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	}
Packit c04fcb
Packit c04fcb
	/* recv entries */
Packit c04fcb
	if (entries_len) {
Packit c04fcb
		a_entries = zmalloc(entries_len);
Packit c04fcb
		if (!a_entries)
Packit c04fcb
			return -ENOMEM;
Packit c04fcb
		len = ustcomm_recv_unix_sock(sock, a_entries, entries_len);
Packit c04fcb
		if (len > 0 && len != entries_len) {
Packit c04fcb
			len = -EIO;
Packit c04fcb
			goto entries_error;
Packit c04fcb
		}
Packit c04fcb
		if (len == 0) {
Packit c04fcb
			len = -EPIPE;
Packit c04fcb
			goto entries_error;
Packit c04fcb
		}
Packit c04fcb
		if (len < 0) {
Packit c04fcb
			goto entries_error;
Packit c04fcb
		}
Packit c04fcb
	}
Packit c04fcb
	*nr_entries = entries_len / sizeof(*a_entries);
Packit c04fcb
	*entries = a_entries;
Packit c04fcb
Packit c04fcb
	return 0;
Packit c04fcb
Packit c04fcb
entries_error:
Packit c04fcb
	free(a_entries);
Packit c04fcb
	return len;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
/*
Packit c04fcb
 * Returns 0 on success, negative error value on error.
Packit c04fcb
 */
Packit c04fcb
int ustctl_reply_register_enum(int sock,
Packit c04fcb
	uint64_t id,
Packit c04fcb
	int ret_code)
Packit c04fcb
{
Packit c04fcb
	ssize_t len;
Packit c04fcb
	struct {
Packit c04fcb
		struct ustcomm_notify_hdr header;
Packit c04fcb
		struct ustcomm_notify_enum_reply r;
Packit c04fcb
	} reply;
Packit c04fcb
Packit c04fcb
	memset(&reply, 0, sizeof(reply));
Packit c04fcb
	reply.header.notify_cmd = USTCTL_NOTIFY_CMD_ENUM;
Packit c04fcb
	reply.r.ret_code = ret_code;
Packit c04fcb
	reply.r.enum_id = id;
Packit c04fcb
	len = ustcomm_send_unix_sock(sock, &reply, sizeof(reply));
Packit c04fcb
	if (len > 0 && len != sizeof(reply))
Packit c04fcb
		return -EIO;
Packit c04fcb
	if (len < 0)
Packit c04fcb
		return len;
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
/*
Packit c04fcb
 * Returns 0 on success, negative UST or system error value on error.
Packit c04fcb
 */
Packit c04fcb
int ustctl_recv_register_channel(int sock,
Packit c04fcb
	int *session_objd,		/* session descriptor (output) */
Packit c04fcb
	int *channel_objd,		/* channel descriptor (output) */
Packit c04fcb
	size_t *nr_fields,
Packit c04fcb
	struct ustctl_field **fields)
Packit c04fcb
{
Packit c04fcb
	ssize_t len;
Packit c04fcb
	struct ustcomm_notify_channel_msg msg;
Packit c04fcb
	size_t fields_len;
Packit c04fcb
	struct ustctl_field *a_fields;
Packit c04fcb
Packit c04fcb
	len = ustcomm_recv_unix_sock(sock, &msg, sizeof(msg));
Packit c04fcb
	if (len > 0 && len != sizeof(msg))
Packit c04fcb
		return -EIO;
Packit c04fcb
	if (len == 0)
Packit c04fcb
		return -EPIPE;
Packit c04fcb
	if (len < 0)
Packit c04fcb
		return len;
Packit c04fcb
Packit c04fcb
	*session_objd = msg.session_objd;
Packit c04fcb
	*channel_objd = msg.channel_objd;
Packit c04fcb
	fields_len = msg.ctx_fields_len;
Packit c04fcb
Packit c04fcb
	if (fields_len % sizeof(*a_fields) != 0) {
Packit c04fcb
		return -EINVAL;
Packit c04fcb
	}
Packit c04fcb
Packit c04fcb
	/* recv fields */
Packit c04fcb
	if (fields_len) {
Packit c04fcb
		a_fields = zmalloc(fields_len);
Packit c04fcb
		if (!a_fields) {
Packit c04fcb
			len = -ENOMEM;
Packit c04fcb
			goto alloc_error;
Packit c04fcb
		}
Packit c04fcb
		len = ustcomm_recv_unix_sock(sock, a_fields, fields_len);
Packit c04fcb
		if (len > 0 && len != fields_len) {
Packit c04fcb
			len = -EIO;
Packit c04fcb
			goto fields_error;
Packit c04fcb
		}
Packit c04fcb
		if (len == 0) {
Packit c04fcb
			len = -EPIPE;
Packit c04fcb
			goto fields_error;
Packit c04fcb
		}
Packit c04fcb
		if (len < 0) {
Packit c04fcb
			goto fields_error;
Packit c04fcb
		}
Packit c04fcb
		*fields = a_fields;
Packit c04fcb
	} else {
Packit c04fcb
		*fields = NULL;
Packit c04fcb
	}
Packit c04fcb
	*nr_fields = fields_len / sizeof(*a_fields);
Packit c04fcb
	return 0;
Packit c04fcb
Packit c04fcb
fields_error:
Packit c04fcb
	free(a_fields);
Packit c04fcb
alloc_error:
Packit c04fcb
	return len;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
/*
Packit c04fcb
 * Returns 0 on success, negative error value on error.
Packit c04fcb
 */
Packit c04fcb
int ustctl_reply_register_channel(int sock,
Packit c04fcb
	uint32_t chan_id,
Packit c04fcb
	enum ustctl_channel_header header_type,
Packit c04fcb
	int ret_code)
Packit c04fcb
{
Packit c04fcb
	ssize_t len;
Packit c04fcb
	struct {
Packit c04fcb
		struct ustcomm_notify_hdr header;
Packit c04fcb
		struct ustcomm_notify_channel_reply r;
Packit c04fcb
	} reply;
Packit c04fcb
Packit c04fcb
	memset(&reply, 0, sizeof(reply));
Packit c04fcb
	reply.header.notify_cmd = USTCTL_NOTIFY_CMD_CHANNEL;
Packit c04fcb
	reply.r.ret_code = ret_code;
Packit c04fcb
	reply.r.chan_id = chan_id;
Packit c04fcb
	switch (header_type) {
Packit c04fcb
	case USTCTL_CHANNEL_HEADER_COMPACT:
Packit c04fcb
		reply.r.header_type = 1;
Packit c04fcb
		break;
Packit c04fcb
	case USTCTL_CHANNEL_HEADER_LARGE:
Packit c04fcb
		reply.r.header_type = 2;
Packit c04fcb
		break;
Packit c04fcb
	default:
Packit c04fcb
		reply.r.header_type = 0;
Packit c04fcb
		break;
Packit c04fcb
	}
Packit c04fcb
	len = ustcomm_send_unix_sock(sock, &reply, sizeof(reply));
Packit c04fcb
	if (len > 0 && len != sizeof(reply))
Packit c04fcb
		return -EIO;
Packit c04fcb
	if (len < 0)
Packit c04fcb
		return len;
Packit c04fcb
	return 0;
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
static __attribute__((constructor))
Packit c04fcb
void ustctl_init(void)
Packit c04fcb
{
Packit c04fcb
	init_usterr();
Packit c04fcb
	lttng_ust_clock_init();
Packit c04fcb
	lttng_ring_buffer_metadata_client_init();
Packit c04fcb
	lttng_ring_buffer_client_overwrite_init();
Packit c04fcb
	lttng_ring_buffer_client_overwrite_rt_init();
Packit c04fcb
	lttng_ring_buffer_client_discard_init();
Packit c04fcb
	lttng_ring_buffer_client_discard_rt_init();
Packit c04fcb
	lib_ringbuffer_signal_init();
Packit c04fcb
}
Packit c04fcb
Packit c04fcb
static __attribute__((destructor))
Packit c04fcb
void ustctl_exit(void)
Packit c04fcb
{
Packit c04fcb
	lttng_ring_buffer_client_discard_rt_exit();
Packit c04fcb
	lttng_ring_buffer_client_discard_exit();
Packit c04fcb
	lttng_ring_buffer_client_overwrite_rt_exit();
Packit c04fcb
	lttng_ring_buffer_client_overwrite_exit();
Packit c04fcb
	lttng_ring_buffer_metadata_client_exit();
Packit c04fcb
}