[lttng-dev] [RFC PATCH lttng-ust] Add basic support for dynamic instrumentation

Zifei Tong soariez at gmail.com
Wed Sep 4 07:02:13 EDT 2013


Support for instrument shared libraries is not implemented yet.

You can also view the patch at:
https://github.com/5kg/lttng-ust/commit/ae460fd8c5a2d77a4303bf82df26cc8f5cb7e392
---
 include/lttng/ust-abi.h            |  30 ++++++++++-
 include/lttng/ust-ctl.h            |  19 +++++++
 include/lttng/ust-events.h         |   3 ++
 include/ust-comm.h                 |  28 ++++++++++
 liblttng-ust-comm/lttng-ust-comm.c |  76 +++++++++++++++++++++++++++
 liblttng-ust-ctl/ustctl.c          | 103 +++++++++++++++++++++++++++++++++++++
 liblttng-ust/compat.h              |  13 +++++
 liblttng-ust/lttng-events.c        |  99 ++++++++++++++++++++++++++++-------
 liblttng-ust/lttng-ust-abi.c       |  16 ++++++
 liblttng-ust/lttng-ust-comm.c      |  62 ++++++++++++++++++++++
 10 files changed, 430 insertions(+), 19 deletions(-)

diff --git a/include/lttng/ust-abi.h b/include/lttng/ust-abi.h
index 6630332..f1787d4 100644
--- a/include/lttng/ust-abi.h
+++ b/include/lttng/ust-abi.h
@@ -98,7 +98,32 @@ struct lttng_ust_stream {
 	 */
 } LTTNG_PACKED;
 
-#define LTTNG_UST_EVENT_PADDING1	16
+/*
+ * Either addr is used, or symbol_name and offset.
+ */
+#define LTTNG_UST_PROBE_PADDING	16
+struct lttng_ust_probe {
+	uint64_t addr;
+
+	uint64_t offset;
+	char symbol_name[LTTNG_UST_SYM_NAME_LEN];
+
+	char padding[LTTNG_UST_PROBE_PADDING];
+} LTTNG_PACKED;
+
+/*
+ * Instrument target
+ */
+#define LTTNG_UST_TARGET_PADDING	32
+struct lttng_ust_target {
+	uint32_t path_len;
+
+	char padding[LTTNG_UST_TARGET_PADDING];
+
+	char path[0];
+} LTTNG_PACKED;
+
+#define LTTNG_UST_EVENT_PADDING1	(16 - sizeof(struct lttng_ust_target *))
 #define LTTNG_UST_EVENT_PADDING2	(LTTNG_UST_SYM_NAME_LEN + 32)
 struct lttng_ust_event {
 	enum lttng_ust_instrumentation instrumentation;
@@ -106,10 +131,12 @@ struct lttng_ust_event {
 
 	enum lttng_ust_loglevel_type loglevel_type;
 	int loglevel;	/* value, -1: all */
+	struct lttng_ust_target *target;
 	char padding[LTTNG_UST_EVENT_PADDING1];
 
 	/* Per instrumentation type configuration */
 	union {
+		struct lttng_ust_probe probe;
 		char padding[LTTNG_UST_EVENT_PADDING2];
 	} u;
 } LTTNG_PACKED;
@@ -273,6 +300,7 @@ struct lttng_ust_filter_bytecode {
 
 /* Event FD commands */
 #define LTTNG_UST_FILTER			_UST_CMD(0xA0)
+#define LTTNG_UST_TARGET			_UST_CMD(0xA1)
 
 #define LTTNG_UST_ROOT_HANDLE	0
 
diff --git a/include/lttng/ust-ctl.h b/include/lttng/ust-ctl.h
index 3c81e50..f88fbc7 100644
--- a/include/lttng/ust-ctl.h
+++ b/include/lttng/ust-ctl.h
@@ -73,6 +73,8 @@ int ustctl_add_context(int sock, struct lttng_ust_context *ctx,
 		struct lttng_ust_object_data **context_data);
 int ustctl_set_filter(int sock, struct lttng_ust_filter_bytecode *bytecode,
 		struct lttng_ust_object_data *obj_data);
+int ustctl_set_target(int sock, struct lttng_ust_target *target,
+		struct lttng_ust_object_data *obj_data);
 
 int ustctl_enable(int sock, struct lttng_ust_object_data *object);
 int ustctl_disable(int sock, struct lttng_ust_object_data *object);
@@ -230,6 +232,7 @@ enum ustctl_socket_type {
 enum ustctl_notify_cmd {
 	USTCTL_NOTIFY_CMD_EVENT = 0,
 	USTCTL_NOTIFY_CMD_CHANNEL = 1,
+	USTCTL_NOTIFY_CMD_INSTRUMENT = 2,
 };
 
 enum ustctl_channel_header {
@@ -395,4 +398,20 @@ int ustctl_reply_register_channel(int sock,
 	enum ustctl_channel_header header_type,
 	int ret_code);			/* return code. 0 ok, negative error */
 
+/*
+ * Returns 0 on success, negative error value on error.
+ */
+int ustctl_recv_instrument_probe(int sock,
+	char *object_path,
+	char *name,
+	enum lttng_ust_instrumentation *instrumentation,
+	uint64_t *addr,
+	char *symbol,
+	uint64_t *offset);
+
+/*
+ * Returns 0 on success, negative error value on error.
+ */
+int ustctl_reply_instrument_probe(int sock, int ret_code);
+
 #endif /* _LTTNG_UST_CTL_H */
diff --git a/include/lttng/ust-events.h b/include/lttng/ust-events.h
index f40c044..4759943 100644
--- a/include/lttng/ust-events.h
+++ b/include/lttng/ust-events.h
@@ -290,6 +290,7 @@ struct lttng_probe_desc {
 enum lttng_enabler_type {
 	LTTNG_ENABLER_WILDCARD,
 	LTTNG_ENABLER_EVENT,
+	LTTNG_ENABLER_INSTRUMENT,
 };
 
 /*
@@ -536,6 +537,8 @@ int lttng_enabler_enable(struct lttng_enabler *enabler);
 int lttng_enabler_disable(struct lttng_enabler *enabler);
 int lttng_enabler_attach_bytecode(struct lttng_enabler *enabler,
 		struct lttng_ust_filter_bytecode_node *bytecode);
+int lttng_enabler_attach_target(struct lttng_enabler *enabler,
+		struct lttng_ust_target *target);
 int lttng_enabler_attach_context(struct lttng_enabler *enabler,
 		struct lttng_ust_context *ctx);
 
diff --git a/include/ust-comm.h b/include/ust-comm.h
index 7f268b7..e555da8 100644
--- a/include/ust-comm.h
+++ b/include/ust-comm.h
@@ -90,6 +90,9 @@ struct ustcomm_ust_msg {
 			uint32_t reloc_offset;
 			uint64_t seqnum;
 		} LTTNG_PACKED filter;
+		struct {
+			uint32_t data_size;	/* following target data */
+		} LTTNG_PACKED target;
 		char padding[USTCOMM_MSG_PADDING2];
 	} u;
 } LTTNG_PACKED;
@@ -160,6 +163,24 @@ struct ustcomm_notify_channel_reply {
 	char padding[USTCOMM_NOTIFY_CHANNEL_REPLY_PADDING];
 } LTTNG_PACKED;
 
+#define USTCOMM_NOTIFY_INSTRUMENT_MSG_PADDING	32
+struct ustcomm_notify_instrument_msg {
+	uint32_t instrumentation;	/* enum lttng_ust_instrumentation */
+	char name[LTTNG_UST_SYM_NAME_LEN];
+	uint64_t addr;
+	char symbol[LTTNG_UST_SYM_NAME_LEN];
+	uint64_t offset;
+	uint32_t object_path_len;
+	char padding[USTCOMM_NOTIFY_INSTRUMENT_MSG_PADDING];
+	/* followed by object_path */
+} LTTNG_PACKED;
+
+#define USTCOMM_NOTIFY_INSTRUMENT_REPLY_PADDING	32
+struct ustcomm_notify_instrument_reply {
+	int32_t ret_code;	/* 0: ok, negative: error code */
+	char padding[USTCOMM_NOTIFY_INSTRUMENT_REPLY_PADDING];
+} LTTNG_PACKED;
+
 /*
  * LTTNG_UST_TRACEPOINT_FIELD_LIST reply is followed by a
  * struct lttng_ust_field_iter field.
@@ -231,6 +252,13 @@ int ustcomm_register_channel(int sock,
 	uint32_t *chan_id,		/* channel id (output) */
 	int *header_type); 		/* header type (output) */
 
+/*
+ * Returns 0 on success, negative error value on error.
+ * Returns -EPIPE or -ECONNRESET if other end has hung up.
+ */
+int ustcomm_instrument_probe(int sock,
+	const struct lttng_ust_event *uevent);	/* userspace event */
+
 int ustcomm_setsockopt_rcv_timeout(int sock, unsigned int msec);
 int ustcomm_setsockopt_snd_timeout(int sock, unsigned int msec);
 
diff --git a/liblttng-ust-comm/lttng-ust-comm.c b/liblttng-ust-comm/lttng-ust-comm.c
index a31786a..796f654 100644
--- a/liblttng-ust-comm/lttng-ust-comm.c
+++ b/liblttng-ust-comm/lttng-ust-comm.c
@@ -1111,6 +1111,82 @@ int ustcomm_register_channel(int sock,
 }
 
 /*
+ * Returns 0 on success, negative error value on error.
+ */
+int ustcomm_instrument_probe(int sock,
+	const struct lttng_ust_event *uevent)	/* userspace event */
+{
+	ssize_t len;
+	struct {
+		struct ustcomm_notify_hdr header;
+		struct ustcomm_notify_instrument_msg m;
+	} msg;
+	struct {
+		struct ustcomm_notify_hdr header;
+		struct ustcomm_notify_instrument_reply r;
+	} reply;
+
+	memset(&msg, 0, sizeof(msg));
+	msg.header.notify_cmd = USTCTL_NOTIFY_CMD_INSTRUMENT;
+	msg.m.instrumentation = uevent->instrumentation;
+	strncpy(msg.m.name, uevent->name, LTTNG_UST_SYM_NAME_LEN);
+	msg.m.name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+	msg.m.addr = uevent->u.probe.addr;
+	strncpy(msg.m.symbol, uevent->u.probe.symbol_name, LTTNG_UST_SYM_NAME_LEN);
+	msg.m.symbol[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+	msg.m.offset = uevent->u.probe.offset;
+	msg.m.object_path_len = uevent->target->path_len;
+
+	len = ustcomm_send_unix_sock(sock, &msg, sizeof(msg));
+	if (len > 0 && len != sizeof(msg)) {
+		return -EIO;
+	}
+	if (len < 0) {
+		return len;
+	}
+
+	len = ustcomm_send_unix_sock(sock, uevent->target->path,
+			uevent->target->path_len);
+	if (len > 0 && len != uevent->target->path_len) {
+		return -EIO;
+	}
+	if (len < 0) {
+		return len;
+	}
+
+	/* receive reply */
+	len = ustcomm_recv_unix_sock(sock, &reply, sizeof(reply));
+	switch (len) {
+	case 0:	/* orderly shutdown */
+		return -EPIPE;
+	case sizeof(reply):
+		if (reply.header.notify_cmd != msg.header.notify_cmd) {
+			ERR("Unexpected result message command "
+				"expected: %u vs received: %u\n",
+				msg.header.notify_cmd, reply.header.notify_cmd);
+			return -EINVAL;
+		}
+		if (reply.r.ret_code > 0)
+			return -EINVAL;
+		if (reply.r.ret_code < 0)
+			return reply.r.ret_code;
+		DBG("Sent instrument probe notification for object \"%s\": ret_code %d\n",
+			uevent->target->path, reply.r.ret_code);
+		return 0;
+	default:
+		if (len < 0) {
+			/* Transport level error */
+			if (errno == EPIPE || errno == ECONNRESET)
+				len = -errno;
+			return len;
+		} else {
+			ERR("incorrect message size: %zd\n", len);
+			return len;
+		}
+	}
+}
+
+/*
  * Set socket reciving timeout.
  */
 int ustcomm_setsockopt_rcv_timeout(int sock, unsigned int msec)
diff --git a/liblttng-ust-ctl/ustctl.c b/liblttng-ust-ctl/ustctl.c
index 28dee5e..684c2e6 100644
--- a/liblttng-ust-ctl/ustctl.c
+++ b/liblttng-ust-ctl/ustctl.c
@@ -196,6 +196,10 @@ int ustctl_create_event(int sock, struct lttng_ust_event *ev,
 	lum.cmd = LTTNG_UST_EVENT;
 	strncpy(lum.u.event.name, ev->name,
 		LTTNG_UST_SYM_NAME_LEN);
+	lum.u.event.u.probe.addr = ev->u.probe.addr;
+	lum.u.event.u.probe.offset = ev->u.probe.offset;
+	strncpy(lum.u.event.u.probe.symbol_name, ev->u.probe.symbol_name,
+		LTTNG_UST_SYM_NAME_LEN);
 	lum.u.event.instrumentation = ev->instrumentation;
 	lum.u.event.loglevel_type = ev->loglevel_type;
 	lum.u.event.loglevel = ev->loglevel;
@@ -241,6 +245,35 @@ int ustctl_add_context(int sock, struct lttng_ust_context *ctx,
 	return ret;
 }
 
+int ustctl_set_target(int sock, struct lttng_ust_target *target,
+		struct lttng_ust_object_data *obj_data)
+{
+	struct ustcomm_ust_msg lum;
+	struct ustcomm_ust_reply lur;
+	int ret;
+
+	if (!obj_data)
+		return -EINVAL;
+
+	memset(&lum, 0, sizeof(lum));
+	lum.handle = obj_data->handle;
+	lum.cmd = LTTNG_UST_TARGET;
+	lum.u.target.data_size = sizeof(struct lttng_ust_target)
+			+ target->path_len;
+
+	ret = ustcomm_send_app_msg(sock, &lum);
+	if (ret)
+		return ret;
+	/* send var len target struct */
+	ret = ustcomm_send_unix_sock(sock, target, lum.u.target.data_size);
+	if (ret < 0) {
+		return ret;
+	}
+	if (ret != lum.u.target.data_size)
+		return -EINVAL;
+	return ustcomm_recv_app_reply(sock, &lur, lum.handle, lum.cmd);
+}
+
 int ustctl_set_filter(int sock, struct lttng_ust_filter_bytecode *bytecode,
 		struct lttng_ust_object_data *obj_data)
 {
@@ -1548,6 +1581,9 @@ int ustctl_recv_notify(int sock, enum ustctl_notify_cmd *notify_cmd)
 	case 1:
 		*notify_cmd = USTCTL_NOTIFY_CMD_CHANNEL;
 		break;
+	case 2:
+		*notify_cmd = USTCTL_NOTIFY_CMD_INSTRUMENT;
+		break;
 	default:
 		return -EINVAL;
 	}
@@ -1799,6 +1835,73 @@ int ustctl_reply_register_channel(int sock,
 	return 0;
 }
 
+/*
+ * Returns 0 on success, negative error value on error.
+ */
+int ustctl_recv_instrument_probe(int sock,
+	char *object_path,
+	char *name,
+	enum lttng_ust_instrumentation *instrumentation,
+	uint64_t *addr,
+	char *symbol,
+	uint64_t *offset)
+{
+	ssize_t len;
+	struct ustcomm_notify_instrument_msg msg;
+
+	len = ustcomm_recv_unix_sock(sock, &msg, sizeof(msg));
+	if (len > 0 && len != sizeof(msg))
+		return -EIO;
+	if (len == 0)
+		return -EPIPE;
+	if (len < 0)
+		return len;
+
+	strncpy(name, msg.name, LTTNG_UST_SYM_NAME_LEN);
+	name[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+	*instrumentation = msg.instrumentation;
+	*addr = msg.addr;
+	strncpy(symbol, msg.symbol, LTTNG_UST_SYM_NAME_LEN);
+	symbol[LTTNG_UST_SYM_NAME_LEN - 1] = '\0';
+	*offset = msg.offset;
+
+	if (msg.object_path_len <= 0) {
+		return -EINVAL;
+	}
+
+	len = ustcomm_recv_unix_sock(sock, object_path, msg.object_path_len);
+	if (len > 0 && len != msg.object_path_len)
+		return -EIO;
+	if (len == 0)
+		return -EPIPE;
+	if (len < 0)
+		return len;
+
+	return 0;
+}
+
+/*
+ * Returns 0 on success, negative error value on error.
+ */
+int ustctl_reply_instrument_probe(int sock, int ret_code)
+{
+	ssize_t len;
+	struct {
+		struct ustcomm_notify_hdr header;
+		struct ustcomm_notify_instrument_reply r;
+	} reply;
+
+	memset(&reply, 0, sizeof(reply));
+	reply.header.notify_cmd = USTCTL_NOTIFY_CMD_INSTRUMENT;
+	reply.r.ret_code = ret_code;
+	len = ustcomm_send_unix_sock(sock, &reply, sizeof(reply));
+	if (len > 0 && len != sizeof(reply))
+		return -EIO;
+	if (len < 0)
+		return len;
+	return 0;
+}
+
 static __attribute__((constructor))
 void ustctl_init(void)
 {
diff --git a/liblttng-ust/compat.h b/liblttng-ust/compat.h
index 43b2223..9504517 100644
--- a/liblttng-ust/compat.h
+++ b/liblttng-ust/compat.h
@@ -25,6 +25,7 @@
 #ifdef __linux__
 
 #include <sys/prctl.h>
+#include <unistd.h>
 
 #define LTTNG_UST_PROCNAME_LEN 17
 
@@ -34,6 +35,18 @@ void lttng_ust_getprocname(char *name)
 	(void) prctl(PR_GET_NAME, (unsigned long) name, 0, 0, 0);
 }
 
+static inline
+int lttng_ust_getexecpath(char *path)
+{
+	ssize_t len;
+
+	if ((len = readlink("/proc/self/exe", path, PATH_MAX)) != -1) {
+		path[len] = '\0';
+		return len;
+	}
+	return -1;
+}
+
 #elif defined(__FreeBSD__)
 #include <stdlib.h>
 #include <string.h>
diff --git a/liblttng-ust/lttng-events.c b/liblttng-ust/lttng-events.c
index 26601a6..36a2ed6 100644
--- a/liblttng-ust/lttng-events.c
+++ b/liblttng-ust/lttng-events.c
@@ -441,18 +441,47 @@ exist:
 	return ret;
 }
 
+/*
+ * Notify sessiond to instrument the application.
+ */
 static
-int lttng_desc_match_wildcard_enabler(const struct lttng_event_desc *desc,
+int lttng_probe_instrument(const struct lttng_ust_event *uevent,
+		struct lttng_channel *chan)
+{
+	struct lttng_session *session = chan->session;
+	int ret = 0;
+	int notify_socket;
+
+	/* TODO: check if the probe is already instrumented */
+	/* TODO: register the probe, assuming probe registered for now */
+
+	notify_socket = lttng_get_notify_socket(session->owner);
+	if (notify_socket < 0) {
+		ret = notify_socket;
+		goto socket_error;
+	}
+
+	/* Notify sessiond to do the instrumentation */
+	ret = ustcomm_instrument_probe(notify_socket, uevent);
+	if (ret < 0) {
+		DBG("Error (%d) instrument probe by sessiond", ret);
+		goto sessiond_instrument_error;
+	}
+	return 0;
+
+socket_error:
+sessiond_instrument_error:
+	return ret;
+}
+
+
+static
+int lttng_desc_loglevel_match_enabler(const struct lttng_event_desc *desc,
 		struct lttng_enabler *enabler)
 {
 	int loglevel = 0;
 	unsigned int has_loglevel = 0;
 
-	assert(enabler->type == LTTNG_ENABLER_WILDCARD);
-	/* Compare excluding final '*' */
-	if (strncmp(desc->name, enabler->event_param.name,
-			strlen(enabler->event_param.name) - 1))
-		return 0;
 	if (desc->loglevel) {
 		loglevel = *(*desc->loglevel);
 		has_loglevel = 1;
@@ -466,25 +495,40 @@ int lttng_desc_match_wildcard_enabler(const struct lttng_event_desc *desc,
 }
 
 static
-int lttng_desc_match_event_enabler(const struct lttng_event_desc *desc,
+int lttng_desc_match_wildcard_enabler(const struct lttng_event_desc *desc,
 		struct lttng_enabler *enabler)
 {
-	int loglevel = 0;
-	unsigned int has_loglevel = 0;
+	assert(enabler->type == LTTNG_ENABLER_WILDCARD);
+	/* Compare excluding final '*' */
+	if (strncmp(desc->name, enabler->event_param.name,
+			strlen(enabler->event_param.name) - 1))
+		return 0;
+	return lttng_desc_loglevel_match_enabler(desc, enabler);
+}
 
+static
+int lttng_desc_match_event_enabler(const struct lttng_event_desc *desc,
+		struct lttng_enabler *enabler)
+{
 	assert(enabler->type == LTTNG_ENABLER_EVENT);
 	if (strcmp(desc->name, enabler->event_param.name))
 		return 0;
-	if (desc->loglevel) {
-		loglevel = *(*desc->loglevel);
-		has_loglevel = 1;
-	}
-	if (!lttng_loglevel_match(loglevel,
-			has_loglevel,
-			enabler->event_param.loglevel_type,
-			enabler->event_param.loglevel))
+	return lttng_desc_loglevel_match_enabler(desc, enabler);
+}
+
+static
+int lttng_desc_match_instrument_enabler(const struct lttng_event_desc *desc,
+		struct lttng_enabler *enabler)
+{
+	char exec_path[PATH_MAX];
+
+	assert(enabler->type == LTTNG_ENABLER_INSTRUMENT);
+	if (lttng_ust_getexecpath(exec_path) == -1)
 		return 0;
-	return 1;
+	if (strcmp(exec_path, enabler->event_param.target->path))
+		return 0;
+	/* TODO: match shared libraries */
+	return lttng_desc_loglevel_match_enabler(desc, enabler);
 }
 
 static
@@ -496,6 +540,8 @@ int lttng_desc_match_enabler(const struct lttng_event_desc *desc,
 		return lttng_desc_match_wildcard_enabler(desc, enabler);
 	case LTTNG_ENABLER_EVENT:
 		return lttng_desc_match_event_enabler(desc, enabler);
+	case LTTNG_ENABLER_INSTRUMENT:
+		return lttng_desc_match_instrument_enabler(desc, enabler);
 	default:
 		return -EINVAL;
 	}
@@ -574,6 +620,15 @@ void lttng_create_event_if_missing(struct lttng_enabler *enabler)
 			if (found)
 				continue;
 
+			if (enabler->type == LTTNG_ENABLER_INSTRUMENT) {
+				ret = lttng_probe_instrument(&enabler->event_param,
+						enabler->chan);
+				if (ret) {
+					DBG("Unable to instrument probe %s, error %d",
+						enabler->event_param.name, ret);
+				}
+			}
+
 			/*
 			 * We need to create an event for this
 			 * event probe.
@@ -720,6 +775,14 @@ int lttng_enabler_attach_bytecode(struct lttng_enabler *enabler,
 	return 0;
 }
 
+int lttng_enabler_attach_target(struct lttng_enabler *enabler,
+		struct lttng_ust_target *target)
+{
+	enabler->event_param.target = target;
+	lttng_session_lazy_sync_enablers(enabler->chan->session);
+	return 0;
+}
+
 int lttng_attach_context(struct lttng_ust_context *context_param,
 		struct lttng_ctx **ctx, struct lttng_session *session)
 {
diff --git a/liblttng-ust/lttng-ust-abi.c b/liblttng-ust/lttng-ust-abi.c
index a852aae..befb9ea 100644
--- a/liblttng-ust/lttng-ust-abi.c
+++ b/liblttng-ust/lttng-ust-abi.c
@@ -875,6 +875,15 @@ long lttng_channel_cmd(int objd, unsigned int cmd, unsigned long arg,
 	{
 		struct lttng_ust_event *event_param =
 			(struct lttng_ust_event *) arg;
+
+		switch (event_param->instrumentation) {
+			case LTTNG_UST_PROBE:
+			case LTTNG_UST_FUNCTION:
+				return lttng_abi_create_enabler(objd, event_param,
+						owner, LTTNG_ENABLER_INSTRUMENT);
+			default: break;
+		}
+
 		if (event_param->name[strlen(event_param->name) - 1] == '*') {
 			/* If ends with wildcard, create wildcard. */
 			return lttng_abi_create_enabler(objd, event_param,
@@ -933,6 +942,8 @@ static const struct lttng_ust_objd_ops lttng_channel_ops = {
  *		Disable recording for this enabler
  *	LTTNG_UST_FILTER
  *		Attach a filter to an enabler.
+ *	LTTNG_UST_TARGET
+ *		Attach a target to an enabler.
  */
 static
 long lttng_enabler_cmd(int objd, unsigned int cmd, unsigned long arg,
@@ -958,6 +969,11 @@ long lttng_enabler_cmd(int objd, unsigned int cmd, unsigned long arg,
 			return ret;
 		return 0;
 	}
+	case LTTNG_UST_TARGET:
+	{
+		return lttng_enabler_attach_target(enabler,
+				(struct lttng_ust_target *) arg);
+	}
 	default:
 		return -EINVAL;
 	}
diff --git a/liblttng-ust/lttng-ust-comm.c b/liblttng-ust/lttng-ust-comm.c
index 475110c..6815638 100644
--- a/liblttng-ust/lttng-ust-comm.c
+++ b/liblttng-ust/lttng-ust-comm.c
@@ -172,6 +172,7 @@ static const char *cmd_name_mapping[] = {
 
 	/* Event FD commands */
 	[ LTTNG_UST_FILTER ] = "Create Filter",
+	[ LTTNG_UST_TARGET ] = "Create Target",
 };
 
 static const char *str_timeout;
@@ -487,6 +488,67 @@ int handle_message(struct sock_info *sock_info,
 		}
 		break;
 	}
+	case LTTNG_UST_TARGET:
+	{
+		/* Receive filter data */
+		struct lttng_ust_target *target;
+
+		if (lum->u.target.data_size >
+				sizeof(struct lttng_ust_target) + PATH_MAX) {
+			ERR("Target data size is too large: %u bytes",
+				lum->u.target.data_size);
+			ret = -EINVAL;
+			goto error;
+		}
+
+		target = zmalloc(lum->u.target.data_size);
+		if (!target) {
+			ret = -ENOMEM;
+			goto error;
+		}
+		len = ustcomm_recv_unix_sock(sock, target,
+				lum->u.target.data_size);
+		switch (len) {
+		case 0:	/* orderly shutdown */
+			ret = 0;
+			free(target);
+			goto error;
+		default:
+			if (len == lum->u.target.data_size) {
+				DBG("target data received");
+				break;
+			} else if (len < 0) {
+				DBG("Receive failed from lttng-sessiond with errno %d", (int) -len);
+				if (len == -ECONNRESET) {
+					ERR("%s remote end closed connection", sock_info->name);
+					ret = len;
+					free(target);
+					goto error;
+				}
+				ret = len;
+				free(target);
+				goto end;
+			} else {
+				DBG("incorrect target data message size: %zd", len);
+				ret = -EINVAL;
+				free(target);
+				goto end;
+			}
+		}
+		if (ops->cmd) {
+			ret = ops->cmd(lum->handle, lum->cmd,
+					(unsigned long) target,
+					&args, sock_info);
+			if (ret) {
+				free(target);
+			}
+			/* don't free target if everything went fine. */
+		} else {
+			ret = -ENOSYS;
+			free(target);
+		}
+		break;
+	}
 	case LTTNG_UST_CHANNEL:
 	{
 		void *chan_data;
-- 
1.8.4




More information about the lttng-dev mailing list