[lttng-dev] [PATCH lttng-ust 8/8] Support unloading of probe providers
Mathieu Desnoyers
mathieu.desnoyers at efficios.com
Wed Feb 7 21:03:53 UTC 2018
----- On Feb 2, 2018, at 2:48 PM, Francis Deslauriers francis.deslauriers at efficios.com wrote:
> With this commit, it's now possible to dlclose() a library containing an
> actively used probe provider.
>
> The destructor of such library will now iterate over all the sessions
> and over all probe definitions to unregister them from the respective
> callsites in the process.
>
> Signed-off-by: Francis Deslauriers <francis.deslauriers at efficios.com>
> ---
> liblttng-ust/lttng-events.c | 22 +++++++++++++++++++++-
> liblttng-ust/lttng-probes.c | 5 ++++-
> liblttng-ust/tracepoint.c | 43 ++++++++++++++++++++++++++++++++++---------
> 3 files changed, 59 insertions(+), 11 deletions(-)
>
> diff --git a/liblttng-ust/lttng-events.c b/liblttng-ust/lttng-events.c
> index 07385d7..698210c 100644
> --- a/liblttng-ust/lttng-events.c
> +++ b/liblttng-ust/lttng-events.c
> @@ -793,7 +793,7 @@ void lttng_create_event_if_missing(struct lttng_enabler
> *enabler)
> */
> void lttng_probe_provider_unregister_events(struct lttng_probe_desc
> *provider_desc)
> {
> - int i;
> + unsigned int i, j;
shorter lines below whenever possible.
> struct cds_list_head *sessionsp;
> struct lttng_session *session;
> struct cds_hlist_head *head;
> @@ -867,7 +867,27 @@ void lttng_probe_provider_unregister_events(struct
> lttng_probe_desc *provider_de
> head = &session->events_ht.table[hash & (LTTNG_UST_EVENT_HT_SIZE - 1)];
> cds_hlist_for_each_entry(event, node, head, hlist) {
> if (event_desc == event->desc) {
> + /* Destroy enums of the current event. */
> + for (j = 0; j < event->desc->nr_fields; j++) {
> + const struct lttng_event_field *field;
> + const struct lttng_enum_desc *enum_desc;
> + struct lttng_enum *curr_enum;
> +
> + field = &(event->desc->fields[j]);
> + if (field->type.atype != atype_enum) {
> + continue;
> + }
> +
> + enum_desc = field->type.u.basic.enumeration.desc;
> + curr_enum = lttng_ust_enum_get_from_desc(session, enum_desc);
> + if (curr_enum) {
> + _lttng_enum_destroy(curr_enum);
> + }
> + }
> +
> + /* Destroy event. */
> _lttng_event_destroy(event);
> +
> break;
> }
> }
> diff --git a/liblttng-ust/lttng-probes.c b/liblttng-ust/lttng-probes.c
> index a09497f..862b19e 100644
> --- a/liblttng-ust/lttng-probes.c
> +++ b/liblttng-ust/lttng-probes.c
> @@ -226,7 +226,10 @@ void lttng_probe_unregister(struct lttng_probe_desc *desc)
> cds_list_del(&desc->head);
> else
> cds_list_del(&desc->lazy_init_head);
> - DBG("just unregistered probe %s", desc->provider);
> +
> + lttng_probe_provider_unregister_events(desc);
> + DBG("just unregistered probes of provider %s", desc->provider);
> +
> ust_unlock();
> }
>
> diff --git a/liblttng-ust/tracepoint.c b/liblttng-ust/tracepoint.c
> index 14b8231..8c630a6 100644
> --- a/liblttng-ust/tracepoint.c
> +++ b/liblttng-ust/tracepoint.c
> @@ -107,8 +107,8 @@ struct tracepoint_entry {
> struct lttng_ust_tracepoint_probe *probes;
> int refcount; /* Number of times armed. 0 if disarmed. */
> int callsite_refcount; /* how many libs use this tracepoint */
> - const char *signature;
> - char name[0];
> + char *signature;
> + char *name;
> };
>
> struct tp_probes {
> @@ -132,6 +132,7 @@ struct callsite_entry {
> struct cds_hlist_node hlist; /* hash table node */
> struct cds_list_head node; /* lib list of callsites node */
> struct lttng_ust_tracepoint *tp;
> + bool tp_entry_callsite_ref; /* Has a tp_entry took a ref on this callsite*/
missing space after callsite.
Thanks,
Mathieu
> };
>
> /* coverity[+alloc] */
> @@ -284,6 +285,8 @@ static struct tracepoint_entry *add_tracepoint(const char
> *name,
> struct cds_hlist_node *node;
> struct tracepoint_entry *e;
> size_t name_len = strlen(name);
> + size_t sig_len = strlen(signature);
> + size_t sig_off, name_off;
> uint32_t hash;
>
> if (name_len > LTTNG_UST_SYM_NAME_LEN - 1) {
> @@ -298,19 +301,29 @@ static struct tracepoint_entry *add_tracepoint(const char
> *name,
> return ERR_PTR(-EEXIST); /* Already there */
> }
> }
> +
> /*
> - * Using zmalloc here to allocate a variable length element. Could
> - * cause some memory fragmentation if overused.
> + * Using zmalloc here to allocate a variable length elements: name and
> + * signature. Could cause some memory fragmentation if overused.
> */
> - e = zmalloc(sizeof(struct tracepoint_entry) + name_len + 1);
> + name_off = sizeof(struct tracepoint_entry);
> + sig_off = name_off + name_len + 1;
> +
> + e = zmalloc(sizeof(struct tracepoint_entry) + name_len + 1 + sig_len + 1);
> if (!e)
> return ERR_PTR(-ENOMEM);
> - memcpy(&e->name[0], name, name_len + 1);
> + e->name = (char *) e + name_off;
> + memcpy(e->name, name, name_len + 1);
> e->name[name_len] = '\0';
> +
> + e->signature = (char *) e + sig_off;
> + memcpy(e->signature, signature, sig_len + 1);
> + e->signature[sig_len] = '\0';
> +
> e->probes = NULL;
> e->refcount = 0;
> e->callsite_refcount = 0;
> - e->signature = signature;
> +
> cds_hlist_add_head(&e->hlist, head);
> return e;
> }
> @@ -405,6 +418,7 @@ static void add_callsite(struct tracepoint_lib * lib, struct
> lttng_ust_tracepoin
> if (!tp_entry)
> return;
> tp_entry->callsite_refcount++;
> + e->tp_entry_callsite_ref = true;
> }
>
> /*
> @@ -417,7 +431,8 @@ static void remove_callsite(struct callsite_entry *e)
>
> tp_entry = get_tracepoint(e->tp->name);
> if (tp_entry) {
> - tp_entry->callsite_refcount--;
> + if (e->tp_entry_callsite_ref)
> + tp_entry->callsite_refcount--;
> if (tp_entry->callsite_refcount == 0)
> disable_tracepoint(e->tp);
> }
> @@ -453,10 +468,15 @@ static void tracepoint_sync_callsites(const char *name)
> if (strncmp(name, tp->name, LTTNG_UST_SYM_NAME_LEN - 1))
> continue;
> if (tp_entry) {
> + if (!e->tp_entry_callsite_ref) {
> + tp_entry->callsite_refcount++;
> + e->tp_entry_callsite_ref = true;
> + }
> set_tracepoint(&tp_entry, tp,
> !!tp_entry->refcount);
> } else {
> disable_tracepoint(tp);
> + e->tp_entry_callsite_ref = false;
> }
> }
> }
> @@ -545,7 +565,12 @@ tracepoint_add_probe(const char *name, void (*probe)(void),
> void *data,
> struct lttng_ust_tracepoint_probe *old;
>
> entry = get_tracepoint(name);
> - if (!entry) {
> + if (entry) {
> + if (strcmp(entry->signature, signature) != 0) {
> + ERR("Tracepoint and probe signature do not match.");
> + return ERR_PTR(-EINVAL);
> + }
> + } else {
> entry = add_tracepoint(name, signature);
> if (IS_ERR(entry))
> return (struct lttng_ust_tracepoint_probe *)entry;
> --
> 2.7.4
--
Mathieu Desnoyers
EfficiOS Inc.
http://www.efficios.com
More information about the lttng-dev
mailing list