Fix: relayd: crash on creation of session by peer < 2.11
[lttng-tools.git] / src / common / trace-chunk.c
index 266a02ee68e3933ea2533c70572c714098c4df45..32792926928d6abb6ebed749460e3a970307c2f3 100644 (file)
@@ -1,41 +1,34 @@
 /*
- * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
+ * Copyright (C) 2019 Jérémie Galarneau <jeremie.galarneau@efficios.com>
  *
- * 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 <lttng/constant.h>
-#include <common/string-utils/format.h>
-#include <common/trace-chunk.h>
-#include <common/trace-chunk-registry.h>
-#include <common/hashtable/utils.h>
-#include <common/hashtable/hashtable.h>
-#include <common/error.h>
-#include <common/utils.h>
-#include <common/time.h>
-#include <common/optional.h>
 #include <common/compat/directory-handle.h>
 #include <common/credentials.h>
 #include <common/defaults.h>
 #include <common/dynamic-array.h>
+#include <common/error.h>
+#include <common/fd-tracker/fd-tracker.h>
+#include <common/fd-tracker/utils.h>
+#include <common/fs-handle-internal.h>
+#include <common/hashtable/hashtable.h>
+#include <common/hashtable/utils.h>
+#include <common/optional.h>
+#include <common/string-utils/format.h>
+#include <common/time.h>
+#include <common/trace-chunk-registry.h>
+#include <common/trace-chunk.h>
+#include <common/utils.h>
+#include <lttng/constant.h>
 
-#include <urcu/ref.h>
-#include <urcu/rculfhash.h>
-#include <sys/stat.h>
 #include <inttypes.h>
 #include <pthread.h>
 #include <stdio.h>
+#include <sys/stat.h>
+#include <urcu/rculfhash.h>
+#include <urcu/ref.h>
 
 /*
  * Two ISO 8601-compatible timestamps, separated by a hypen, followed an
@@ -60,6 +53,12 @@ typedef int (*chunk_command)(struct lttng_trace_chunk *trace_chunk);
 /* Move a completed trace chunk to the 'completed' trace archive folder. */
 static
 int lttng_trace_chunk_move_to_completed_post_release(struct lttng_trace_chunk *trace_chunk);
+/* Empty callback. */
+static
+int lttng_trace_chunk_no_operation(struct lttng_trace_chunk *trace_chunk);
+/* Unlink old chunk files. */
+static
+int lttng_trace_chunk_delete_post_release(struct lttng_trace_chunk *trace_chunk);
 static
 enum lttng_trace_chunk_status lttng_trace_chunk_rename_path_no_lock(
                struct lttng_trace_chunk *chunk, const char *path);
@@ -104,6 +103,14 @@ struct lttng_trace_chunk {
        struct lttng_directory_handle *session_output_directory;
        struct lttng_directory_handle *chunk_directory;
        LTTNG_OPTIONAL(enum lttng_trace_chunk_command_type) close_command;
+       /*
+        * fd_tracker instance through which file descriptors should be
+        * created/closed.
+        *
+        * An fd_tracker always outlives any trace chunk; there is no
+        * need to perform any reference counting of that object.
+        */
+       struct fd_tracker *fd_tracker;
 };
 
 /* A trace chunk is uniquely identified by its (session id, chunk id) tuple. */
@@ -121,6 +128,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] =
@@ -135,8 +160,98 @@ static const
 chunk_command close_command_post_release_funcs[] = {
        [LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED] =
                        lttng_trace_chunk_move_to_completed_post_release,
+       [LTTNG_TRACE_CHUNK_COMMAND_TYPE_NO_OPERATION] =
+                       lttng_trace_chunk_no_operation,
+       [LTTNG_TRACE_CHUNK_COMMAND_TYPE_DELETE] =
+                       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);
+
+       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);
+       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,
@@ -342,6 +457,16 @@ 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);
+       chunk->fd_tracker = fd_tracker;
+}
+
 LTTNG_HIDDEN
 struct lttng_trace_chunk *lttng_trace_chunk_copy(
                struct lttng_trace_chunk *source_chunk)
@@ -403,6 +528,7 @@ struct lttng_trace_chunk *lttng_trace_chunk_copy(
                new_chunk->chunk_directory = source_chunk->chunk_directory;
        }
        new_chunk->close_command = source_chunk->close_command;
+       new_chunk->fd_tracker = source_chunk->fd_tracker;
        pthread_mutex_unlock(&source_chunk->lock);
 end:
        return new_chunk;
@@ -640,7 +766,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,
@@ -656,9 +782,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;
@@ -673,7 +804,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);
 
@@ -728,7 +859,7 @@ 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(
@@ -774,21 +905,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;
@@ -900,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,
@@ -914,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;
@@ -973,6 +1108,31 @@ end:
        return status;
 }
 
+LTTNG_HIDDEN
+enum lttng_trace_chunk_status
+lttng_trace_chunk_get_session_output_directory_handle(
+               struct lttng_trace_chunk *chunk,
+               struct lttng_directory_handle **handle)
+{
+       enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
+
+       pthread_mutex_lock(&chunk->lock);
+       if (!chunk->session_output_directory) {
+               status = LTTNG_TRACE_CHUNK_STATUS_NONE;
+               *handle = NULL;
+               goto end;
+       } else {
+               const bool reference_acquired = lttng_directory_handle_get(
+                               chunk->session_output_directory);
+
+               assert(reference_acquired);
+               *handle = chunk->session_output_directory;
+       }
+end:
+       pthread_mutex_unlock(&chunk->lock);
+       return status;
+}
+
 LTTNG_HIDDEN
 enum lttng_trace_chunk_status lttng_trace_chunk_borrow_chunk_directory_handle(
                struct lttng_trace_chunk *chunk,
@@ -1175,16 +1335,19 @@ void lttng_trace_chunk_remove_file(
        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
@@ -1205,10 +1368,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) {
+               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;
@@ -1220,12 +1399,62 @@ 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;
+}
+
+LTTNG_HIDDEN
+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.
+        */
+       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;
+}
+
 LTTNG_HIDDEN
 int lttng_trace_chunk_unlink_file(struct lttng_trace_chunk *chunk,
                const char *file_path)
@@ -1265,7 +1494,7 @@ end:
        return status;
 }
 
-LTTNG_HIDDEN
+static
 int lttng_trace_chunk_remove_subdirectory_recursive(struct lttng_trace_chunk *chunk,
                const char *path)
 {
@@ -1353,9 +1582,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;
@@ -1398,6 +1632,117 @@ end:
        return ret;
 }
 
+static
+int lttng_trace_chunk_no_operation(struct lttng_trace_chunk *trace_chunk)
+{
+       return 0;
+}
+
+static
+int lttng_trace_chunk_delete_post_release_user(
+               struct lttng_trace_chunk *trace_chunk)
+{
+       int ret = 0;
+
+       DBG("Trace chunk \"delete\" close command post-release (User)");
+
+       /* Unlink all files. */
+       while (lttng_dynamic_pointer_array_get_count(&trace_chunk->files) != 0) {
+               enum lttng_trace_chunk_status status;
+               const char *path;
+
+               /* Remove first. */
+               path = lttng_dynamic_pointer_array_get_pointer(
+                               &trace_chunk->files, 0);
+               DBG("Unlink file: %s", path);
+               status = lttng_trace_chunk_unlink_file(trace_chunk, path);
+               if (status != LTTNG_TRACE_CHUNK_STATUS_OK) {
+                       ERR("Error unlinking file '%s' when deleting chunk", path);
+                       ret = -1;
+                       goto end;
+               }
+       }
+end:
+       return ret;
+}
+
+static
+int lttng_trace_chunk_delete_post_release_owner(
+               struct lttng_trace_chunk *trace_chunk)
+{
+       enum lttng_trace_chunk_status status;
+       size_t i, count;
+       int ret = 0;
+
+       ret = lttng_trace_chunk_delete_post_release_user(trace_chunk);
+       if (ret) {
+               goto end;
+       }
+
+       DBG("Trace chunk \"delete\" close command post-release (Owner)");
+
+       assert(trace_chunk->session_output_directory);
+       assert(trace_chunk->chunk_directory);
+
+       /* Remove empty directories. */
+       count = lttng_dynamic_pointer_array_get_count(
+                       &trace_chunk->top_level_directories);
+
+       for (i = 0; i < count; i++) {
+               const char *top_level_name =
+                               lttng_dynamic_pointer_array_get_pointer(
+                                       &trace_chunk->top_level_directories, i);
+
+               status = lttng_trace_chunk_remove_subdirectory_recursive(trace_chunk, top_level_name);
+               if (status != LTTNG_TRACE_CHUNK_STATUS_OK) {
+                       ERR("Error recursively removing subdirectory '%s' file when deleting chunk",
+                                       top_level_name);
+                       ret = -1;
+                       break;
+               }
+       }
+       if (!ret) {
+               lttng_directory_handle_put(trace_chunk->chunk_directory);
+               trace_chunk->chunk_directory = NULL;
+
+               if (trace_chunk->path && trace_chunk->path[0] != '\0') {
+                       status = lttng_directory_handle_remove_subdirectory(
+                                       trace_chunk->session_output_directory,
+                                       trace_chunk->path);
+                       if (status != LTTNG_TRACE_CHUNK_STATUS_OK) {
+                               ERR("Error removing subdirectory '%s' file when deleting chunk",
+                                       trace_chunk->path);
+                               ret = -1;
+                       }
+               }
+       }
+       free(trace_chunk->path);
+       trace_chunk->path = NULL;
+end:
+       return ret;
+}
+
+/*
+ * For local files, session and consumer daemons all run the delete hook. The
+ * consumer daemons have the list of files to unlink, and technically the
+ * session daemon is the owner of the chunk. Unlink all files owned by each
+ * consumer daemon.
+ */
+static
+int lttng_trace_chunk_delete_post_release(
+               struct lttng_trace_chunk *trace_chunk)
+{
+       if (!trace_chunk->chunk_directory) {
+               return 0;
+       }
+
+       if (trace_chunk->mode.value == TRACE_CHUNK_MODE_OWNER) {
+               return lttng_trace_chunk_delete_post_release_owner(trace_chunk);
+       } else {
+               return lttng_trace_chunk_delete_post_release_user(trace_chunk);
+       }
+}
+
 LTTNG_HIDDEN
 enum lttng_trace_chunk_status lttng_trace_chunk_get_close_command(
                struct lttng_trace_chunk *chunk,
@@ -1600,6 +1945,7 @@ lttng_trace_chunk_registry_element_create_from_chunk(
         */
        chunk->name = NULL;
        chunk->path = NULL;
+       element->chunk.fd_tracker = chunk->fd_tracker;
        element->chunk.in_registry_element = true;
 end:
        return element;
@@ -1787,8 +2133,9 @@ lttng_trace_chunk_registry_find_anonymous_chunk(
                        session_id, NULL);
 }
 
+LTTNG_HIDDEN
 unsigned int lttng_trace_chunk_registry_put_each_chunk(
-               struct lttng_trace_chunk_registry *registry)
+               const struct lttng_trace_chunk_registry *registry)
 {
        struct cds_lfht_iter iter;
        struct lttng_trace_chunk_registry_element *chunk_element;
This page took 0.029659 seconds and 4 git commands to generate.