summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@lst.de>2018-03-05 10:26:05 -0500
committerChristoph Hellwig <hch@lst.de>2018-05-26 03:16:44 -0400
commit9965ed174e7d38896e5d2582159d8ef31ecd4cb5 (patch)
tree955bfa805fff87c169a4814deaf311b90cca84b2
parent6e8b704df58407aad7607053cb1b5ead4ac4a0bc (diff)
fs: add new vfs_poll and file_can_poll helpers
These abstract out calls to the poll method in preparation for changes in how we poll. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
-rw-r--r--drivers/staging/comedi/drivers/serial2002.c4
-rw-r--r--drivers/vfio/virqfd.c2
-rw-r--r--drivers/vhost/vhost.c2
-rw-r--r--fs/eventpoll.c5
-rw-r--r--fs/select.c23
-rw-r--r--include/linux/poll.h12
-rw-r--r--mm/memcontrol.c2
-rw-r--r--net/9p/trans_fd.c18
-rw-r--r--virt/kvm/eventfd.c2
9 files changed, 32 insertions, 38 deletions
diff --git a/drivers/staging/comedi/drivers/serial2002.c b/drivers/staging/comedi/drivers/serial2002.c
index b3f3b4a201af..5471b2212a62 100644
--- a/drivers/staging/comedi/drivers/serial2002.c
+++ b/drivers/staging/comedi/drivers/serial2002.c
@@ -113,7 +113,7 @@ static void serial2002_tty_read_poll_wait(struct file *f, int timeout)
113 long elapsed; 113 long elapsed;
114 __poll_t mask; 114 __poll_t mask;
115 115
116 mask = f->f_op->poll(f, &table.pt); 116 mask = vfs_poll(f, &table.pt);
117 if (mask & (EPOLLRDNORM | EPOLLRDBAND | EPOLLIN | 117 if (mask & (EPOLLRDNORM | EPOLLRDBAND | EPOLLIN |
118 EPOLLHUP | EPOLLERR)) { 118 EPOLLHUP | EPOLLERR)) {
119 break; 119 break;
@@ -136,7 +136,7 @@ static int serial2002_tty_read(struct file *f, int timeout)
136 136
137 result = -1; 137 result = -1;
138 if (!IS_ERR(f)) { 138 if (!IS_ERR(f)) {
139 if (f->f_op->poll) { 139 if (file_can_poll(f)) {
140 serial2002_tty_read_poll_wait(f, timeout); 140 serial2002_tty_read_poll_wait(f, timeout);
141 141
142 if (kernel_read(f, &ch, 1, &pos) == 1) 142 if (kernel_read(f, &ch, 1, &pos) == 1)
diff --git a/drivers/vfio/virqfd.c b/drivers/vfio/virqfd.c
index 085700f1be10..2a1be859ee71 100644
--- a/drivers/vfio/virqfd.c
+++ b/drivers/vfio/virqfd.c
@@ -166,7 +166,7 @@ int vfio_virqfd_enable(void *opaque,
166 init_waitqueue_func_entry(&virqfd->wait, virqfd_wakeup); 166 init_waitqueue_func_entry(&virqfd->wait, virqfd_wakeup);
167 init_poll_funcptr(&virqfd->pt, virqfd_ptable_queue_proc); 167 init_poll_funcptr(&virqfd->pt, virqfd_ptable_queue_proc);
168 168
169 events = irqfd.file->f_op->poll(irqfd.file, &virqfd->pt); 169 events = vfs_poll(irqfd.file, &virqfd->pt);
170 170
171 /* 171 /*
172 * Check if there was an event already pending on the eventfd 172 * Check if there was an event already pending on the eventfd
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index f3bd8e941224..f6022881f147 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -208,7 +208,7 @@ int vhost_poll_start(struct vhost_poll *poll, struct file *file)
208 if (poll->wqh) 208 if (poll->wqh)
209 return 0; 209 return 0;
210 210
211 mask = file->f_op->poll(file, &poll->table); 211 mask = vfs_poll(file, &poll->table);
212 if (mask) 212 if (mask)
213 vhost_poll_wakeup(&poll->wait, 0, 0, poll_to_key(mask)); 213 vhost_poll_wakeup(&poll->wait, 0, 0, poll_to_key(mask));
214 if (mask & EPOLLERR) { 214 if (mask & EPOLLERR) {
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 602ca4285b2e..67db22fe99c5 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -884,8 +884,7 @@ static __poll_t ep_item_poll(const struct epitem *epi, poll_table *pt,
884 884
885 pt->_key = epi->event.events; 885 pt->_key = epi->event.events;
886 if (!is_file_epoll(epi->ffd.file)) 886 if (!is_file_epoll(epi->ffd.file))
887 return epi->ffd.file->f_op->poll(epi->ffd.file, pt) & 887 return vfs_poll(epi->ffd.file, pt) & epi->event.events;
888 epi->event.events;
889 888
890 ep = epi->ffd.file->private_data; 889 ep = epi->ffd.file->private_data;
891 poll_wait(epi->ffd.file, &ep->poll_wait, pt); 890 poll_wait(epi->ffd.file, &ep->poll_wait, pt);
@@ -2025,7 +2024,7 @@ SYSCALL_DEFINE4(epoll_ctl, int, epfd, int, op, int, fd,
2025 2024
2026 /* The target file descriptor must support poll */ 2025 /* The target file descriptor must support poll */
2027 error = -EPERM; 2026 error = -EPERM;
2028 if (!tf.file->f_op->poll) 2027 if (!file_can_poll(tf.file))
2029 goto error_tgt_fput; 2028 goto error_tgt_fput;
2030 2029
2031 /* Check if EPOLLWAKEUP is allowed */ 2030 /* Check if EPOLLWAKEUP is allowed */
diff --git a/fs/select.c b/fs/select.c
index 25da26253485..e30def680b2e 100644
--- a/fs/select.c
+++ b/fs/select.c
@@ -502,14 +502,10 @@ static int do_select(int n, fd_set_bits *fds, struct timespec64 *end_time)
502 continue; 502 continue;
503 f = fdget(i); 503 f = fdget(i);
504 if (f.file) { 504 if (f.file) {
505 const struct file_operations *f_op; 505 wait_key_set(wait, in, out, bit,
506 f_op = f.file->f_op; 506 busy_flag);
507 mask = DEFAULT_POLLMASK; 507 mask = vfs_poll(f.file, wait);
508 if (f_op->poll) { 508
509 wait_key_set(wait, in, out,
510 bit, busy_flag);
511 mask = (*f_op->poll)(f.file, wait);
512 }
513 fdput(f); 509 fdput(f);
514 if ((mask & POLLIN_SET) && (in & bit)) { 510 if ((mask & POLLIN_SET) && (in & bit)) {
515 res_in |= bit; 511 res_in |= bit;
@@ -825,13 +821,10 @@ static inline __poll_t do_pollfd(struct pollfd *pollfd, poll_table *pwait,
825 821
826 /* userland u16 ->events contains POLL... bitmap */ 822 /* userland u16 ->events contains POLL... bitmap */
827 filter = demangle_poll(pollfd->events) | EPOLLERR | EPOLLHUP; 823 filter = demangle_poll(pollfd->events) | EPOLLERR | EPOLLHUP;
828 mask = DEFAULT_POLLMASK; 824 pwait->_key = filter | busy_flag;
829 if (f.file->f_op->poll) { 825 mask = vfs_poll(f.file, pwait);
830 pwait->_key = filter | busy_flag; 826 if (mask & busy_flag)
831 mask = f.file->f_op->poll(f.file, pwait); 827 *can_busy_poll = true;
832 if (mask & busy_flag)
833 *can_busy_poll = true;
834 }
835 mask &= filter; /* Mask out unneeded events. */ 828 mask &= filter; /* Mask out unneeded events. */
836 fdput(f); 829 fdput(f);
837 830
diff --git a/include/linux/poll.h b/include/linux/poll.h
index a3576da63377..7e0fdcf905d2 100644
--- a/include/linux/poll.h
+++ b/include/linux/poll.h
@@ -74,6 +74,18 @@ static inline void init_poll_funcptr(poll_table *pt, poll_queue_proc qproc)
74 pt->_key = ~(__poll_t)0; /* all events enabled */ 74 pt->_key = ~(__poll_t)0; /* all events enabled */
75} 75}
76 76
77static inline bool file_can_poll(struct file *file)
78{
79 return file->f_op->poll;
80}
81
82static inline __poll_t vfs_poll(struct file *file, struct poll_table_struct *pt)
83{
84 if (unlikely(!file->f_op->poll))
85 return DEFAULT_POLLMASK;
86 return file->f_op->poll(file, pt);
87}
88
77struct poll_table_entry { 89struct poll_table_entry {
78 struct file *filp; 90 struct file *filp;
79 __poll_t key; 91 __poll_t key;
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index 2bd3df3d101a..1695f38630f1 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -3849,7 +3849,7 @@ static ssize_t memcg_write_event_control(struct kernfs_open_file *of,
3849 if (ret) 3849 if (ret)
3850 goto out_put_css; 3850 goto out_put_css;
3851 3851
3852 efile.file->f_op->poll(efile.file, &event->pt); 3852 vfs_poll(efile.file, &event->pt);
3853 3853
3854 spin_lock(&memcg->event_list_lock); 3854 spin_lock(&memcg->event_list_lock);
3855 list_add(&event->list, &memcg->event_list); 3855 list_add(&event->list, &memcg->event_list);
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c
index 0cfba919d167..3811775692d0 100644
--- a/net/9p/trans_fd.c
+++ b/net/9p/trans_fd.c
@@ -231,7 +231,7 @@ static void p9_conn_cancel(struct p9_conn *m, int err)
231static __poll_t 231static __poll_t
232p9_fd_poll(struct p9_client *client, struct poll_table_struct *pt, int *err) 232p9_fd_poll(struct p9_client *client, struct poll_table_struct *pt, int *err)
233{ 233{
234 __poll_t ret, n; 234 __poll_t ret;
235 struct p9_trans_fd *ts = NULL; 235 struct p9_trans_fd *ts = NULL;
236 236
237 if (client && client->status == Connected) 237 if (client && client->status == Connected)
@@ -243,19 +243,9 @@ p9_fd_poll(struct p9_client *client, struct poll_table_struct *pt, int *err)
243 return EPOLLERR; 243 return EPOLLERR;
244 } 244 }
245 245
246 if (!ts->rd->f_op->poll) 246 ret = vfs_poll(ts->rd, pt);
247 ret = DEFAULT_POLLMASK; 247 if (ts->rd != ts->wr)
248 else 248 ret = (ret & ~EPOLLOUT) | (vfs_poll(ts->wr, pt) & ~EPOLLIN);
249 ret = ts->rd->f_op->poll(ts->rd, pt);
250
251 if (ts->rd != ts->wr) {
252 if (!ts->wr->f_op->poll)
253 n = DEFAULT_POLLMASK;
254 else
255 n = ts->wr->f_op->poll(ts->wr, pt);
256 ret = (ret & ~EPOLLOUT) | (n & ~EPOLLIN);
257 }
258
259 return ret; 249 return ret;
260} 250}
261 251
diff --git a/virt/kvm/eventfd.c b/virt/kvm/eventfd.c
index 6e865e8b5b10..90d30fbe95ae 100644
--- a/virt/kvm/eventfd.c
+++ b/virt/kvm/eventfd.c
@@ -397,7 +397,7 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
397 * Check if there was an event already pending on the eventfd 397 * Check if there was an event already pending on the eventfd
398 * before we registered, and trigger it as if we didn't miss it. 398 * before we registered, and trigger it as if we didn't miss it.
399 */ 399 */
400 events = f.file->f_op->poll(f.file, &irqfd->pt); 400 events = vfs_poll(f.file, &irqfd->pt);
401 401
402 if (events & EPOLLIN) 402 if (events & EPOLLIN)
403 schedule_work(&irqfd->inject); 403 schedule_work(&irqfd->inject);