X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Fcommon%2Ftrace-chunk.c;h=d04d51637e603fe763a067a3271917d1da5e80a7;hb=3afa94aeca5a0daae40fd7b6cc96b7e4c150c7d8;hp=326d42ce2c6656c02f5d00cbba6359915536e5ab;hpb=b2621f79ae2fade4d2d7f21624dfe4649e5e3352;p=lttng-tools.git diff --git a/src/common/trace-chunk.c b/src/common/trace-chunk.c index 326d42ce2..d04d51637 100644 --- a/src/common/trace-chunk.c +++ b/src/common/trace-chunk.c @@ -1,18 +1,8 @@ /* - * Copyright (C) 2019 - Jérémie Galarneau + * Copyright (C) 2019 Jérémie Galarneau * - * This library is free software; you can redistribute it and/or modify it - * under the terms of the GNU Lesser General Public License, version 2.1 only, - * as published by the Free Software Foundation. + * SPDX-License-Identifier: LGPL-2.1-only * - * This library is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this library; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include @@ -21,6 +11,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -105,8 +98,14 @@ struct lttng_trace_chunk { char *path; /* An unset id means the chunk is anonymous. */ LTTNG_OPTIONAL(uint64_t) id; + + /* + * The creation and close timestamps are NOT monotonic. + * They must not be used in context were monotonicity is required. + */ LTTNG_OPTIONAL(time_t) timestamp_creation; LTTNG_OPTIONAL(time_t) timestamp_close; + LTTNG_OPTIONAL(struct chunk_credentials) credentials; struct lttng_directory_handle *session_output_directory; struct lttng_directory_handle *chunk_directory; @@ -136,6 +135,24 @@ struct lttng_trace_chunk_registry { struct cds_lfht *ht; }; +struct fs_handle_untracked { + struct fs_handle parent; + int fd; + struct { + struct lttng_directory_handle *directory_handle; + char *path; + } location; +}; + +static +int fs_handle_untracked_get_fd(struct fs_handle *handle); +static +void fs_handle_untracked_put_fd(struct fs_handle *handle); +static +int fs_handle_untracked_unlink(struct fs_handle *handle); +static +int fs_handle_untracked_close(struct fs_handle *handle); + static const char *close_command_names[] = { [LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED] = @@ -156,6 +173,92 @@ chunk_command close_command_post_release_funcs[] = { lttng_trace_chunk_delete_post_release, }; +static +struct fs_handle *fs_handle_untracked_create( + struct lttng_directory_handle *directory_handle, + const char *path, + int fd) +{ + struct fs_handle_untracked *handle = NULL; + bool reference_acquired; + char *path_copy = strdup(path); + + LTTNG_ASSERT(fd >= 0); + if (!path_copy) { + PERROR("Failed to copy file path while creating untracked filesystem handle"); + goto end; + } + + handle = zmalloc(sizeof(typeof(*handle))); + if (!handle) { + PERROR("Failed to allocate untracked filesystem handle"); + goto end; + } + + handle->parent = (typeof(handle->parent)) { + .get_fd = fs_handle_untracked_get_fd, + .put_fd = fs_handle_untracked_put_fd, + .unlink = fs_handle_untracked_unlink, + .close = fs_handle_untracked_close, + }; + + handle->fd = fd; + reference_acquired = lttng_directory_handle_get(directory_handle); + LTTNG_ASSERT(reference_acquired); + handle->location.directory_handle = directory_handle; + /* Ownership is transferred. */ + handle->location.path = path_copy; + path_copy = NULL; +end: + free(path_copy); + return handle ? &handle->parent : NULL; +} + +static +int fs_handle_untracked_get_fd(struct fs_handle *_handle) +{ + struct fs_handle_untracked *handle = container_of( + _handle, struct fs_handle_untracked, parent); + + return handle->fd; +} + +static +void fs_handle_untracked_put_fd(struct fs_handle *_handle) +{ + /* no-op. */ +} + +static +int fs_handle_untracked_unlink(struct fs_handle *_handle) +{ + struct fs_handle_untracked *handle = container_of( + _handle, struct fs_handle_untracked, parent); + + return lttng_directory_handle_unlink_file( + handle->location.directory_handle, + handle->location.path); +} + +static +void fs_handle_untracked_destroy(struct fs_handle_untracked *handle) +{ + lttng_directory_handle_put(handle->location.directory_handle); + free(handle->location.path); + free(handle); +} + +static +int fs_handle_untracked_close(struct fs_handle *_handle) +{ + struct fs_handle_untracked *handle = container_of( + _handle, struct fs_handle_untracked, parent); + int ret = close(handle->fd); + + fs_handle_untracked_destroy(handle); + return ret; +} + static bool lttng_trace_chunk_registry_element_equals( const struct lttng_trace_chunk_registry_element *a, @@ -266,7 +369,7 @@ void lttng_trace_chunk_fini(struct lttng_trace_chunk *chunk) } 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; @@ -292,21 +395,19 @@ end: return chunk; } -LTTNG_HIDDEN struct lttng_trace_chunk *lttng_trace_chunk_create_anonymous(void) { DBG("Creating anonymous trace chunk"); return lttng_trace_chunk_allocate(); } -LTTNG_HIDDEN struct lttng_trace_chunk *lttng_trace_chunk_create( 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) { @@ -338,7 +439,7 @@ struct lttng_trace_chunk *lttng_trace_chunk_create( ERR("Failed to allocate trace chunk name storage"); goto error; } - } + } if (path) { chunk->path = strdup(path); if (!chunk->path) { @@ -353,7 +454,7 @@ struct lttng_trace_chunk *lttng_trace_chunk_create( } } - DBG("Chunk name set to \"%s\"", chunk->name ? : "(none)"); + DBG("Chunk name set to \"%s\"", chunk->name ? : "(none)"); end: return chunk; error: @@ -361,17 +462,15 @@ error: return NULL; } -LTTNG_HIDDEN void lttng_trace_chunk_set_fd_tracker(struct lttng_trace_chunk *chunk, struct fd_tracker *fd_tracker) { - assert(!chunk->session_output_directory); - assert(!chunk->chunk_directory); - assert(lttng_dynamic_pointer_array_get_count(&chunk->files) == 0); + LTTNG_ASSERT(!chunk->session_output_directory); + LTTNG_ASSERT(!chunk->chunk_directory); + LTTNG_ASSERT(lttng_dynamic_pointer_array_get_count(&chunk->files) == 0); chunk->fd_tracker = fd_tracker; } -LTTNG_HIDDEN struct lttng_trace_chunk *lttng_trace_chunk_copy( struct lttng_trace_chunk *source_chunk) { @@ -420,7 +519,7 @@ struct lttng_trace_chunk *lttng_trace_chunk_copy( const bool reference_acquired = lttng_directory_handle_get( source_chunk->session_output_directory); - assert(reference_acquired); + LTTNG_ASSERT(reference_acquired); new_chunk->session_output_directory = source_chunk->session_output_directory; } @@ -428,7 +527,7 @@ struct lttng_trace_chunk *lttng_trace_chunk_copy( const bool reference_acquired = lttng_directory_handle_get( source_chunk->chunk_directory); - assert(reference_acquired); + LTTNG_ASSERT(reference_acquired); new_chunk->chunk_directory = source_chunk->chunk_directory; } new_chunk->close_command = source_chunk->close_command; @@ -442,7 +541,6 @@ error_unlock: return NULL; } -LTTNG_HIDDEN enum lttng_trace_chunk_status lttng_trace_chunk_get_id( struct lttng_trace_chunk *chunk, uint64_t *id) { @@ -458,7 +556,6 @@ enum lttng_trace_chunk_status lttng_trace_chunk_get_id( return status; } -LTTNG_HIDDEN enum lttng_trace_chunk_status lttng_trace_chunk_get_creation_timestamp( struct lttng_trace_chunk *chunk, time_t *creation_ts) @@ -475,7 +572,6 @@ enum lttng_trace_chunk_status lttng_trace_chunk_get_creation_timestamp( return status; } -LTTNG_HIDDEN enum lttng_trace_chunk_status lttng_trace_chunk_get_close_timestamp( struct lttng_trace_chunk *chunk, time_t *close_ts) { @@ -491,7 +587,6 @@ enum lttng_trace_chunk_status lttng_trace_chunk_get_close_timestamp( return status; } -LTTNG_HIDDEN enum lttng_trace_chunk_status lttng_trace_chunk_set_close_timestamp( struct lttng_trace_chunk *chunk, time_t close_ts) { @@ -503,11 +598,20 @@ enum lttng_trace_chunk_status lttng_trace_chunk_set_close_timestamp( status = LTTNG_TRACE_CHUNK_STATUS_INVALID_OPERATION; goto end; } + + /* + * Note: we do not enforce that the closing timestamp be greater or + * equal to the begin timestamp. These timestamps are used for + * generating the chunk name and should only be used in context where + * the monotonicity of time is not important. The source of those + * timestamps is NOT monotonic and represent the system calendar time, + * also know as the wall time. + */ if (chunk->timestamp_creation.value > close_ts) { - ERR("Failed to set trace chunk close timestamp: close timestamp is before creation timestamp"); - status = LTTNG_TRACE_CHUNK_STATUS_INVALID_ARGUMENT; - goto end; + WARN("Set trace chunk close timestamp: close timestamp is before creation timestamp, begin : %ld, close : %ld", + chunk->timestamp_creation.value, close_ts); } + LTTNG_OPTIONAL_SET(&chunk->timestamp_close, close_ts); if (!chunk->name_overridden) { free(chunk->name); @@ -523,7 +627,6 @@ end: return status; } -LTTNG_HIDDEN enum lttng_trace_chunk_status lttng_trace_chunk_get_name( struct lttng_trace_chunk *chunk, const char **name, bool *name_overridden) @@ -531,10 +634,10 @@ enum lttng_trace_chunk_status lttng_trace_chunk_get_name( 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; } @@ -544,7 +647,6 @@ end: return status; } -LTTNG_HIDDEN bool lttng_trace_chunk_get_name_overridden(struct lttng_trace_chunk *chunk) { bool name_overridden; @@ -576,7 +678,6 @@ bool is_valid_chunk_name(const char *name) return true; } -LTTNG_HIDDEN enum lttng_trace_chunk_status lttng_trace_chunk_override_name( struct lttng_trace_chunk *chunk, const char *name) @@ -670,7 +771,7 @@ enum lttng_trace_chunk_status lttng_trace_chunk_rename_path_no_lock( goto skip_move; } - if (old_path[0] != '\0' && path[0] != '\0') { + if (old_path && old_path[0] != '\0' && path[0] != '\0') { /* Rename chunk directory. */ ret = lttng_directory_handle_rename_as_user( chunk->session_output_directory, @@ -686,9 +787,14 @@ enum lttng_trace_chunk_status lttng_trace_chunk_rename_path_no_lock( status = LTTNG_TRACE_CHUNK_STATUS_ERROR; goto end; } - rename_directory = lttng_directory_handle_create_from_handle( - path, - chunk->session_output_directory); + rename_directory = chunk->fd_tracker ? + fd_tracker_create_directory_handle_from_handle( + chunk->fd_tracker, + chunk->session_output_directory, + path) : + lttng_directory_handle_create_from_handle( + path, + chunk->session_output_directory); if (!rename_directory) { ERR("Failed to get handle to trace chunk rename directory"); status = LTTNG_TRACE_CHUNK_STATUS_ERROR; @@ -703,7 +809,7 @@ enum lttng_trace_chunk_status lttng_trace_chunk_rename_path_no_lock( */ chunk->chunk_directory = rename_directory; rename_directory = NULL; - } else if (old_path[0] == '\0') { + } else if (old_path && old_path[0] == '\0') { size_t i, count = lttng_dynamic_pointer_array_get_count( &chunk->top_level_directories); @@ -758,13 +864,13 @@ enum lttng_trace_chunk_status lttng_trace_chunk_rename_path_no_lock( */ chunk->chunk_directory = rename_directory; rename_directory = NULL; - } else { + } else if (old_path) { size_t i, count = lttng_dynamic_pointer_array_get_count( &chunk->top_level_directories); const bool reference_acquired = lttng_directory_handle_get( chunk->session_output_directory); - assert(reference_acquired); + LTTNG_ASSERT(reference_acquired); rename_directory = chunk->session_output_directory; /* Move toplevel directories. */ @@ -804,21 +910,20 @@ enum lttng_trace_chunk_status lttng_trace_chunk_rename_path_no_lock( if (status != LTTNG_TRACE_CHUNK_STATUS_OK) { ERR("Error removing subdirectory '%s' file when deleting chunk", old_path); - ret = -1; goto end; } + } else { + /* Unexpected !old_path && !path. */ + status = LTTNG_TRACE_CHUNK_STATUS_INVALID_ARGUMENT; + goto end; } skip_move: - if (path) { - new_path = strdup(path); - if (!new_path) { - ERR("Failed to allocate new trace chunk path"); - status = LTTNG_TRACE_CHUNK_STATUS_ERROR; - goto end; - } - } else { - new_path = NULL; + new_path = strdup(path); + if (!new_path) { + ERR("Failed to allocate new trace chunk path"); + status = LTTNG_TRACE_CHUNK_STATUS_ERROR; + goto end; } free(chunk->path); chunk->path = new_path; @@ -827,7 +932,6 @@ end: return status; } -LTTNG_HIDDEN enum lttng_trace_chunk_status lttng_trace_chunk_rename_path( struct lttng_trace_chunk *chunk, const char *path) @@ -841,7 +945,6 @@ enum lttng_trace_chunk_status lttng_trace_chunk_rename_path( return status; } -LTTNG_HIDDEN enum lttng_trace_chunk_status lttng_trace_chunk_get_credentials( struct lttng_trace_chunk *chunk, struct lttng_credentials *credentials) @@ -851,8 +954,8 @@ enum lttng_trace_chunk_status lttng_trace_chunk_get_credentials( 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; } @@ -863,7 +966,6 @@ enum lttng_trace_chunk_status lttng_trace_chunk_get_credentials( return status; } -LTTNG_HIDDEN enum lttng_trace_chunk_status lttng_trace_chunk_set_credentials( struct lttng_trace_chunk *chunk, const struct lttng_credentials *user_credentials) @@ -885,7 +987,6 @@ end: return status; } -LTTNG_HIDDEN enum lttng_trace_chunk_status lttng_trace_chunk_set_credentials_current_user( struct lttng_trace_chunk *chunk) { @@ -906,7 +1007,6 @@ end: } -LTTNG_HIDDEN enum lttng_trace_chunk_status lttng_trace_chunk_set_as_owner( struct lttng_trace_chunk *chunk, struct lttng_directory_handle *session_output_directory) @@ -930,7 +1030,7 @@ enum lttng_trace_chunk_status lttng_trace_chunk_set_as_owner( status = LTTNG_TRACE_CHUNK_STATUS_ERROR; goto end; } - if (chunk->path[0] != '\0') { + if (chunk->path && chunk->path[0] != '\0') { ret = lttng_directory_handle_create_subdirectory_as_user( session_output_directory, chunk->path, @@ -944,9 +1044,14 @@ enum lttng_trace_chunk_status lttng_trace_chunk_set_as_owner( goto end; } chunk_directory_handle = - lttng_directory_handle_create_from_handle( - chunk->path, - session_output_directory); + chunk->fd_tracker ? + fd_tracker_create_directory_handle_from_handle( + chunk->fd_tracker, + session_output_directory, + chunk->path) : + lttng_directory_handle_create_from_handle( + chunk->path, + session_output_directory); if (!chunk_directory_handle) { /* The function already logs on all error paths. */ status = LTTNG_TRACE_CHUNK_STATUS_ERROR; @@ -957,18 +1062,17 @@ enum lttng_trace_chunk_status lttng_trace_chunk_set_as_owner( * 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); + LTTNG_ASSERT(reference_acquired); chunk_directory_handle = session_output_directory; } chunk->chunk_directory = chunk_directory_handle; chunk_directory_handle = NULL; reference_acquired = lttng_directory_handle_get( session_output_directory); - assert(reference_acquired); + LTTNG_ASSERT(reference_acquired); chunk->session_output_directory = session_output_directory; LTTNG_OPTIONAL_SET(&chunk->mode, TRACE_CHUNK_MODE_OWNER); end: @@ -976,7 +1080,6 @@ end: return status; } -LTTNG_HIDDEN enum lttng_trace_chunk_status lttng_trace_chunk_set_as_user( struct lttng_trace_chunk *chunk, struct lttng_directory_handle *chunk_directory) @@ -995,7 +1098,7 @@ enum lttng_trace_chunk_status lttng_trace_chunk_set_as_user( goto end; } reference_acquired = lttng_directory_handle_get(chunk_directory); - assert(reference_acquired); + LTTNG_ASSERT(reference_acquired); chunk->chunk_directory = chunk_directory; LTTNG_OPTIONAL_SET(&chunk->mode, TRACE_CHUNK_MODE_USER); end: @@ -1003,7 +1106,6 @@ end: return status; } -LTTNG_HIDDEN enum lttng_trace_chunk_status lttng_trace_chunk_get_session_output_directory_handle( struct lttng_trace_chunk *chunk, @@ -1020,7 +1122,7 @@ lttng_trace_chunk_get_session_output_directory_handle( const bool reference_acquired = lttng_directory_handle_get( chunk->session_output_directory); - assert(reference_acquired); + LTTNG_ASSERT(reference_acquired); *handle = chunk->session_output_directory; } end: @@ -1028,7 +1130,6 @@ end: return status; } -LTTNG_HIDDEN enum lttng_trace_chunk_status lttng_trace_chunk_borrow_chunk_directory_handle( struct lttng_trace_chunk *chunk, const struct lttng_directory_handle **handle) @@ -1096,7 +1197,6 @@ end: return ret; } -LTTNG_HIDDEN enum lttng_trace_chunk_status lttng_trace_chunk_create_subdirectory( struct lttng_trace_chunk *chunk, const char *path) @@ -1227,19 +1327,22 @@ void lttng_trace_chunk_remove_file( } ret = lttng_dynamic_pointer_array_remove_pointer( &chunk->files, index); - assert(!ret); + LTTNG_ASSERT(!ret); } -LTTNG_HIDDEN -enum lttng_trace_chunk_status lttng_trace_chunk_open_file( - struct lttng_trace_chunk *chunk, const char *file_path, - int flags, mode_t mode, int *out_fd, bool expect_no_file) +static +enum lttng_trace_chunk_status _lttng_trace_chunk_open_fs_handle_locked( + struct lttng_trace_chunk *chunk, + const char *file_path, + int flags, + mode_t mode, + struct fs_handle **out_handle, + bool expect_no_file) { int ret; enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK; DBG("Opening trace chunk file \"%s\"", file_path); - pthread_mutex_lock(&chunk->lock); if (!chunk->credentials.is_set) { /* * Fatal error, credentials must be set before a @@ -1260,10 +1363,26 @@ enum lttng_trace_chunk_status lttng_trace_chunk_open_file( if (status != LTTNG_TRACE_CHUNK_STATUS_OK) { goto end; } - ret = lttng_directory_handle_open_file_as_user( - chunk->chunk_directory, file_path, flags, mode, - chunk->credentials.value.use_current_user ? - NULL : &chunk->credentials.value.user); + if (chunk->fd_tracker) { + LTTNG_ASSERT(chunk->credentials.value.use_current_user); + *out_handle = fd_tracker_open_fs_handle(chunk->fd_tracker, + chunk->chunk_directory, file_path, flags, &mode); + ret = *out_handle ? 0 : -1; + } else { + ret = lttng_directory_handle_open_file_as_user( + chunk->chunk_directory, file_path, flags, mode, + chunk->credentials.value.use_current_user ? + NULL : + &chunk->credentials.value.user); + if (ret >= 0) { + *out_handle = fs_handle_untracked_create( + chunk->chunk_directory, file_path, ret); + if (!*out_handle) { + status = LTTNG_TRACE_CHUNK_STATUS_ERROR; + goto end; + } + } + } if (ret < 0) { if (errno == ENOENT && expect_no_file) { status = LTTNG_TRACE_CHUNK_STATUS_NO_FILE; @@ -1275,13 +1394,60 @@ enum lttng_trace_chunk_status lttng_trace_chunk_open_file( lttng_trace_chunk_remove_file(chunk, file_path); goto end; } - *out_fd = ret; end: + return status; +} + +enum lttng_trace_chunk_status lttng_trace_chunk_open_fs_handle( + struct lttng_trace_chunk *chunk, + const char *file_path, + int flags, + mode_t mode, + struct fs_handle **out_handle, + bool expect_no_file) +{ + enum lttng_trace_chunk_status status; + + pthread_mutex_lock(&chunk->lock); + status = _lttng_trace_chunk_open_fs_handle_locked(chunk, file_path, + flags, mode, out_handle, expect_no_file); pthread_mutex_unlock(&chunk->lock); return status; } -LTTNG_HIDDEN +enum lttng_trace_chunk_status lttng_trace_chunk_open_file( + struct lttng_trace_chunk *chunk, + const char *file_path, + int flags, + mode_t mode, + int *out_fd, + bool expect_no_file) +{ + enum lttng_trace_chunk_status status; + struct fs_handle *fs_handle; + + pthread_mutex_lock(&chunk->lock); + /* + * Using this method is never valid when an fd_tracker is being + * used since the resulting file descriptor would not be tracked. + */ + LTTNG_ASSERT(!chunk->fd_tracker); + status = _lttng_trace_chunk_open_fs_handle_locked(chunk, file_path, + flags, mode, &fs_handle, expect_no_file); + pthread_mutex_unlock(&chunk->lock); + + if (status == LTTNG_TRACE_CHUNK_STATUS_OK) { + *out_fd = fs_handle_get_fd(fs_handle); + /* + * Does not close the fd; we just "unbox" it from the fs_handle. + */ + fs_handle_untracked_destroy(container_of( + fs_handle, struct fs_handle_untracked, parent)); + } + + return status; +} + int lttng_trace_chunk_unlink_file(struct lttng_trace_chunk *chunk, const char *file_path) { @@ -1320,7 +1486,7 @@ end: return status; } -LTTNG_HIDDEN +static int lttng_trace_chunk_remove_subdirectory_recursive(struct lttng_trace_chunk *chunk, const char *path) { @@ -1383,9 +1549,9 @@ int lttng_trace_chunk_move_to_completed_post_release( goto end; } - assert(trace_chunk->mode.value == TRACE_CHUNK_MODE_OWNER); - assert(!trace_chunk->name_overridden); - assert(trace_chunk->path); + LTTNG_ASSERT(trace_chunk->mode.value == TRACE_CHUNK_MODE_OWNER); + LTTNG_ASSERT(!trace_chunk->name_overridden); + LTTNG_ASSERT(trace_chunk->path); archived_chunk_name = generate_chunk_name(chunk_id, creation_timestamp, &close_timestamp); @@ -1397,7 +1563,7 @@ int lttng_trace_chunk_move_to_completed_post_release( 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 : @@ -1408,9 +1574,14 @@ int lttng_trace_chunk_move_to_completed_post_release( goto end; } - archived_chunks_directory = lttng_directory_handle_create_from_handle( - DEFAULT_ARCHIVED_TRACE_CHUNKS_DIRECTORY, - trace_chunk->session_output_directory); + archived_chunks_directory = trace_chunk->fd_tracker ? + fd_tracker_create_directory_handle_from_handle( + trace_chunk->fd_tracker, + trace_chunk->session_output_directory, + DEFAULT_ARCHIVED_TRACE_CHUNKS_DIRECTORY) : + lttng_directory_handle_create_from_handle( + DEFAULT_ARCHIVED_TRACE_CHUNKS_DIRECTORY, + trace_chunk->session_output_directory); if (!archived_chunks_directory) { PERROR("Failed to get handle to archived trace chunks directory"); ret = -1; @@ -1502,8 +1673,8 @@ int lttng_trace_chunk_delete_post_release_owner( DBG("Trace chunk \"delete\" close command post-release (Owner)"); - assert(trace_chunk->session_output_directory); - assert(trace_chunk->chunk_directory); + LTTNG_ASSERT(trace_chunk->session_output_directory); + LTTNG_ASSERT(trace_chunk->chunk_directory); /* Remove empty directories. */ count = lttng_dynamic_pointer_array_get_count( @@ -1564,7 +1735,6 @@ int lttng_trace_chunk_delete_post_release( } } -LTTNG_HIDDEN enum lttng_trace_chunk_status lttng_trace_chunk_get_close_command( struct lttng_trace_chunk *chunk, enum lttng_trace_chunk_command_type *command_type) @@ -1582,7 +1752,6 @@ enum lttng_trace_chunk_status lttng_trace_chunk_get_close_command( return status; } -LTTNG_HIDDEN enum lttng_trace_chunk_status lttng_trace_chunk_set_close_command( struct lttng_trace_chunk *chunk, enum lttng_trace_chunk_command_type close_command) @@ -1600,10 +1769,10 @@ enum lttng_trace_chunk_status lttng_trace_chunk_set_close_command( 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. @@ -1618,7 +1787,6 @@ end: return status; } -LTTNG_HIDDEN const char *lttng_trace_chunk_command_type_get_name( enum lttng_trace_chunk_command_type command) { @@ -1634,7 +1802,36 @@ const char *lttng_trace_chunk_command_type_get_name( } } -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; +} + bool lttng_trace_chunk_get(struct lttng_trace_chunk *chunk) { return urcu_ref_get_unless_zero(&chunk->ref); @@ -1687,17 +1884,15 @@ void lttng_trace_chunk_release(struct urcu_ref *ref) } } -LTTNG_HIDDEN void lttng_trace_chunk_put(struct lttng_trace_chunk *chunk) { if (!chunk) { return; } - assert(chunk->ref.refcount); + LTTNG_ASSERT(chunk->ref.refcount); urcu_ref_put(&chunk->ref, lttng_trace_chunk_release); } -LTTNG_HIDDEN struct lttng_trace_chunk_registry *lttng_trace_chunk_registry_create(void) { struct lttng_trace_chunk_registry *registry; @@ -1719,7 +1914,6 @@ error: return NULL; } -LTTNG_HIDDEN void lttng_trace_chunk_registry_destroy( struct lttng_trace_chunk_registry *registry) { @@ -1728,7 +1922,7 @@ void lttng_trace_chunk_registry_destroy( } if (registry->ht) { int ret = cds_lfht_destroy(registry->ht, NULL); - assert(!ret); + LTTNG_ASSERT(!ret); } free(registry); } @@ -1772,7 +1966,6 @@ end: return element; } -LTTNG_HIDDEN struct lttng_trace_chunk * lttng_trace_chunk_registry_publish_chunk( struct lttng_trace_chunk_registry *registry, @@ -1802,13 +1995,13 @@ lttng_trace_chunk_registry_publish_chunk( 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)) { break; @@ -1899,17 +2092,15 @@ end: return published_chunk; } -LTTNG_HIDDEN struct lttng_trace_chunk * lttng_trace_chunk_registry_find_chunk( 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); } -LTTNG_HIDDEN int lttng_trace_chunk_registry_chunk_exists( const struct lttng_trace_chunk_registry *registry, uint64_t session_id, uint64_t chunk_id, bool *chunk_exists) @@ -1944,17 +2135,15 @@ end: return ret; } -LTTNG_HIDDEN struct lttng_trace_chunk * lttng_trace_chunk_registry_find_anonymous_chunk( 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); } -LTTNG_HIDDEN unsigned int lttng_trace_chunk_registry_put_each_chunk( const struct lttng_trace_chunk_registry *registry) {