X-Git-Url: https://git.lttng.org/?a=blobdiff_plain;f=src%2Fbin%2Flttng-sessiond%2Fust-registry.c;h=399d48f681d8e0aa22bd269109e580f0e2206d77;hb=020d7f606b4264ec26bdae8b84d6e85182539ab2;hp=b538a8fa9f37d6f5108c609a3021a27173cbe9ac;hpb=9209cee7e4ccdb6c8c14047a4727bac41302a632;p=lttng-tools.git diff --git a/src/bin/lttng-sessiond/ust-registry.c b/src/bin/lttng-sessiond/ust-registry.c index b538a8fa9..399d48f68 100644 --- a/src/bin/lttng-sessiond/ust-registry.c +++ b/src/bin/lttng-sessiond/ust-registry.c @@ -308,12 +308,28 @@ void ust_registry_destroy_event(struct ust_registry_channel *chan, return; } +/* + * We need to execute ht_destroy outside of RCU read-side critical + * section, so we postpone its execution using call_rcu. It is simpler + * than to change the semantic of the many callers of + * destroy_channel(). + */ +static +void destroy_channel_rcu(struct rcu_head *head) +{ + struct ust_registry_channel *chan = + caa_container_of(head, struct ust_registry_channel, rcu_head); + + if (chan->ht) { + lttng_ht_destroy(chan->ht); + } + free(chan); +} + /* * Destroy every element of the registry and free the memory. This does NOT * free the registry pointer since it might not have been allocated before so * it's the caller responsability. - * - * This *MUST NOT* be called within a RCU read side lock section. */ static void destroy_channel(struct ust_registry_channel *chan) { @@ -329,9 +345,7 @@ static void destroy_channel(struct ust_registry_channel *chan) ust_registry_destroy_event(chan, event); } rcu_read_unlock(); - - lttng_ht_destroy(chan->ht); - free(chan); + call_rcu(&chan->rcu_head, destroy_channel_rcu); } /* @@ -349,7 +363,7 @@ int ust_registry_channel_add(struct ust_registry_session *session, if (!chan) { PERROR("zmalloc ust registry channel"); ret = -ENOMEM; - goto error; + goto error_alloc; } chan->ht = lttng_ht_new(0, LTTNG_HT_TYPE_STRING); @@ -378,7 +392,11 @@ int ust_registry_channel_add(struct ust_registry_session *session, lttng_ht_add_unique_u64(session->channels, &chan->node); rcu_read_unlock(); + return 0; + error: + destroy_channel(chan); +error_alloc: return ret; } @@ -435,12 +453,6 @@ void ust_registry_channel_del_free(struct ust_registry_session *session, ret = lttng_ht_del(session->channels, &iter); assert(!ret); rcu_read_unlock(); - - /* - * Destroying the hash table should be done without RCU - * read-side lock held. Since we own "chan" now, it is OK to use - * it outside of RCU read-side critical section. - */ destroy_channel(chan); end: @@ -474,7 +486,7 @@ int ust_registry_session_init(struct ust_registry_session **sessionp, session = zmalloc(sizeof(*session)); if (!session) { PERROR("zmalloc ust registry session"); - goto error; + goto error_alloc; } pthread_mutex_init(&session->lock, NULL); @@ -510,6 +522,8 @@ int ust_registry_session_init(struct ust_registry_session **sessionp, return 0; error: + ust_registry_session_destroy(session); +error_alloc: return -1; } @@ -535,8 +549,10 @@ void ust_registry_session_destroy(struct ust_registry_session *reg) assert(!ret); destroy_channel(chan); } - lttng_ht_destroy(reg->channels); rcu_read_unlock(); + if (reg->channels) { + lttng_ht_destroy(reg->channels); + } free(reg->metadata); }