From: Francis Deslauriers Date: Wed, 5 Feb 2020 19:44:02 +0000 (-0500) Subject: Implement event notifier send notification X-Git-Tag: v2.13.0-rc1~140 X-Git-Url: http://git.lttng.org/?p=lttng-modules.git;a=commitdiff_plain;h=21f58fb7e62071dae3ddf13817631749bcab4e00 Implement event notifier send notification Signed-off-by: Mathieu Desnoyers Signed-off-by: Francis Deslauriers Change-Id: Ibdab5a25439da7d4c26e480c41cdd655a7d58d82 --- diff --git a/include/lttng/abi.h b/include/lttng/abi.h index 03e07ae9..5f0a3aa5 100644 --- a/include/lttng/abi.h +++ b/include/lttng/abi.h @@ -334,6 +334,8 @@ struct lttng_kernel_tracker_args { /* Event notifier group file descriptor ioctl */ #define LTTNG_KERNEL_EVENT_NOTIFIER_CREATE \ _IOW(0xF6, 0xB0, struct lttng_kernel_event_notifier) +#define LTTNG_KERNEL_EVENT_NOTIFIER_GROUP_NOTIFICATION_FD \ + _IO(0xF6, 0xB1) /* * LTTng-specific ioctls for the lib ringbuffer. diff --git a/include/lttng/event-notifier-notification.h b/include/lttng/event-notifier-notification.h new file mode 100644 index 00000000..f5ef9b98 --- /dev/null +++ b/include/lttng/event-notifier-notification.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: (GPL-2.0-only or LGPL-2.1-only) + * + * lttng/event-notifier-notification.h + * + * Copyright (C) 2020 Francis Deslauriers + */ + +#ifndef _LTTNG_EVENT_NOTIFIER_NOTIFICATION_H +#define _LTTNG_EVENT_NOTIFIER_NOTIFICATION_H + +#include + +void lttng_event_notifier_notification_send(struct lttng_event_notifier *event_notifier); + +#endif /* _LTTNG_EVENT_NOTIFIER_NOTIFICATION_H */ diff --git a/include/lttng/events.h b/include/lttng/events.h index e32480a9..4c94116e 100644 --- a/include/lttng/events.h +++ b/include/lttng/events.h @@ -10,6 +10,7 @@ #ifndef _LTTNG_EVENTS_H #define _LTTNG_EVENTS_H +#include #include #include #include @@ -348,6 +349,7 @@ struct lttng_event_notifier { struct list_head bytecode_runtime_head; int has_enablers_without_bytecode; + void (*send_notification)(struct lttng_event_notifier *event_notifier); struct lttng_event_notifier_group *group; /* Weak ref */ }; @@ -604,6 +606,7 @@ struct lttng_session { struct lttng_event_notifier_group { struct file *file; /* File associated to event notifier group */ + struct file *notif_file; /* File used to expose notifications to userspace. */ struct list_head node; /* event notifier group list */ struct list_head enablers_head; /* List of enablers */ struct list_head event_notifiers_head; /* List of event notifier */ @@ -613,6 +616,8 @@ struct lttng_event_notifier_group { struct lttng_transport *transport; struct channel *chan; /* Ring buffer channel for event notifier group. */ struct lib_ring_buffer *buf; /* Ring buffer for event notifier group. */ + wait_queue_head_t read_wait; + struct irq_work wakeup_pending; /* Pending wakeup irq work. */ }; struct lttng_metadata_cache { diff --git a/src/Kbuild b/src/Kbuild index bb149ffa..6e4b50cf 100644 --- a/src/Kbuild +++ b/src/Kbuild @@ -49,6 +49,7 @@ lttng-tracer-objs := lttng-events.o lttng-abi.o lttng-string-utils.o \ lttng-filter-validator.o \ probes/lttng-probe-user.o \ lttng-tp-mempool.o \ + lttng-event-notifier-notification.o lttng-wrapper-objs := wrapper/page_alloc.o \ wrapper/random.o \ diff --git a/src/lttng-abi.c b/src/lttng-abi.c index 07c520f0..6eb83875 100644 --- a/src/lttng-abi.c +++ b/src/lttng-abi.c @@ -106,6 +106,14 @@ fd_error: return ret; } +void event_notifier_send_notification_work_wakeup(struct irq_work *entry) +{ + struct lttng_event_notifier_group *event_notifier_group = + container_of(entry, struct lttng_event_notifier_group, + wakeup_pending); + wake_up_interruptible(&event_notifier_group->read_wait); +} + static int lttng_abi_create_event_notifier_group(void) { @@ -131,6 +139,9 @@ int lttng_abi_create_event_notifier_group(void) } event_notifier_group->file = event_notifier_group_file; + init_waitqueue_head(&event_notifier_group->read_wait); + init_irq_work(&event_notifier_group->wakeup_pending, + event_notifier_send_notification_work_wakeup); fd_install(event_notifier_group_fd, event_notifier_group_file); return event_notifier_group_fd; @@ -804,6 +815,10 @@ static const struct file_operations lttng_session_fops = { #endif }; +static const struct file_operations lttng_event_notifier_group_notif_fops = { + .owner = THIS_MODULE, +}; + /** * lttng_metadata_ring_buffer_poll - LTTng ring buffer poll file operation * @filp: the file @@ -1307,6 +1322,41 @@ nomem: return ret; } +static +int lttng_abi_open_event_notifier_group_stream(struct file *notif_file) +{ + struct lttng_event_notifier_group *event_notifier_group = notif_file->private_data; + struct channel *chan = event_notifier_group->chan; + struct lib_ring_buffer *buf; + int ret; + void *stream_priv; + + buf = event_notifier_group->ops->buffer_read_open(chan); + if (!buf) + return -ENOENT; + + /* The event_notifier notification fd holds a reference on the event_notifier group */ + if (!atomic_long_add_unless(¬if_file->f_count, 1, LONG_MAX)) { + ret = -EOVERFLOW; + goto refcount_error; + } + event_notifier_group->buf = buf; + stream_priv = event_notifier_group; + ret = lttng_abi_create_stream_fd(notif_file, stream_priv, + <tng_event_notifier_group_notif_fops, + "[lttng_event_notifier_stream]"); + if (ret < 0) + goto fd_error; + + return ret; + +fd_error: + atomic_long_dec(¬if_file->f_count); +refcount_error: + event_notifier_group->ops->buffer_read_close(buf); + return ret; +} + static int lttng_abi_validate_event_param(struct lttng_kernel_event *event_param) { @@ -1625,6 +1675,10 @@ long lttng_event_notifier_group_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { switch (cmd) { + case LTTNG_KERNEL_EVENT_NOTIFIER_GROUP_NOTIFICATION_FD: + { + return lttng_abi_open_event_notifier_group_stream(file); + } case LTTNG_KERNEL_EVENT_NOTIFIER_CREATE: { struct lttng_kernel_event_notifier uevent_notifier_param; diff --git a/src/lttng-event-notifier-notification.c b/src/lttng-event-notifier-notification.c new file mode 100644 index 00000000..bd08991b --- /dev/null +++ b/src/lttng-event-notifier-notification.c @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: (GPL-2.0-only or LGPL-2.1-only) + * + * lttng-event-notifier-notification.c + * + * Copyright (C) 2020 Francis Deslauriers + */ + +#include +#include + +void lttng_event_notifier_notification_send(struct lttng_event_notifier *event_notifier) +{ + struct lttng_event_notifier_group *event_notifier_group = event_notifier->group; + struct lib_ring_buffer_ctx ctx; + int ret; + + if (unlikely(!READ_ONCE(event_notifier->enabled))) + return; + + lib_ring_buffer_ctx_init(&ctx, event_notifier_group->chan, NULL, + sizeof(event_notifier->user_token), + lttng_alignof(event_notifier->user_token), -1); + ret = event_notifier_group->ops->event_reserve(&ctx, 0); + if (ret < 0) { + //TODO: error handling with counter maps + //silently drop for now. + WARN_ON_ONCE(1); + return; + } + lib_ring_buffer_align_ctx(&ctx, lttng_alignof(event_notifier->user_token)); + event_notifier_group->ops->event_write(&ctx, &event_notifier->user_token, + sizeof(event_notifier->user_token)); + event_notifier_group->ops->event_commit(&ctx); + irq_work_queue(&event_notifier_group->wakeup_pending); +} diff --git a/src/lttng-events.c b/src/lttng-events.c index 092cbb88..df834298 100644 --- a/src/lttng-events.c +++ b/src/lttng-events.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -333,6 +334,8 @@ void lttng_event_notifier_group_destroy( WARN_ON(ret); } + irq_work_sync(&event_notifier_group->wakeup_pending); + list_for_each_entry_safe(event_notifier_enabler, tmp_event_notifier_enabler, &event_notifier_group->enablers_head, node) lttng_event_notifier_enabler_destroy(event_notifier_enabler); @@ -1020,11 +1023,13 @@ struct lttng_event_notifier *_lttng_event_notifier_create( ret = -ENOMEM; goto cache_error; } + event_notifier->group = event_notifier_group; event_notifier->user_token = token; event_notifier->filter = filter; event_notifier->instrumentation = itype; event_notifier->evtype = LTTNG_TYPE_EVENT; + event_notifier->send_notification = lttng_event_notifier_notification_send; INIT_LIST_HEAD(&event_notifier->bytecode_runtime_head); INIT_LIST_HEAD(&event_notifier->enablers_ref_head);