From 4a6c2fbfdc2c8de225f9f0b92658c2e8c4dd25b0 Mon Sep 17 00:00:00 2001 From: Mathieu Desnoyers Date: Thu, 24 Feb 2022 15:42:56 -0500 Subject: [PATCH] Implement counter maps (for listing) Also wire up LTTNG_KERNEL_ABI_SYSCALL_MASK in lttng_counter_ioctl. Signed-off-by: Mathieu Desnoyers Change-Id: If9215bafb010162250636c9407d85fefcd61ebc2 --- include/lttng/events-internal.h | 28 +++++------ src/lttng-abi.c | 49 +++++++++++++++++++ src/lttng-events.c | 83 +++++++++++++++++++++++++++++++++ 3 files changed, 147 insertions(+), 13 deletions(-) diff --git a/include/lttng/events-internal.h b/include/lttng/events-internal.h index 9e516b2c..e79847fe 100644 --- a/include/lttng/events-internal.h +++ b/include/lttng/events-internal.h @@ -256,6 +256,19 @@ struct lttng_kernel_channel_counter_ops_private { size_t *max_nr_elem); /* array of size nr_dimensions */ }; +struct lttng_counter_map_descriptor { + uint64_t user_token; + size_t array_index; + char key[LTTNG_KERNEL_ABI_COUNTER_KEY_LEN]; +}; + +struct lttng_counter_map { + struct lttng_counter_map_descriptor *descriptors; + size_t nr_descriptors; + size_t alloc_len; + struct mutex lock; /* counter map lock */ +}; + struct lttng_kernel_channel_counter_private { struct lttng_kernel_channel_common_private parent; @@ -263,6 +276,8 @@ struct lttng_kernel_channel_counter_private { struct lib_counter *counter; struct lttng_kernel_channel_counter_ops *ops; + struct lttng_counter_map map; + /* Owned either by session or event notifier group. */ /* Session or event notifier group file owner. */ @@ -491,19 +506,6 @@ struct lttng_kernel_channel_buffer_ops_private { uint64_t *id); }; -struct lttng_counter_map_descriptor { - uint64_t user_token; - size_t array_index; - char key[LTTNG_KERNEL_ABI_COUNTER_KEY_LEN]; -}; - -struct lttng_counter_map { - struct lttng_counter_map_descriptor *descriptors; - size_t nr_descriptors; - size_t alloc_len; - struct mutex lock; /* counter map lock */ -}; - #define LTTNG_EVENT_HT_BITS 12 #define LTTNG_EVENT_HT_SIZE (1U << LTTNG_EVENT_HT_BITS) diff --git a/src/lttng-abi.c b/src/lttng-abi.c index f03796fb..b94f34cb 100644 --- a/src/lttng-abi.c +++ b/src/lttng-abi.c @@ -764,6 +764,55 @@ long lttng_counter_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return lttng_channel_enable(&counter->parent); case LTTNG_KERNEL_ABI_DISABLE: return lttng_channel_disable(&counter->parent); + case LTTNG_KERNEL_ABI_SYSCALL_MASK: + return lttng_syscall_table_get_active_mask(&counter->priv->parent.syscall_table, + (struct lttng_kernel_abi_syscall_mask __user *) arg); + case LTTNG_KERNEL_ABI_COUNTER_MAP_NR_DESCRIPTORS: + { + uint64_t __user *user_nr_descriptors = (uint64_t __user *) arg; + uint64_t nr_descriptors; + + mutex_lock(&counter->priv->map.lock); + nr_descriptors = counter->priv->map.nr_descriptors; + mutex_unlock(&counter->priv->map.lock); + return put_user(nr_descriptors, user_nr_descriptors); + } + case LTTNG_KERNEL_ABI_COUNTER_MAP_DESCRIPTOR: + { + struct lttng_kernel_abi_counter_map_descriptor __user *user_descriptor = + (struct lttng_kernel_abi_counter_map_descriptor __user *) arg; + struct lttng_kernel_abi_counter_map_descriptor local_descriptor; + struct lttng_counter_map_descriptor *kernel_descriptor; + int ret; + + if (copy_from_user(&local_descriptor, user_descriptor, + sizeof(local_descriptor))) + return -EFAULT; + if (validate_zeroed_padding(local_descriptor.padding, + sizeof(local_descriptor.padding))) + return -EINVAL; + + mutex_lock(&counter->priv->map.lock); + if (local_descriptor.descriptor_index >= counter->priv->map.nr_descriptors) { + ret = -EOVERFLOW; + goto map_descriptor_error_unlock; + } + kernel_descriptor = &counter->priv->map.descriptors[local_descriptor.descriptor_index]; + local_descriptor.user_token = kernel_descriptor->user_token; + local_descriptor.array_index = kernel_descriptor->array_index; + memcpy(local_descriptor.key, kernel_descriptor->key, LTTNG_KERNEL_ABI_COUNTER_KEY_LEN); + mutex_unlock(&counter->priv->map.lock); + + if (copy_to_user(user_descriptor, &local_descriptor, + sizeof(local_descriptor))) + return -EFAULT; + + return 0; + + map_descriptor_error_unlock: + mutex_unlock(&counter->priv->map.lock); + return ret; + } default: return -ENOSYS; } diff --git a/src/lttng-events.c b/src/lttng-events.c index 640d9d3a..89a72e66 100644 --- a/src/lttng-events.c +++ b/src/lttng-events.c @@ -262,6 +262,7 @@ struct lttng_kernel_channel_counter *lttng_kernel_counter_create( counter->ops = &counter_transport->ops; counter->priv->parent.coalesce_hits = coalesce_hits; counter->priv->transport = counter_transport; + mutex_init(&counter->priv->map.lock); return counter; @@ -278,6 +279,7 @@ void lttng_kernel_counter_destroy(struct lttng_kernel_channel_counter *counter) struct lttng_counter_transport *counter_transport = counter->priv->transport; counter->ops->priv->counter_destroy(counter); + lttng_kvfree(counter->priv->map.descriptors); module_put(counter_transport->owner); } @@ -1303,6 +1305,73 @@ bool lttng_event_enabler_event_name_key_match_event(struct lttng_event_enabler_c } } +static +int lttng_counter_append_descriptor(struct lttng_kernel_channel_counter *counter, + uint64_t user_token, + size_t index, + const char *key) +{ + struct lttng_counter_map *map = &counter->priv->map; + struct lttng_counter_map_descriptor *last; + int ret = 0; + + if (strlen(key) >= LTTNG_KERNEL_ABI_COUNTER_KEY_LEN) { + WARN_ON_ONCE(1); + return -EOVERFLOW; + } + mutex_lock(&map->lock); + if (map->nr_descriptors == map->alloc_len) { + struct lttng_counter_map_descriptor *new_table, *old_table; + size_t old_len = map->nr_descriptors; + size_t new_len = max_t(size_t, old_len + 1, map->alloc_len * 2); + + old_table = map->descriptors; + new_table = lttng_kvzalloc(sizeof(struct lttng_counter_map_descriptor) * new_len, + GFP_KERNEL); + if (!new_table) { + ret = -ENOMEM; + goto unlock; + } + + if (old_table) + memcpy(new_table, old_table, old_len * sizeof(struct lttng_counter_map_descriptor)); + + map->descriptors = new_table; + map->alloc_len = new_len; + lttng_kvfree(old_table); + } + last = &map->descriptors[map->nr_descriptors++]; + last->user_token = user_token; + last->array_index = index; + strcpy(last->key, key); +unlock: + mutex_unlock(&map->lock); + return ret; +} + +static +int lttng_append_event_to_channel_map(struct lttng_event_enabler_common *event_enabler, + struct lttng_kernel_event_common *event, + const char *event_name) +{ + struct lttng_event_counter_enabler *event_counter_enabler; + struct lttng_kernel_channel_counter *chan_counter; + struct lttng_kernel_event_counter *event_counter; + const char *name = ""; + + if (event_enabler->enabler_type != LTTNG_EVENT_ENABLER_TYPE_COUNTER) + return 0; + event_counter_enabler = container_of(event_enabler, struct lttng_event_counter_enabler, parent.parent); + event_counter = container_of(event, struct lttng_kernel_event_counter, parent); + chan_counter = event_counter_enabler->chan; + if (event_counter->priv->key[0]) + name = event_counter->priv->key; + else + name = event_name; + return lttng_counter_append_descriptor(chan_counter, event_enabler->user_token, + event_counter->priv->parent.id, name); +} + /* * Supports event creation while tracing session is active. * Needs to be called with sessions mutex held. @@ -1408,6 +1477,8 @@ struct lttng_kernel_event_common *_lttng_kernel_event_create(struct lttng_event_ } ret = try_module_get(event->priv->desc->owner); WARN_ON_ONCE(!ret); + ret = lttng_append_event_to_channel_map(event_enabler, event, event_name); + WARN_ON_ONCE(ret); break; case LTTNG_KERNEL_ABI_KRETPROBE: @@ -1459,6 +1530,10 @@ struct lttng_kernel_event_common *_lttng_kernel_event_create(struct lttng_event_ goto statedump_error; } list_add(&event_return->priv->node, event_list_head); + ret = lttng_append_event_to_channel_map(event_enabler, event, event_name); + WARN_ON_ONCE(ret); + ret = lttng_append_event_to_channel_map(event_enabler, event_return, event_name); + WARN_ON_ONCE(ret); break; } @@ -1516,6 +1591,8 @@ struct lttng_kernel_event_common *_lttng_kernel_event_create(struct lttng_event_ goto register_error; ret = try_module_get(event->priv->desc->owner); WARN_ON_ONCE(!ret); + ret = lttng_append_event_to_channel_map(event_enabler, event, event_name); + WARN_ON_ONCE(ret); break; default: @@ -2358,6 +2435,8 @@ int lttng_event_enabler_ref_events(struct lttng_event_enabler_common *event_enab enabler_ref = lttng_enabler_ref(&event_priv->enablers_ref_head, event_enabler); if (!enabler_ref) { + int ret; + /* * If no backward ref, create it. * Add backward ref from event_notifier to enabler. @@ -2368,6 +2447,10 @@ int lttng_event_enabler_ref_events(struct lttng_event_enabler_common *event_enab enabler_ref->ref = event_enabler; list_add(&enabler_ref->node, &event_priv->enablers_ref_head); + + ret = lttng_append_event_to_channel_map(event_enabler, event, + event->priv->desc->event_name); + WARN_ON_ONCE(ret); } lttng_event_enabler_init_event_filter(event_enabler, event); -- 2.34.1