Implement event notifier send notification
authorFrancis Deslauriers <francis.deslauriers@efficios.com>
Wed, 5 Feb 2020 19:44:02 +0000 (14:44 -0500)
committerMathieu Desnoyers <mathieu.desnoyers@efficios.com>
Wed, 18 Nov 2020 18:11:02 +0000 (13:11 -0500)
Signed-off-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Signed-off-by: Francis Deslauriers <francis.deslauriers@efficios.com>
Change-Id: Ibdab5a25439da7d4c26e480c41cdd655a7d58d82

include/lttng/abi.h
include/lttng/event-notifier-notification.h [new file with mode: 0644]
include/lttng/events.h
src/Kbuild
src/lttng-abi.c
src/lttng-event-notifier-notification.c [new file with mode: 0644]
src/lttng-events.c

index 03e07ae937b50e06709629f8564416cf5fde2b0e..5f0a3aa52a8ee992b0f5242a3e9412be4b923006 100644 (file)
@@ -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 (file)
index 0000000..f5ef9b9
--- /dev/null
@@ -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 <francis.deslauriers@efficios.com>
+ */
+
+#ifndef _LTTNG_EVENT_NOTIFIER_NOTIFICATION_H
+#define _LTTNG_EVENT_NOTIFIER_NOTIFICATION_H
+
+#include <lttng/events.h>
+
+void lttng_event_notifier_notification_send(struct lttng_event_notifier *event_notifier);
+
+#endif /* _LTTNG_EVENT_NOTIFIER_NOTIFICATION_H */
index e32480a98791286c5ad7f46d59f0b646746e8941..4c94116eec236470bebbfe4de3815a228dae1b3d 100644 (file)
@@ -10,6 +10,7 @@
 #ifndef _LTTNG_EVENTS_H
 #define _LTTNG_EVENTS_H
 
+#include <linux/irq_work.h>
 #include <linux/version.h>
 #include <linux/list.h>
 #include <linux/kprobes.h>
@@ -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 {
index bb149ffac44e9a1655356afd9ffe76021c2d8fba..6e4b50cf048d2f12fd85ecea73ed787a02ed1328 100644 (file)
@@ -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 \
index 07c520f00a0c8d2604e0d170186621b35f46e2ae..6eb838752111ab207fe94dca18ece53fc85b0161 100644 (file)
@@ -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(&notif_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,
+                       &lttng_event_notifier_group_notif_fops,
+                       "[lttng_event_notifier_stream]");
+       if (ret < 0)
+               goto fd_error;
+
+       return ret;
+
+fd_error:
+       atomic_long_dec(&notif_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 (file)
index 0000000..bd08991
--- /dev/null
@@ -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 <francis.deslauriers@efficios.com>
+ */
+
+#include <lttng/events.h>
+#include <lttng/event-notifier-notification.h>
+
+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);
+}
index 092cbb887a97899e4a6fd4be4c50ede12c65d97d..df834298a0dc24a624208da9eed020d66c1fc472 100644 (file)
@@ -37,6 +37,7 @@
 #include <lttng/kernel-version.h>
 #include <lttng/events.h>
 #include <lttng/tracer.h>
+#include <lttng/event-notifier-notification.h>
 #include <lttng/abi-old.h>
 #include <lttng/endian.h>
 #include <lttng/string-utils.h>
@@ -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);
 
This page took 0.030803 seconds and 4 git commands to generate.