Fix: consumerd: fd still open after `lttng snapshot record` returns
[lttng-tools.git] / src / common / trace-chunk.cpp
index eed3d558b0181d269501fb485e7ec63298a8f8d5..9e804ce0197b25c74a66a0b211cce3fa8f77768a 100644 (file)
@@ -1857,7 +1857,6 @@ 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);
 
-       lttng_trace_chunk_fini(&element->chunk);
        free(element);
 }
 
@@ -1879,6 +1878,24 @@ void lttng_trace_chunk_release(struct urcu_ref *ref)
        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();
@@ -1984,7 +2001,20 @@ 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;
@@ -2019,6 +2049,7 @@ lttng_trace_chunk_registry_publish_chunk(
                        element->registry = registry;
                        /* Acquire a reference for the caller. */
                        if (lttng_trace_chunk_get(&element->chunk)) {
+                               *previously_published = false;
                                break;
                        } else {
                                /*
@@ -2045,6 +2076,7 @@ lttng_trace_chunk_registry_publish_chunk(
                if (lttng_trace_chunk_get(published_chunk)) {
                        lttng_trace_chunk_put(&element->chunk);
                        element = published_element;
+                       *previously_published = true;
                        break;
                }
                /*
This page took 0.024396 seconds and 4 git commands to generate.