diff options
-rw-r--r-- | kernel/trace/trace_events_hist.c | 29 |
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; } |