}
if (chunk->chunk_directory) {
lttng_directory_handle_put(chunk->chunk_directory);
- chunk->chunk_directory = NULL;
+ chunk->chunk_directory = NULL;
}
free(chunk->name);
chunk->name = NULL;
uint64_t chunk_id, time_t chunk_creation_time, const char *path)
{
struct lttng_trace_chunk *chunk;
- char chunk_creation_datetime_buf[16] = {};
+ char chunk_creation_datetime_buf[16] = {};
const char *chunk_creation_datetime_str = "(formatting error)";
- struct tm timeinfo_buf, *timeinfo;
+ struct tm timeinfo_buf, *timeinfo;
timeinfo = localtime_r(&chunk_creation_time, &timeinfo_buf);
if (timeinfo) {
ERR("Failed to allocate trace chunk name storage");
goto error;
}
- }
+ }
if (path) {
chunk->path = strdup(path);
if (!chunk->path) {
}
}
- DBG("Chunk name set to \"%s\"", chunk->name ? : "(none)");
+ DBG("Chunk name set to \"%s\"", chunk->name ? : "(none)");
end:
return chunk;
error:
enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
pthread_mutex_lock(&chunk->lock);
- if (name_overridden) {
+ if (name_overridden) {
*name_overridden = chunk->name_overridden;
- }
- if (!chunk->name) {
+ }
+ if (!chunk->name) {
status = LTTNG_TRACE_CHUNK_STATUS_NONE;
goto end;
}
pthread_mutex_lock(&chunk->lock);
if (chunk->credentials.is_set) {
if (chunk->credentials.value.use_current_user) {
- credentials->uid = geteuid();
- credentials->gid = getegid();
+ LTTNG_OPTIONAL_SET(&credentials->uid, geteuid());
+ LTTNG_OPTIONAL_SET(&credentials->gid, getegid());
} else {
*credentials = chunk->credentials.value.user;
}
* A nameless chunk does not need its own output directory.
* The session's output directory will be used.
*/
- const bool reference_acquired =
- lttng_directory_handle_get(
- session_output_directory);
+ reference_acquired = lttng_directory_handle_get(
+ session_output_directory);
assert(reference_acquired);
chunk_directory_handle = session_output_directory;
ret = lttng_directory_handle_create_subdirectory_as_user(
trace_chunk->session_output_directory,
- DEFAULT_ARCHIVED_TRACE_CHUNKS_DIRECTORY,
+ DEFAULT_ARCHIVED_TRACE_CHUNKS_DIRECTORY,
DIR_CREATION_MODE,
!trace_chunk->credentials.value.use_current_user ?
&trace_chunk->credentials.value.user :
DBG("Overriding trace chunk close command from \"%s\" to \"%s\"",
close_command_names[chunk->close_command.value],
close_command_names[close_command]);
- } else {
+ } else {
DBG("Setting trace chunk close command to \"%s\"",
close_command_names[close_command]);
- }
+ }
/*
* Unset close command for no-op for backward compatibility with relayd
* 2.11.
}
}
+LTTNG_HIDDEN
+bool lttng_trace_chunk_ids_equal(const struct lttng_trace_chunk *chunk_a,
+ const struct lttng_trace_chunk *chunk_b)
+{
+ bool equal = false;
+
+ if (chunk_a == chunk_b) {
+ equal = true;
+ goto end;
+ }
+
+ if (!!chunk_a ^ !!chunk_b) {
+ goto end;
+ }
+
+ if (chunk_a->id.is_set ^ chunk_a->id.is_set) {
+ /* One id is set and not the other, thus they are not equal. */
+ goto end;
+ }
+
+ if (!chunk_a->id.is_set) {
+ /* Both ids are unset. */
+ equal = true;
+ } else {
+ equal = chunk_a->id.value == chunk_b->id.value;
+ }
+
+end:
+ return equal;
+}
+
LTTNG_HIDDEN
bool lttng_trace_chunk_get(struct lttng_trace_chunk *chunk)
{
struct lttng_trace_chunk_registry_element *element =
container_of(node, typeof(*element), rcu_node);
- lttng_trace_chunk_fini(&element->chunk);
free(element);
}
if (chunk->in_registry_element) {
struct lttng_trace_chunk_registry_element *element;
+ /*
+ * Release internal chunk attributes immediately and
+ * only use the deferred `call_rcu` work to reclaim the
+ * storage.
+ *
+ * This ensures that file handles are released as soon as
+ * possible which works around a problem we encounter with PRAM fs
+ * mounts (and possibly other non-POSIX compliant file systems):
+ * directories that contain files which are open can't be
+ * rmdir().
+ *
+ * This means that the recording of a snapshot could be
+ * completed, but that it would be impossible for the user to
+ * delete it until the deferred clean-up released the file
+ * handles to its contents.
+ */
+ lttng_trace_chunk_fini(chunk);
+
element = container_of(chunk, typeof(*element), chunk);
if (element->registry) {
rcu_read_lock();
struct lttng_trace_chunk *
lttng_trace_chunk_registry_publish_chunk(
struct lttng_trace_chunk_registry *registry,
- uint64_t session_id, struct lttng_trace_chunk *chunk)
+ uint64_t session_id,
+ struct lttng_trace_chunk *chunk)
+{
+ bool unused;
+
+ return lttng_trace_chunk_registry_publish_chunk_published(
+ registry, session_id, chunk, &unused);
+}
+
+struct lttng_trace_chunk *
+lttng_trace_chunk_registry_publish_chunk_published(
+ struct lttng_trace_chunk_registry *registry,
+ uint64_t session_id, struct lttng_trace_chunk *chunk,
+ bool *previously_published)
{
struct lttng_trace_chunk_registry_element *element;
unsigned long element_hash;
struct lttng_trace_chunk_registry_element *published_element;
published_node = cds_lfht_add_unique(registry->ht,
- element_hash,
+ element_hash,
lttng_trace_chunk_registry_element_match,
- element,
+ element,
&element->trace_chunk_registry_ht_node);
if (published_node == &element->trace_chunk_registry_ht_node) {
/* Successfully published the new element. */
- element->registry = registry;
+ element->registry = registry;
/* Acquire a reference for the caller. */
if (lttng_trace_chunk_get(&element->chunk)) {
+ *previously_published = false;
break;
} else {
/*
if (lttng_trace_chunk_get(published_chunk)) {
lttng_trace_chunk_put(&element->chunk);
element = published_element;
+ *previously_published = true;
break;
}
/*
const struct lttng_trace_chunk_registry *registry,
uint64_t session_id, uint64_t chunk_id)
{
- return _lttng_trace_chunk_registry_find_chunk(registry,
+ return _lttng_trace_chunk_registry_find_chunk(registry,
session_id, &chunk_id);
}
const struct lttng_trace_chunk_registry *registry,
uint64_t session_id)
{
- return _lttng_trace_chunk_registry_find_chunk(registry,
+ return _lttng_trace_chunk_registry_find_chunk(registry,
session_id, NULL);
}