]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
tracing/hist: Support POLLPRI event for poll on histogram
authorMasami Hiramatsu (Google) <mhiramat@kernel.org>
Fri, 27 Dec 2024 04:08:07 +0000 (13:08 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 10 Apr 2025 12:37:41 +0000 (14:37 +0200)
[ Upstream commit 66fc6f521a0b91051ce6968a216a30bc52267bf8 ]

Since POLLIN will not be flushed until the hist file is read, the user
needs to repeatedly read() and poll() on the hist file for monitoring the
event continuously. But the read() is somewhat redundant when the user is
only monitoring for event updates.

Add POLLPRI poll event on the hist file so the event returns when a
histogram is updated after open(), poll() or read(). Thus it is possible
to wait for the next event without having to issue a read().

Cc: Shuah Khan <shuah@kernel.org>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Link: https://lore.kernel.org/173527248770.464571.2536902137325258133.stgit@devnote2
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Reviewed-by: Tom Zanussi <zanussi@kernel.org>
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
Stable-dep-of: 0b4ffbe4888a ("tracing: Correct the refcount if the hist/hist_debug file fails to open")
Signed-off-by: Sasha Levin <sashal@kernel.org>
kernel/trace/trace_events_hist.c

index 49b7811dec9f8a4aeffa74e7f7dc073b59ad6cc8..08cc6405b8837c72fce61b3fc156d8ecd026e4c5 100644 (file)
@@ -5606,6 +5606,7 @@ static void hist_trigger_show(struct seq_file *m,
 struct hist_file_data {
        struct file *file;
        u64 last_read;
+       u64 last_act;
 };
 
 static u64 get_hist_hit_count(struct trace_event_file *event_file)
@@ -5641,6 +5642,11 @@ static int hist_show(struct seq_file *m, void *v)
                        hist_trigger_show(m, data, n++);
        }
        hist_file->last_read = get_hist_hit_count(event_file);
+       /*
+        * Update last_act too so that poll()/POLLPRI can wait for the next
+        * event after any syscall on hist file.
+        */
+       hist_file->last_act = hist_file->last_read;
 
        return 0;
 }
@@ -5650,6 +5656,8 @@ static __poll_t event_hist_poll(struct file *file, struct poll_table_struct *wai
        struct trace_event_file *event_file;
        struct seq_file *m = file->private_data;
        struct hist_file_data *hist_file = m->private;
+       __poll_t ret = 0;
+       u64 cnt;
 
        guard(mutex)(&event_mutex);
 
@@ -5659,10 +5667,15 @@ static __poll_t event_hist_poll(struct file *file, struct poll_table_struct *wai
 
        hist_poll_wait(file, wait);
 
-       if (hist_file->last_read != get_hist_hit_count(event_file))
-               return EPOLLIN | EPOLLRDNORM;
+       cnt = get_hist_hit_count(event_file);
+       if (hist_file->last_read != cnt)
+               ret |= EPOLLIN | EPOLLRDNORM;
+       if (hist_file->last_act != cnt) {
+               hist_file->last_act = cnt;
+               ret |= EPOLLPRI;
+       }
 
-       return 0;
+       return ret;
 }
 
 static int event_hist_release(struct inode *inode, struct file *file)
@@ -5676,6 +5689,7 @@ static int event_hist_release(struct inode *inode, struct file *file)
 
 static int event_hist_open(struct inode *inode, struct file *file)
 {
+       struct trace_event_file *event_file;
        struct hist_file_data *hist_file;
        int ret;
 
@@ -5683,16 +5697,25 @@ static int event_hist_open(struct inode *inode, struct file *file)
        if (ret)
                return ret;
 
+       guard(mutex)(&event_mutex);
+
+       event_file = event_file_data(file);
+       if (!event_file)
+               return -ENODEV;
+
        hist_file = kzalloc(sizeof(*hist_file), GFP_KERNEL);
        if (!hist_file)
                return -ENOMEM;
+
        hist_file->file = file;
+       hist_file->last_act = get_hist_hit_count(event_file);
 
        /* Clear private_data to avoid warning in single_open() */
        file->private_data = NULL;
        ret = single_open(file, hist_show, hist_file);
        if (ret)
                kfree(hist_file);
+
        return ret;
 }