summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--kernel/trace/trace_events_hist.c29
1 files changed, 26 insertions, 3 deletions
diff --git a/kernel/trace/trace_events_hist.c b/kernel/trace/trace_events_hist.c
index af4be28f01e0..261163b00137 100644
--- a/kernel/trace/trace_events_hist.c
+++ b/kernel/trace/trace_events_hist.c
@@ -5595,6 +5595,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)
@@ -5630,6 +5631,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;
}
@@ -5639,6 +5645,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);
@@ -5648,10 +5656,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)
@@ -5665,6 +5678,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;
@@ -5672,16 +5686,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;
}