Fix: consumerd: fd still open after `lttng snapshot record` returns
[lttng-tools.git] / src / common / trace-chunk.c
index ec52e5d2b3e30598216e26bf1f8eea6fd7a2ae9a..5518051960e654b654c118429e00e81b211e3cdc 100644 (file)
@@ -1834,7 +1834,12 @@ bool lttng_trace_chunk_ids_equal(const struct lttng_trace_chunk *chunk_a,
 {
        bool equal = false;
 
-       if (!chunk_a || !chunk_b) {
+       if (chunk_a == chunk_b) {
+               equal = true;
+               goto end;
+       }
+
+       if (!!chunk_a ^ !!chunk_b) {
                goto end;
        }
 
@@ -1866,7 +1871,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);
 }
 
@@ -1887,6 +1891,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();
@@ -1996,7 +2018,20 @@ LTTNG_HIDDEN
 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_published(
+                       registry, session_id, chunk, &unused);
+}
+
+struct lttng_trace_chunk *
+lttng_trace_chunk_registry_publish_chunk_published(
+               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;
@@ -2031,6 +2066,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 {
                                /*
@@ -2057,6 +2093,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.024333 seconds and 4 git commands to generate.