+static int lttng_unlinked_file_pool_add_inode(
+ struct lttng_unlinked_file_pool *pool,
+ struct lttng_inode *inode)
+{
+ int ret;
+ const unsigned int unlinked_id = pool->next_id++;
+ char *inode_unlinked_name;
+ bool reference_acquired;
+
+ DBG("Adding inode of %s to unlinked file pool as id %u",
+ inode->location.path, unlinked_id);
+ ret = asprintf(&inode_unlinked_name, "%u", unlinked_id);
+ if (ret < 0) {
+ ERR("Failed to format unlinked inode name");
+ ret = -1;
+ goto end;
+ }
+
+ if (pool->file_count == 0) {
+ DBG("Creating unlinked files directory at %s",
+ pool->unlink_directory_path);
+ assert(!pool->unlink_directory_handle);
+ ret = utils_mkdir(pool->unlink_directory_path,
+ S_IRWXU | S_IRWXG, -1, -1);
+ if (ret) {
+ if (errno == EEXIST) {
+ /*
+ * Unexpected (previous crash?), but not an
+ * error.
+ */
+ DBG("Unlinked file directory \"%s\" already exists",
+ pool->unlink_directory_path);
+ } else {
+ PERROR("Failed to create unlinked files directory at %s",
+ pool->unlink_directory_path);
+ goto end;
+ }
+ }
+ pool->unlink_directory_handle = lttng_directory_handle_create(
+ pool->unlink_directory_path);
+ }
+
+ ret = lttng_directory_handle_rename(inode->location.directory_handle,
+ inode->location.path, pool->unlink_directory_handle,
+ inode_unlinked_name);
+ if (ret) {
+ goto end;
+ }
+
+ lttng_directory_handle_put(inode->location.directory_handle);
+ inode->location.directory_handle = NULL;
+ reference_acquired = lttng_directory_handle_get(
+ pool->unlink_directory_handle);
+ assert(reference_acquired);
+ inode->location.directory_handle = pool->unlink_directory_handle;
+
+ free(inode->location.path);
+ inode->location.path = inode_unlinked_name;
+ inode_unlinked_name = NULL;
+ LTTNG_OPTIONAL_SET(&inode->unlinked_id, unlinked_id);
+ pool->file_count++;
+end:
+ free(inode_unlinked_name);
+ return ret;
+}
+
+static int lttng_unlinked_file_pool_remove_inode(
+ struct lttng_unlinked_file_pool *pool,
+ struct lttng_inode *inode)
+{
+ int ret;
+
+ DBG("Removing inode with unlinked id %u from unlinked file pool",
+ LTTNG_OPTIONAL_GET(inode->unlinked_id));
+
+ ret = lttng_directory_handle_unlink_file(
+ inode->location.directory_handle, inode->location.path);
+ if (ret) {
+ PERROR("Failed to unlink file %s from unlinked file directory",
+ inode->location.path);
+ goto end;
+ }
+ free(inode->location.path);
+ inode->location.path = NULL;
+ lttng_directory_handle_put(inode->location.directory_handle);
+ inode->location.directory_handle = NULL;
+
+ pool->file_count--;
+ if (pool->file_count == 0) {
+ ret = utils_recursive_rmdir(pool->unlink_directory_path);
+ if (ret) {
+ /*
+ * There is nothing the caller can do, don't report an
+ * error except through logging.
+ */
+ PERROR("Failed to remove unlinked files directory at %s",
+ pool->unlink_directory_path);
+ }
+ lttng_directory_handle_put(pool->unlink_directory_handle);
+ pool->unlink_directory_handle = NULL;
+ }
+end:
+ return ret;
+}
+