->get_poll_head returns the waitqueue that the poll operation is going to sleep on. Note that this means we can only use a single waitqueue for the poll, unlike some current drivers that use two waitqueues for different events. But now that we have keyed wakeups and heavily use those for poll there aren't that many good reason left to keep the multiple waitqueues, and if there are any ->poll is still around, the driver just won't support aio poll. ->poll_mask is called after the wakeup to return the actual mask of events reported by poll. It can be called with the waitqueue lock held in some cases. Signed-off-by: Christoph Hellwig <hch@xxxxxx> --- Documentation/filesystems/Locking | 7 ++++++- Documentation/filesystems/vfs.txt | 11 +++++++++++ include/linux/fs.h | 2 ++ include/linux/poll.h | 16 ++++++++++++++-- 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 220bba28f72b..6d227f9d7bd9 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -440,6 +440,8 @@ prototypes: ssize_t (*write_iter) (struct kiocb *, struct iov_iter *); int (*iterate) (struct file *, struct dir_context *); __poll_t (*poll) (struct file *, struct poll_table_struct *); + struct wait_queue_head * (*get_poll_head)(struct file *, __poll_t); + __poll_t (*poll_mask) (struct file *, __poll_t); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); long (*compat_ioctl) (struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); @@ -470,7 +472,7 @@ prototypes: }; locking rules: - All may block. + All except for ->poll_mask may block. ->llseek() locking has moved from llseek to the individual llseek implementations. If your fs is not using generic_file_llseek, you @@ -498,6 +500,9 @@ in sys_read() and friends. the lease within the individual filesystem to record the result of the operation +->poll_mask can be called with or without the waitqueue lock for the waitqueue +returned from ->get_poll_head. + --------------------------- dquot_operations ------------------------------- prototypes: int (*write_dquot) (struct dquot *); diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index f608180ad59d..bafb5c749443 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -857,6 +857,8 @@ struct file_operations { ssize_t (*write_iter) (struct kiocb *, struct iov_iter *); int (*iterate) (struct file *, struct dir_context *); __poll_t (*poll) (struct file *, struct poll_table_struct *); + struct wait_queue_head * (*get_poll_head)(struct file *, __poll_t); + __poll_t (*poll_mask) (struct file *, __poll_t); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); long (*compat_ioctl) (struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); @@ -901,6 +903,15 @@ otherwise noted. activity on this file and (optionally) go to sleep until there is activity. Called by the select(2) and poll(2) system calls + get_poll_head: Returns the struct wait_queue_head that poll, select, + epoll or aio poll should wait on in case this instance only has single + waitqueue. + + poll_mask: return the mask of POLL* values describing the file descriptor + state. Called before going to sleep on the waitqueue returned by + get_poll_head, and after it has been woken. If ->get_poll_head and + ->poll_mask are implemented ->poll does not need to be implement. + unlocked_ioctl: called by the ioctl(2) system call. compat_ioctl: called by the ioctl(2) system call when 32 bit system calls diff --git a/include/linux/fs.h b/include/linux/fs.h index 34c0434511c7..f7dd8eb1eb85 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1699,6 +1699,8 @@ struct file_operations { int (*iterate) (struct file *, struct dir_context *); int (*iterate_shared) (struct file *, struct dir_context *); __poll_t (*poll) (struct file *, struct poll_table_struct *); + struct wait_queue_head * (*get_poll_head)(struct file *, __poll_t); + __poll_t (*poll_mask) (struct file *, __poll_t); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); long (*compat_ioctl) (struct file *, unsigned int, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); diff --git a/include/linux/poll.h b/include/linux/poll.h index 6e4b2ddd4e82..90b1a282f626 100644 --- a/include/linux/poll.h +++ b/include/linux/poll.h @@ -75,12 +75,24 @@ static inline void init_poll_funcptr(poll_table *pt, poll_queue_proc qproc) static inline bool file_can_poll(struct file *file) { - return file->f_op->poll; + return file->f_op->poll || + (file->f_op->get_poll_head && file->f_op->poll_mask); } static inline __poll_t vfs_poll(struct file *file, struct poll_table_struct *pt) { - return file->f_op->poll(file, pt); + unsigned int events = poll_requested_events(pt); + + if (file->f_op->poll) + return file->f_op->poll(file, pt); + + poll_wait(file, file->f_op->get_poll_head(file, events), pt); + return file->f_op->poll_mask(file, events); +} + +static inline __poll_t vfs_poll_mask(struct file *file, __poll_t events) +{ + return file->f_op->poll_mask(file, events) & events; } struct poll_table_entry { -- 2.14.2