#define LTTNG_UST_STREAM _UST_CMD(0x60)
#define LTTNG_UST_EVENT \
_UST_CMDW(0x61, struct lttng_ust_event)
-
+#define LTTNG_UST_STREAM_PIPE _UST_CMD(0x62)
/* Event and Channel FD commands */
#define LTTNG_UST_CONTEXT \
_UST_CMDW(0x70, struct lttng_ust_context)
int ustctl_open_metadata(int sock, int session_handle,
struct lttng_ust_channel_attr *chops,
struct lttng_ust_object_data **metadata_data);
+int ustctl_open_wait_pipe(int sock, struct lttng_ust_object_data *channel_data);
int ustctl_create_channel(int sock, int session_handle,
struct lttng_ust_channel_attr *chops,
struct lttng_ust_object_data **channel_data);
int (*is_finalized)(struct channel *chan);
int (*is_disabled)(struct channel *chan);
int (*flush_buffer)(struct channel *chan, struct lttng_ust_shm_handle *handle);
+ int (*channel_open_pipe)(struct channel *chan, struct lttng_ust_shm_handle *handle);
};
struct ltt_channel {
return -EINVAL;
}
+int ustctl_open_wait_pipe(int sock,
+ struct lttng_ust_object_data *channel_data)
+{
+ struct ustcomm_ust_msg lum;
+ struct ustcomm_ust_reply lur;
+ int ret;
+
+ if (!channel_data)
+ return -EINVAL;
+
+ /* Create metadata channel */
+ memset(&lum, 0, sizeof(lum));
+ lum.handle = channel_data->handle;
+ lum.cmd = LTTNG_UST_STREAM_PIPE;
+ ret = ustcomm_send_app_cmd(sock, &lum, &lur);
+
+ if (ret) {
+ goto error;
+ }
+ if (lur.ret_code != USTCOMM_OK) {
+ ret = lur.ret_code;
+ goto error;
+ }
+
+ return 0;
+
+error:
+ return ret;
+}
+
int ustctl_create_channel(int sock, int session_handle,
struct lttng_ust_channel_attr *chops,
struct lttng_ust_object_data **_channel_data)
return ltt_chan;
}
+static
+int ltt_channel_open_pipe(struct channel *chan,
+ struct lttng_ust_shm_handle *handle)
+{
+ struct shm_ref *ref;
+ int cpu = 0;
+
+ if (client_config.alloc == RING_BUFFER_ALLOC_GLOBAL) {
+ ref = &chan->backend.buf[0].shmp._ref;
+ return shm_open_wakeup_pipe(handle, ref);
+ } else {
+ if (cpu >= num_possible_cpus()) {
+ goto error;
+ }
+
+ for_each_possible_cpu(cpu) {
+ ref = &chan->backend.buf[cpu].shmp._ref;
+ if (shm_open_wakeup_pipe(handle, ref) < 0) {
+ goto error;
+ }
+ }
+ }
+
+ return 0;
+error:
+ return -1;
+}
+
static
void ltt_channel_destroy(struct ltt_channel *ltt_chan)
{
.name = "relay-" RING_BUFFER_MODE_TEMPLATE_STRING "-mmap",
.ops = {
.channel_create = _channel_create,
+ .channel_open_pipe = ltt_channel_open_pipe,
.channel_destroy = ltt_channel_destroy,
.buffer_read_open = ltt_buffer_read_open,
.buffer_read_close = ltt_buffer_read_close,
return ltt_chan;
}
+static
+int ltt_channel_open_pipe(struct channel *chan,
+ struct lttng_ust_shm_handle *handle)
+{
+ struct shm_ref *ref;
+ int cpu = 0;
+
+ if (client_config.alloc == RING_BUFFER_ALLOC_GLOBAL) {
+ ref = &chan->backend.buf[0].shmp._ref;
+ return shm_open_wakeup_pipe(handle, ref);
+ } else {
+ if (cpu >= num_possible_cpus()) {
+ goto error;
+ }
+
+ for_each_possible_cpu(cpu) {
+ ref = &chan->backend.buf[cpu].shmp._ref;
+ if (shm_open_wakeup_pipe(handle, ref) < 0) {
+ goto error;
+ }
+ }
+ }
+
+ return 0;
+error:
+ return -1;
+}
+
static
void ltt_channel_destroy(struct ltt_channel *ltt_chan)
{
.name = "relay-" RING_BUFFER_MODE_TEMPLATE_STRING "-mmap",
.ops = {
.channel_create = _channel_create,
+ .channel_open_pipe = ltt_channel_open_pipe,
.channel_destroy = ltt_channel_destroy,
.buffer_read_open = ltt_buffer_read_open,
.buffer_read_close = ltt_buffer_read_close,
return ltt_channel_disable(channel);
case LTTNG_UST_FLUSH_BUFFER:
return channel->ops->flush_buffer(channel->chan, channel->handle);
+ case LTTNG_UST_STREAM_PIPE:
+ return channel->ops->channel_open_pipe(channel->chan, channel->handle);
default:
return -EINVAL;
}
}
case LTTNG_UST_FLUSH_BUFFER:
return channel->ops->flush_buffer(channel->chan, channel->handle);
+ case LTTNG_UST_STREAM_PIPE:
+ return channel->ops->channel_open_pipe(channel->chan, channel->handle);
default:
return -EINVAL;
}
#include <usterr-signal-safe.h>
#include <urcu/compiler.h>
#include "shm_types.h"
+#include <fcntl.h>
/*
* Pointer dereferencing. We don't trust the shm_ref, so we validate
if (caa_unlikely(index >= table->allocated_len))
return -EPERM;
obj = &table->objects[index];
+
return obj->wait_fd[1];
+}
+
+static inline
+int shm_open_wakeup_pipe(struct lttng_ust_shm_handle *handle, struct shm_ref *ref)
+{
+ struct shm_object_table *table = handle->table;
+ struct shm_object *obj;
+ size_t index;
+ int fd, ret = -1;
+
+ index = (size_t) ref->index;
+ if (caa_unlikely(index >= table->allocated_len))
+ return -EPERM;
+
+ obj = &table->objects[index];
+ if (obj->wait_fd[1] < 0 && obj->wait_pipe_path != NULL) {
+ fd = open(obj->wait_pipe_path, O_WRONLY);
+ if (fd < 0) {
+ ret = -1;
+ } else {
+ /* FIXME: What if fcntl fail? */
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+ obj->wait_fd[1] = fd;
+ ret = 0;
+ }
+ }
+
+ return ret;
}
static inline