/*
* Push metadata to consumer socket.
*
- * The socket lock MUST be acquired.
- * The ust app session lock MUST be acquired.
+ * RCU read-side lock must be held to guarantee existance of socket.
+ * Must be called with the ust app session lock held.
+ * Must be called with the registry lock held.
*
* On success, return the len of metadata pushed or else a negative value.
*/
assert(registry);
assert(socket);
- pthread_mutex_lock(®istry->lock);
-
/*
- * Means that no metadata was assigned to the session. This can happens if
- * no start has been done previously.
+ * Means that no metadata was assigned to the session. This can
+ * happens if no start has been done previously.
*/
if (!registry->metadata_key) {
- pthread_mutex_unlock(®istry->lock);
return 0;
}
/*
- * On a push metadata error either the consumer is dead or the metadata
- * channel has been destroyed because its endpoint might have died (e.g:
- * relayd). If so, the metadata closed flag is set to 1 so we deny pushing
- * metadata again which is not valid anymore on the consumer side.
+ * On a push metadata error either the consumer is dead or the
+ * metadata channel has been destroyed because its endpoint
+ * might have died (e.g: relayd). If so, the metadata closed
+ * flag is set to 1 so we deny pushing metadata again which is
+ * not valid anymore on the consumer side.
*/
if (registry->metadata_closed) {
- pthread_mutex_unlock(®istry->lock);
return -EPIPE;
}
registry->metadata_len_sent += len;
push_data:
- pthread_mutex_unlock(®istry->lock);
ret = consumer_push_metadata(socket, registry->metadata_key,
metadata_str, len, offset);
if (ret < 0) {
/*
- * There is an acceptable race here between the registry metadata key
- * assignment and the creation on the consumer. The session daemon can
- * concurrently push metadata for this registry while being created on
- * the consumer since the metadata key of the registry is assigned
- * *before* it is setup to avoid the consumer to ask for metadata that
- * could possibly be not found in the session daemon.
+ * There is an acceptable race here between the registry
+ * metadata key assignment and the creation on the
+ * consumer. The session daemon can concurrently push
+ * metadata for this registry while being created on the
+ * consumer since the metadata key of the registry is
+ * assigned *before* it is setup to avoid the consumer
+ * to ask for metadata that could possibly be not found
+ * in the session daemon.
*
- * The metadata will get pushed either by the session being stopped or
- * the consumer requesting metadata if that race is triggered.
+ * The metadata will get pushed either by the session
+ * being stopped or the consumer requesting metadata if
+ * that race is triggered.
*/
if (ret == -LTTCOMM_CONSUMERD_CHANNEL_FAIL) {
ret = 0;
}
- /* Update back the actual metadata len sent since it failed here. */
- pthread_mutex_lock(®istry->lock);
+ /*
+ * Update back the actual metadata len sent since it
+ * failed here.
+ */
registry->metadata_len_sent -= len;
- pthread_mutex_unlock(®istry->lock);
ret_val = ret;
goto error_push;
}
error:
if (ret_val) {
/*
- * On error, flag the registry that the metadata is closed. We were unable
- * to push anything and this means that either the consumer is not
- * responding or the metadata cache has been destroyed on the consumer.
+ * On error, flag the registry that the metadata is
+ * closed. We were unable to push anything and this
+ * means that either the consumer is not responding or
+ * the metadata cache has been destroyed on the
+ * consumer.
*/
registry->metadata_closed = 1;
}
- pthread_mutex_unlock(®istry->lock);
error_push:
free(metadata_str);
return ret_val;
* socket to send the metadata is retrieved from consumer, if sock
* is not NULL we use it to send the metadata.
* RCU read-side lock must be held while calling this function,
- * therefore ensuring existance of registry.
+ * therefore ensuring existance of registry. It also ensures existance
+ * of socket throughout this function.
*
* Return 0 on success else a negative error.
*/
assert(consumer);
pthread_mutex_lock(®istry->lock);
-
if (registry->metadata_closed) {
- pthread_mutex_unlock(®istry->lock);
- return -EPIPE;
+ ret_val = -EPIPE;
+ goto error;
}
/* Get consumer socket to use to push the metadata.*/
socket = consumer_find_socket_by_bitness(registry->bits_per_long,
consumer);
- pthread_mutex_unlock(®istry->lock);
if (!socket) {
ret_val = -1;
goto error;
}
- /*
- * TODO: Currently, we hold the socket lock around sampling of the next
- * metadata segment to ensure we send metadata over the consumer socket in
- * the correct order. This makes the registry lock nest inside the socket
- * lock.
- *
- * Please note that this is a temporary measure: we should move this lock
- * back into ust_consumer_push_metadata() when the consumer gets the
- * ability to reorder the metadata it receives.
- */
- pthread_mutex_lock(socket->lock);
ret = ust_app_push_metadata(registry, socket, 0);
- pthread_mutex_unlock(socket->lock);
if (ret < 0) {
ret_val = ret;
goto error;
}
-
+ pthread_mutex_unlock(®istry->lock);
return 0;
error:
-end:
+ pthread_mutex_unlock(®istry->lock);
return ret_val;
}
/*
* Send to the consumer a close metadata command for the given session. Once
* done, the metadata channel is deleted and the session metadata pointer is
- * nullified. The session lock MUST be acquired here unless the application is
+ * nullified. The session lock MUST be held unless the application is
* in the destroy path.
*
* Return 0 on success else a negative value.
struct tm *timeinfo;
char datetime[16];
int ret;
+ char tmp_shm_path[PATH_MAX];
/* Get date and time for unique app path */
time(&rawtime);
goto error;
}
+ strncpy(ua_sess->root_shm_path, usess->root_shm_path,
+ sizeof(ua_sess->root_shm_path));
+ ua_sess->root_shm_path[sizeof(ua_sess->root_shm_path) - 1] = '\0';
+ strncpy(ua_sess->shm_path, usess->shm_path,
+ sizeof(ua_sess->shm_path));
+ ua_sess->shm_path[sizeof(ua_sess->shm_path) - 1] = '\0';
+ if (ua_sess->shm_path[0]) {
+ 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",
+ 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,
+ app->uid, app->bits_per_long);
+ break;
+ default:
+ assert(0);
+ goto error;
+ }
+ if (ret < 0) {
+ PERROR("sprintf UST shadow copy session");
+ assert(0);
+ goto error;
+ }
+ strncat(ua_sess->shm_path, tmp_shm_path,
+ sizeof(ua_sess->shm_path) - strlen(ua_sess->shm_path) - 1);
+ ua_sess->shm_path[sizeof(ua_sess->shm_path) - 1] = '\0';
+ }
+
/* Iterate over all channels in global domain. */
cds_lfht_for_each_entry(usess->domain_global.channels->ht, &iter.iter,
uchan, node.node) {
* This is the create channel path meaning that if there is NO
* registry available, we have to create one for this session.
*/
- ret = buffer_reg_pid_create(ua_sess->id, ®_pid);
+ ret = buffer_reg_pid_create(ua_sess->id, ®_pid,
+ ua_sess->root_shm_path, ua_sess->shm_path);
if (ret < 0) {
goto error;
}
app->uint16_t_alignment, app->uint32_t_alignment,
app->uint64_t_alignment, app->long_alignment,
app->byte_order, app->version.major,
- app->version.minor);
+ app->version.minor, reg_pid->root_shm_path,
+ reg_pid->shm_path,
+ ua_sess->euid, ua_sess->egid);
if (ret < 0) {
/*
* reg_pid->registry->reg.ust is NULL upon error, so we need to
* Return 0 on success or else a negative value.
*/
static int setup_buffer_reg_uid(struct ltt_ust_session *usess,
+ struct ust_app_session *ua_sess,
struct ust_app *app, struct buffer_reg_uid **regp)
{
int ret = 0;
* registry available, we have to create one for this session.
*/
ret = buffer_reg_uid_create(usess->id, app->bits_per_long, app->uid,
- LTTNG_DOMAIN_UST, ®_uid);
+ LTTNG_DOMAIN_UST, ®_uid,
+ ua_sess->root_shm_path, ua_sess->shm_path);
if (ret < 0) {
goto error;
}
app->uint16_t_alignment, app->uint32_t_alignment,
app->uint64_t_alignment, app->long_alignment,
app->byte_order, app->version.major,
- app->version.minor);
+ app->version.minor, reg_uid->root_shm_path,
+ reg_uid->shm_path, usess->uid, usess->gid);
if (ret < 0) {
/*
* reg_uid->registry->reg.ust is NULL upon error, so we need to
break;
case LTTNG_BUFFER_PER_UID:
/* Look for a global registry. If none exists, create one. */
- ret = setup_buffer_reg_uid(usess, app, NULL);
+ ret = setup_buffer_reg_uid(usess, ua_sess, app, NULL);
if (ret < 0) {
delete_ust_app_session(-1, ua_sess, app);
goto error;
int ust_app_flush_session(struct ltt_ust_session *usess)
{
- int ret;
+ int ret = 0;
DBG("Flushing session buffers for all ust apps");
/* Push metadata. */
(void) push_metadata(ust_session_reg, usess->consumer);
}
- ret = 0;
break;
}
case LTTNG_BUFFER_PER_PID:
break;
}
default:
+ ret = -1;
assert(0);
break;
}
-end_no_session:
rcu_read_unlock();
health_code_update();
return ret;