* returned.
*/
char *setup_channel_trace_path(struct consumer_output *consumer,
- const char *session_path)
+ const char *session_path, size_t *consumer_path_offset)
{
int ret;
char *pathname;
if (consumer->type == CONSUMER_DST_NET &&
consumer->relay_major_version == 2 &&
consumer->relay_minor_version < 11) {
- ret = snprintf(pathname, LTTNG_PATH_MAX, "%s%s/%s%s",
+ ret = snprintf(pathname, LTTNG_PATH_MAX, "%s%s/%s/%s",
consumer->dst.net.base_dir,
consumer->chunk_path, consumer->domain_subdir,
session_path);
+ *consumer_path_offset = 0;
} else {
- ret = snprintf(pathname, LTTNG_PATH_MAX, "%s%s",
+ ret = snprintf(pathname, LTTNG_PATH_MAX, "%s/%s",
consumer->domain_subdir, session_path);
+ *consumer_path_offset = strlen(consumer->domain_subdir) + 1;
}
DBG3("Consumer trace path relative to current trace chunk: \"%s\"",
pathname);
*/
int consumer_create_trace_chunk(struct consumer_socket *socket,
uint64_t relayd_id, uint64_t session_id,
- struct lttng_trace_chunk *chunk)
+ struct lttng_trace_chunk *chunk,
+ const char *domain_subdir)
{
int ret;
enum lttng_trace_chunk_status chunk_status;
struct lttng_credentials chunk_credentials;
- const struct lttng_directory_handle *chunk_directory_handle;
- int chunk_dirfd;
+ const struct lttng_directory_handle *chunk_directory_handle = NULL;
+ struct lttng_directory_handle *domain_handle = NULL;
+ int domain_dirfd;
const char *chunk_name;
bool chunk_name_overridden;
uint64_t chunk_id;
ret = -LTTNG_ERR_FATAL;
goto error;
}
-
- /*
- * This will only compile on platforms that support
- * dirfd (POSIX.2008). This is fine as the session daemon
- * is only built for such platforms.
- *
- * The ownership of the chunk directory handle's is maintained
- * by the trace chunk.
- */
- chunk_dirfd = lttng_directory_handle_get_dirfd(
- chunk_directory_handle);
- assert(chunk_dirfd >= 0);
-
chunk_status = lttng_trace_chunk_get_credentials(
chunk, &chunk_credentials);
if (chunk_status != LTTNG_TRACE_CHUNK_STATUS_OK) {
ret = -LTTNG_ERR_FATAL;
goto error;
}
+ ret = lttng_directory_handle_create_subdirectory_as_user(
+ chunk_directory_handle,
+ domain_subdir,
+ S_IRWXU | S_IRWXG,
+ &chunk_credentials);
+ if (ret) {
+ PERROR("Failed to create chunk domain output directory \"%s\"",
+ domain_subdir);
+ ret = -LTTNG_ERR_FATAL;
+ goto error;
+ }
+ domain_handle = lttng_directory_handle_create_from_handle(
+ domain_subdir,
+ chunk_directory_handle);
+ if (!domain_handle) {
+ ret = -LTTNG_ERR_FATAL;
+ goto error;
+ }
+
+ /*
+ * This will only compile on platforms that support
+ * dirfd (POSIX.2008). This is fine as the session daemon
+ * is only built for such platforms.
+ *
+ * The ownership of the chunk directory handle's is maintained
+ * by the trace chunk.
+ */
+ domain_dirfd = lttng_directory_handle_get_dirfd(
+ domain_handle);
+ assert(domain_dirfd >= 0);
+
msg.u.create_trace_chunk.credentials.value.uid =
chunk_credentials.uid;
msg.u.create_trace_chunk.credentials.value.gid =
}
if (chunk_has_local_output) {
- DBG("Sending trace chunk directory fd to consumer");
+ DBG("Sending trace chunk domain directory fd to consumer");
health_code_update();
- ret = consumer_send_fds(socket, &chunk_dirfd, 1);
+ ret = consumer_send_fds(socket, &domain_dirfd, 1);
health_code_update();
if (ret < 0) {
ERR("Trace chunk creation error on consumer");
}
}
error:
+ lttng_directory_handle_put(domain_handle);
return ret;
}
int consumer_create_trace_chunk(struct consumer_socket *socket,
uint64_t relayd_id, uint64_t session_id,
- struct lttng_trace_chunk *chunk);
+ struct lttng_trace_chunk *chunk,
+ const char *domain_subdir);
int consumer_close_trace_chunk(struct consumer_socket *socket,
uint64_t relayd_id, uint64_t session_id,
struct lttng_trace_chunk *chunk,
enum consumer_trace_chunk_exists_status *result);
char *setup_channel_trace_path(struct consumer_output *consumer,
- const char *session_path);
+ const char *session_path, size_t *consumer_path_offset);
#endif /* _CONSUMER_H */
#include "session.h"
#include "lttng-sessiond.h"
-static char *create_channel_path(struct consumer_output *consumer)
+static char *create_channel_path(struct consumer_output *consumer,
+ size_t *consumer_path_offset)
{
int ret;
char tmp_path[PATH_MAX];
consumer->domain_subdir);
goto error;
}
+ *consumer_path_offset = strlen(consumer->domain_subdir);
DBG3("Kernel local consumer trace path relative to current trace chunk: \"%s\"",
pathname);
} else {
- /* Network output. */
+ /* Network output, relayd < 2.11. */
ret = snprintf(tmp_path, sizeof(tmp_path), "%s%s",
consumer->dst.net.base_dir,
consumer->domain_subdir);
PERROR("lttng_strndup");
goto error;
}
+ *consumer_path_offset = 0;
DBG3("Kernel network consumer subdir path: %s", pathname);
}
struct ltt_session *session = NULL;
struct lttng_channel_extended *channel_attr_extended;
bool is_local_trace;
+ size_t consumer_path_offset = 0;
/* Safety net */
assert(channel);
channel->channel->name);
is_local_trace = consumer->net_seq_index == -1ULL;
- pathname = create_channel_path(consumer);
+ pathname = create_channel_path(consumer, &consumer_path_offset);
if (!pathname) {
ret = -1;
goto error;
consumer_init_add_channel_comm_msg(&lkm,
channel->key,
ksession->id,
- pathname,
+ &pathname[consumer_path_offset],
ksession->uid,
ksession->gid,
consumer->net_seq_index,
consumer_init_add_channel_comm_msg(&lkm,
ksession->metadata->key,
ksession->id,
- DEFAULT_KERNEL_TRACE_DIR,
+ "",
ksession->uid,
ksession->gid,
consumer->net_seq_index,
struct lttng_ht_iter iter;
struct ltt_kernel_metadata *saved_metadata;
char *trace_path = NULL;
+ size_t consumer_path_offset = 0;
assert(ksess);
assert(ksess->consumer);
}
trace_path = setup_channel_trace_path(ksess->consumer,
- DEFAULT_KERNEL_TRACE_DIR);
+ DEFAULT_KERNEL_TRACE_DIR, &consumer_path_offset);
if (!trace_path) {
status = LTTNG_ERR_INVALID;
goto error;
cds_list_for_each_entry(chan, &ksess->channel_list.head, list) {
status = consumer_snapshot_channel(socket, chan->key, output, 0,
ksess->uid, ksess->gid,
- trace_path, wait,
+ &trace_path[consumer_path_offset], wait,
nb_packets_per_stream);
if (status != LTTNG_OK) {
(void) kernel_consumer_destroy_metadata(socket,
/* Snapshot metadata, */
status = consumer_snapshot_channel(socket, ksess->metadata->key, output,
- 1, ksess->uid, ksess->gid, trace_path, wait, 0);
+ 1, ksess->uid, ksess->gid, &trace_path[consumer_path_offset],
+ wait, 0);
if (status != LTTNG_OK) {
goto error_consumer;
}
pthread_mutex_lock(socket->lock);
ret = consumer_create_trace_chunk(socket,
relayd_id,
- session->id, new_trace_chunk);
+ session->id, new_trace_chunk,
+ DEFAULT_UST_TRACE_DIR);
pthread_mutex_unlock(socket->lock);
if (ret) {
goto error;
pthread_mutex_lock(socket->lock);
ret = consumer_create_trace_chunk(socket,
relayd_id,
- session->id, new_trace_chunk);
+ session->id, new_trace_chunk,
+ DEFAULT_KERNEL_TRACE_DIR);
pthread_mutex_unlock(socket->lock);
if (ret) {
goto error;
switch (ua_sess->buffer_type) {
case LTTNG_BUFFER_PER_PID:
ret = snprintf(tmp_shm_path, sizeof(tmp_shm_path),
- DEFAULT_UST_TRACE_PID_PATH "/%s-%d-%s",
+ "/" DEFAULT_UST_TRACE_PID_PATH "/%s-%d-%s",
app->name, app->pid, datetime);
break;
case LTTNG_BUFFER_PER_UID:
ret = snprintf(tmp_shm_path, sizeof(tmp_shm_path),
- DEFAULT_UST_TRACE_UID_PATH,
+ "/" DEFAULT_UST_TRACE_UID_PATH,
app->uid, app->bits_per_long);
break;
default:
struct buffer_reg_channel *reg_chan;
struct consumer_socket *socket;
char pathname[PATH_MAX];
+ size_t consumer_path_offset = 0;
if (!reg->registry->reg.ust->metadata_key) {
/* Skip since no metadata is present */
}
memset(pathname, 0, sizeof(pathname));
- /*
- * DEFAULT_UST_TRACE_UID_PATH already contains a path
- * separator.
- */
ret = snprintf(pathname, sizeof(pathname),
- DEFAULT_UST_TRACE_DIR DEFAULT_UST_TRACE_UID_PATH,
+ DEFAULT_UST_TRACE_DIR "/" DEFAULT_UST_TRACE_UID_PATH,
reg->uid, reg->bits_per_long);
if (ret < 0) {
PERROR("snprintf snapshot path");
}
/* Free path allowed on previous iteration. */
free(trace_path);
- trace_path = setup_channel_trace_path(usess->consumer, pathname);
+ trace_path = setup_channel_trace_path(usess->consumer, pathname,
+ &consumer_path_offset);
if (!trace_path) {
status = LTTNG_ERR_INVALID;
goto error;
status = consumer_snapshot_channel(socket,
reg_chan->consumer_key,
output, 0, usess->uid,
- usess->gid, trace_path, wait,
+ usess->gid, &trace_path[consumer_path_offset], wait,
nb_packets_per_stream);
if (status != LTTNG_OK) {
goto error;
}
status = consumer_snapshot_channel(socket,
reg->registry->reg.ust->metadata_key, output, 1,
- usess->uid, usess->gid, trace_path, wait, 0);
+ usess->uid, usess->gid, &trace_path[consumer_path_offset],
+ wait, 0);
if (status != LTTNG_OK) {
goto error;
}
struct ust_app_session *ua_sess;
struct ust_registry_session *registry;
char pathname[PATH_MAX];
+ size_t consumer_path_offset = 0;
ua_sess = lookup_session_by_app(usess, app);
if (!ua_sess) {
/* Add the UST default trace dir to path. */
memset(pathname, 0, sizeof(pathname));
- ret = snprintf(pathname, sizeof(pathname), DEFAULT_UST_TRACE_DIR "%s",
+ ret = snprintf(pathname, sizeof(pathname), DEFAULT_UST_TRACE_DIR "/%s",
ua_sess->path);
if (ret < 0) {
status = LTTNG_ERR_INVALID;
}
/* Free path allowed on previous iteration. */
free(trace_path);
- trace_path = setup_channel_trace_path(usess->consumer, pathname);
+ trace_path = setup_channel_trace_path(usess->consumer, pathname,
+ &consumer_path_offset);
if (!trace_path) {
status = LTTNG_ERR_INVALID;
goto error;
.uid,
ua_sess->effective_credentials
.gid,
- trace_path, wait,
+ &trace_path[consumer_path_offset], wait,
nb_packets_per_stream);
switch (status) {
case LTTNG_OK:
registry->metadata_key, output, 1,
ua_sess->effective_credentials.uid,
ua_sess->effective_credentials.gid,
- trace_path, wait, 0);
+ &trace_path[consumer_path_offset], wait, 0);
switch (status) {
case LTTNG_OK:
break;
cds_list_for_each_entry(reg, &usess->buffer_reg_uid_list, lnode) {
fmt_ret = asprintf(&pathname_index,
- DEFAULT_UST_TRACE_DIR DEFAULT_UST_TRACE_UID_PATH "/" DEFAULT_INDEX_DIR,
+ DEFAULT_UST_TRACE_DIR "/" DEFAULT_UST_TRACE_UID_PATH "/" DEFAULT_INDEX_DIR,
reg->uid, reg->bits_per_long);
if (fmt_ret < 0) {
ERR("Failed to format channel index directory");
}
fmt_ret = asprintf(&pathname_index,
- DEFAULT_UST_TRACE_DIR "%s/" DEFAULT_INDEX_DIR,
+ DEFAULT_UST_TRACE_DIR "/%s/" DEFAULT_INDEX_DIR,
ua_sess->path);
if (fmt_ret < 0) {
ERR("Failed to format channel index directory");
char shm_path[PATH_MAX] = "";
char root_shm_path[PATH_MAX] = "";
bool is_local_trace;
+ size_t consumer_path_offset = 0;
assert(ua_sess);
assert(ua_chan);
is_local_trace = consumer->net_seq_index == -1ULL;
/* Format the channel's path (relative to the current trace chunk). */
- pathname = setup_channel_trace_path(consumer, ua_sess->path);
+ pathname = setup_channel_trace_path(consumer, ua_sess->path,
+ &consumer_path_offset);
if (!pathname) {
ret = -1;
goto error;
output,
(int) ua_chan->attr.type,
ua_sess->tracing_id,
- pathname,
+ &pathname[consumer_path_offset],
ua_chan->name,
consumer->net_seq_index,
ua_chan->key,
static struct lttng_ht *metadata_ht;
static struct lttng_ht *data_ht;
+static const char *get_consumer_domain(void)
+{
+ switch (consumer_data.type) {
+ case LTTNG_CONSUMER_KERNEL:
+ return DEFAULT_KERNEL_TRACE_DIR;
+ case LTTNG_CONSUMER64_UST:
+ /* Fall-through. */
+ case LTTNG_CONSUMER32_UST:
+ return DEFAULT_UST_TRACE_DIR;
+ default:
+ abort();
+ }
+}
+
/*
* Notify a thread lttng pipe to poll back again. This usually means that some
* global state has changed so we just send back the thread in a poll wait
/* Add stream on the relayd */
pthread_mutex_lock(&relayd->ctrl_sock_mutex);
ret = relayd_add_stream(&relayd->control_sock, stream->name,
- path, &stream->relayd_stream_id,
+ get_consumer_domain(), path, &stream->relayd_stream_id,
stream->chan->tracefile_size,
stream->chan->tracefile_count,
stream->trace_chunk);
#define DEFAULT_UST_TRACE_DIR "ust"
/* Subpath for per PID or UID sessions. */
-#define DEFAULT_UST_TRACE_PID_PATH "/pid"
-#define DEFAULT_UST_TRACE_UID_PATH "/uid/%d/%u-bit"
+#define DEFAULT_UST_TRACE_PID_PATH "pid"
+#define DEFAULT_UST_TRACE_UID_PATH "uid/%d/%u-bit"
/*
* Default session name for the lttng command line. This default value will
* On success return 0 else return ret_code negative value.
*/
int relayd_add_stream(struct lttcomm_relayd_sock *rsock, const char *channel_name,
- const char *pathname, uint64_t *stream_id,
+ const char *domain_name, const char *_pathname, uint64_t *stream_id,
uint64_t tracefile_size, uint64_t tracefile_count,
struct lttng_trace_chunk *trace_chunk)
{
int ret;
struct lttcomm_relayd_status_stream reply;
+ char pathname[RELAYD_COMM_LTTNG_PATH_MAX];
+ char *separator;
/* Code flow error. Safety net. */
assert(rsock);
assert(channel_name);
- assert(pathname);
+ assert(domain_name);
+ assert(_pathname);
assert(trace_chunk);
DBG("Relayd adding stream for channel name %s", channel_name);
+ if (_pathname[0] == '\0') {
+ separator = "";
+ } else {
+ separator = "/";
+ }
+ ret = snprintf(pathname, RELAYD_COMM_LTTNG_PATH_MAX, "%s%s%s",
+ domain_name, separator, _pathname);
+ if (ret <= 0 || ret >= RELAYD_COMM_LTTNG_PATH_MAX) {
+ ERR("stream path too long.");
+ ret = -1;
+ goto error;
+ }
+
/* Compat with relayd 2.1 */
if (rsock->minor == 1) {
/* For 2.1 */
time_t creation_time, bool session_name_contains_creation_time,
char *output_path);
int relayd_add_stream(struct lttcomm_relayd_sock *sock, const char *channel_name,
- const char *pathname, uint64_t *stream_id,
+ const char *domain_name, const char *pathname, uint64_t *stream_id,
uint64_t tracefile_size, uint64_t tracefile_count,
struct lttng_trace_chunk *trace_chunk);
int relayd_streams_sent(struct lttcomm_relayd_sock *rsock);
goto end_nosignal;
}
+ /*
+ * Receive trace chunk domain dirfd.
+ */
ret = lttcomm_recv_fds_unix_sock(sock, &chunk_dirfd, 1);
if (ret != sizeof(chunk_dirfd)) {
- ERR("Failed to receive trace chunk directory file descriptor");
+ ERR("Failed to receive trace chunk domain directory file descriptor");
goto error_fatal;
}
- DBG("Received trace chunk directory fd (%d)",
+ DBG("Received trace chunk domain directory fd (%d)",
chunk_dirfd);
chunk_directory_handle = lttng_directory_handle_create_from_dirfd(
chunk_dirfd);
if (!chunk_directory_handle) {
- ERR("Failed to initialize chunk directory handle from directory file descriptor");
+ ERR("Failed to initialize chunk domain directory handle from directory file descriptor");
if (close(chunk_dirfd)) {
PERROR("Failed to close chunk directory file descriptor");
}