*
*/
-#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.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 <common/compat/directory-handle.hpp>
+#include <common/credentials.hpp>
+#include <common/defaults.hpp>
+#include <common/dynamic-array.hpp>
+#include <common/error.hpp>
+#include <common/fd-tracker/fd-tracker.hpp>
+#include <common/fd-tracker/utils.hpp>
+#include <common/fs-handle.hpp>
+#include <common/fs-handle-internal.hpp>
+#include <common/hashtable/hashtable.hpp>
+#include <common/hashtable/utils.hpp>
+#include <common/optional.hpp>
+#include <common/string-utils/format.hpp>
+#include <common/time.hpp>
+#include <common/trace-chunk-registry.hpp>
+#include <common/trace-chunk.hpp>
+#include <common/utils.hpp>
#include <lttng/constant.h>
#include <inttypes.h>
enum lttng_trace_chunk_status lttng_trace_chunk_rename_path_no_lock(
struct lttng_trace_chunk *chunk, const char *path);
+namespace {
struct chunk_credentials {
bool use_current_user;
struct lttng_credentials user;
};
+} /* namespace */
/*
* NOTE: Make sure to update:
struct fd_tracker *fd_tracker;
};
+namespace {
/* A trace chunk is uniquely identified by its (session id, chunk id) tuple. */
struct lttng_trace_chunk_registry_element {
struct lttng_trace_chunk chunk;
/* call_rcu delayed reclaim. */
struct rcu_head rcu_node;
};
+} /* namespace */
struct lttng_trace_chunk_registry {
struct cds_lfht *ht;
};
+namespace {
struct fs_handle_untracked {
struct fs_handle parent;
int fd;
char *path;
} location;
};
+} /* namespace */
static
int fs_handle_untracked_get_fd(struct fs_handle *handle);
};
static
-const chunk_command close_command_get_post_release_func(
+chunk_command close_command_get_post_release_func(
lttng_trace_chunk_command_type type) {
switch (type) {
case LTTNG_TRACE_CHUNK_COMMAND_TYPE_MOVE_TO_COMPLETED:
goto end;
}
- handle = (fs_handle_untracked *) zmalloc(sizeof(typeof(*handle)));
+ handle = zmalloc<fs_handle_untracked>();
if (!handle) {
PERROR("Failed to allocate untracked filesystem handle");
goto end;
static
int fs_handle_untracked_get_fd(struct fs_handle *_handle)
{
- struct fs_handle_untracked *handle = container_of(
- _handle, struct fs_handle_untracked, parent);
+ struct fs_handle_untracked *handle = lttng::utils::container_of(
+ _handle, &fs_handle_untracked::parent);
return handle->fd;
}
static
-void fs_handle_untracked_put_fd(struct fs_handle *_handle)
+void fs_handle_untracked_put_fd(struct fs_handle *_handle __attribute__((unused)))
{
/* 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);
+ struct fs_handle_untracked *handle = lttng::utils::container_of(
+ _handle, &fs_handle_untracked::parent);
return lttng_directory_handle_unlink_file(
handle->location.directory_handle,
static
int fs_handle_untracked_close(struct fs_handle *_handle)
{
- struct fs_handle_untracked *handle = container_of(
- _handle, struct fs_handle_untracked, parent);
+ struct fs_handle_untracked *handle = lttng::utils::container_of(
+ _handle, &fs_handle_untracked::parent);
int ret = close(handle->fd);
fs_handle_untracked_destroy(handle);
goto error;
}
}
- new_name = (char *) zmalloc(GENERATED_CHUNK_NAME_LEN);
+ new_name = calloc<char>(GENERATED_CHUNK_NAME_LEN);
if (!new_name) {
ERR("Failed to allocate buffer for automatically-generated trace chunk name");
goto error;
{
struct lttng_trace_chunk *chunk = NULL;
- chunk = (lttng_trace_chunk *) zmalloc(sizeof(*chunk));
+ chunk = zmalloc<lttng_trace_chunk>();
if (!chunk) {
ERR("Failed to allocate trace chunk");
goto end;
enum lttng_trace_chunk_status status = LTTNG_TRACE_CHUNK_STATUS_OK;
const struct chunk_credentials credentials = {
.use_current_user = true,
+ .user = {},
};
pthread_mutex_lock(&chunk->lock);
/*
* 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));
+ fs_handle_untracked_destroy(lttng::utils::container_of(
+ fs_handle, &fs_handle_untracked::parent));
}
return status;
}
static
-int lttng_trace_chunk_no_operation(struct lttng_trace_chunk *trace_chunk)
+int lttng_trace_chunk_no_operation(struct lttng_trace_chunk *trace_chunk __attribute__((unused)))
{
return 0;
}
static
void free_lttng_trace_chunk_registry_element(struct rcu_head *node)
{
- struct lttng_trace_chunk_registry_element *element =
- container_of(node, typeof(*element), rcu_node);
+ struct lttng_trace_chunk_registry_element *element = lttng::utils::container_of(
+ node, <tng_trace_chunk_registry_element::rcu_node);
- lttng_trace_chunk_fini(&element->chunk);
free(element);
}
static
void lttng_trace_chunk_release(struct urcu_ref *ref)
{
- struct lttng_trace_chunk *chunk = container_of(ref, typeof(*chunk),
- ref);
+ struct lttng_trace_chunk *chunk = lttng::utils::container_of(ref, <tng_trace_chunk::ref);
if (chunk->close_command.is_set) {
chunk_command func = close_command_get_post_release_func(chunk->close_command.value);
if (chunk->in_registry_element) {
struct lttng_trace_chunk_registry_element *element;
- element = container_of(chunk, typeof(*element), chunk);
+ /*
+ * 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 = lttng::utils::container_of(
+ chunk, <tng_trace_chunk_registry_element::chunk);
if (element->registry) {
rcu_read_lock();
cds_lfht_del(element->registry->ht,
{
struct lttng_trace_chunk_registry *registry;
- registry = (lttng_trace_chunk_registry *) zmalloc(sizeof(*registry));
+ registry = zmalloc<lttng_trace_chunk_registry>();
if (!registry) {
goto end;
}
struct lttng_trace_chunk *chunk, uint64_t session_id)
{
struct lttng_trace_chunk_registry_element *element =
- (lttng_trace_chunk_registry_element *) zmalloc(sizeof(*element));
+ zmalloc<lttng_trace_chunk_registry_element>();
if (!element) {
goto end;
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(
+ registry, session_id, chunk, &unused);
+}
+
+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,
+ bool *previously_published)
{
struct lttng_trace_chunk_registry_element *element;
unsigned long element_hash;
element->registry = registry;
/* Acquire a reference for the caller. */
if (lttng_trace_chunk_get(&element->chunk)) {
+ *previously_published = false;
break;
} else {
/*
* already published and release the reference to the copy we
* created if successful.
*/
- published_element = container_of(published_node,
- typeof(*published_element),
- trace_chunk_registry_ht_node);
+ published_element = lttng::utils::container_of(published_node,
+ <tng_trace_chunk_registry_element::trace_chunk_registry_ht_node);
published_chunk = &published_element->chunk;
if (lttng_trace_chunk_get(published_chunk)) {
lttng_trace_chunk_put(&element->chunk);
element = published_element;
+ *previously_published = true;
break;
}
/*
goto end;
}
- published_element = container_of(published_node,
- typeof(*published_element),
- trace_chunk_registry_ht_node);
+ published_element = lttng::utils::container_of(published_node,
+ <tng_trace_chunk_registry_element::trace_chunk_registry_ht_node);
if (lttng_trace_chunk_get(&published_element->chunk)) {
published_chunk = &published_element->chunk;
}