fs: introduce new ->get_poll_head and ->poll_mask methods
->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. 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>
This commit is contained in:
parent
9965ed174e
commit
3deb642f0d
|
@ -440,6 +440,8 @@ prototypes:
|
||||||
ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
|
ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
|
||||||
int (*iterate) (struct file *, struct dir_context *);
|
int (*iterate) (struct file *, struct dir_context *);
|
||||||
__poll_t (*poll) (struct file *, struct poll_table_struct *);
|
__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 (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
|
||||||
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
|
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
|
||||||
int (*mmap) (struct file *, struct vm_area_struct *);
|
int (*mmap) (struct file *, struct vm_area_struct *);
|
||||||
|
@ -470,7 +472,7 @@ prototypes:
|
||||||
};
|
};
|
||||||
|
|
||||||
locking rules:
|
locking rules:
|
||||||
All may block.
|
All except for ->poll_mask may block.
|
||||||
|
|
||||||
->llseek() locking has moved from llseek to the individual llseek
|
->llseek() locking has moved from llseek to the individual llseek
|
||||||
implementations. If your fs is not using generic_file_llseek, you
|
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
|
the lease within the individual filesystem to record the result of the
|
||||||
operation
|
operation
|
||||||
|
|
||||||
|
->poll_mask can be called with or without the waitqueue lock for the waitqueue
|
||||||
|
returned from ->get_poll_head.
|
||||||
|
|
||||||
--------------------------- dquot_operations -------------------------------
|
--------------------------- dquot_operations -------------------------------
|
||||||
prototypes:
|
prototypes:
|
||||||
int (*write_dquot) (struct dquot *);
|
int (*write_dquot) (struct dquot *);
|
||||||
|
|
|
@ -857,6 +857,8 @@ struct file_operations {
|
||||||
ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
|
ssize_t (*write_iter) (struct kiocb *, struct iov_iter *);
|
||||||
int (*iterate) (struct file *, struct dir_context *);
|
int (*iterate) (struct file *, struct dir_context *);
|
||||||
__poll_t (*poll) (struct file *, struct poll_table_struct *);
|
__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 (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
|
||||||
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
|
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
|
||||||
int (*mmap) (struct file *, struct vm_area_struct *);
|
int (*mmap) (struct file *, struct vm_area_struct *);
|
||||||
|
@ -901,6 +903,17 @@ otherwise noted.
|
||||||
activity on this file and (optionally) go to sleep until there
|
activity on this file and (optionally) go to sleep until there
|
||||||
is activity. Called by the select(2) and poll(2) system calls
|
is activity. Called by the select(2) and poll(2) system calls
|
||||||
|
|
||||||
|
get_poll_head: Returns the struct wait_queue_head that callers can
|
||||||
|
wait on. Callers need to check the returned events using ->poll_mask
|
||||||
|
once woken. Can return NULL to indicate polling is not supported,
|
||||||
|
or any error code using the ERR_PTR convention to indicate that a
|
||||||
|
grave error occured and ->poll_mask shall not be called.
|
||||||
|
|
||||||
|
poll_mask: return the mask of EPOLL* values describing the file descriptor
|
||||||
|
state. Called either before going to sleep on the waitqueue returned by
|
||||||
|
get_poll_head, or 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.
|
unlocked_ioctl: called by the ioctl(2) system call.
|
||||||
|
|
||||||
compat_ioctl: called by the ioctl(2) system call when 32 bit system calls
|
compat_ioctl: called by the ioctl(2) system call when 32 bit system calls
|
||||||
|
|
23
fs/select.c
23
fs/select.c
|
@ -34,6 +34,29 @@
|
||||||
|
|
||||||
#include <linux/uaccess.h>
|
#include <linux/uaccess.h>
|
||||||
|
|
||||||
|
__poll_t vfs_poll(struct file *file, struct poll_table_struct *pt)
|
||||||
|
{
|
||||||
|
if (file->f_op->poll) {
|
||||||
|
return file->f_op->poll(file, pt);
|
||||||
|
} else if (file_has_poll_mask(file)) {
|
||||||
|
unsigned int events = poll_requested_events(pt);
|
||||||
|
struct wait_queue_head *head;
|
||||||
|
|
||||||
|
if (pt && pt->_qproc) {
|
||||||
|
head = file->f_op->get_poll_head(file, events);
|
||||||
|
if (!head)
|
||||||
|
return DEFAULT_POLLMASK;
|
||||||
|
if (IS_ERR(head))
|
||||||
|
return EPOLLERR;
|
||||||
|
pt->_qproc(file, head, pt);
|
||||||
|
}
|
||||||
|
|
||||||
|
return file->f_op->poll_mask(file, events);
|
||||||
|
} else {
|
||||||
|
return DEFAULT_POLLMASK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(vfs_poll);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Estimate expected accuracy in ns from a timeval.
|
* Estimate expected accuracy in ns from a timeval.
|
||||||
|
|
|
@ -1711,6 +1711,8 @@ struct file_operations {
|
||||||
int (*iterate) (struct file *, struct dir_context *);
|
int (*iterate) (struct file *, struct dir_context *);
|
||||||
int (*iterate_shared) (struct file *, struct dir_context *);
|
int (*iterate_shared) (struct file *, struct dir_context *);
|
||||||
__poll_t (*poll) (struct file *, struct poll_table_struct *);
|
__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 (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
|
||||||
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
|
long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
|
||||||
int (*mmap) (struct file *, struct vm_area_struct *);
|
int (*mmap) (struct file *, struct vm_area_struct *);
|
||||||
|
|
|
@ -74,18 +74,18 @@ static inline void init_poll_funcptr(poll_table *pt, poll_queue_proc qproc)
|
||||||
pt->_key = ~(__poll_t)0; /* all events enabled */
|
pt->_key = ~(__poll_t)0; /* all events enabled */
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool file_can_poll(struct file *file)
|
static inline bool file_has_poll_mask(struct file *file)
|
||||||
{
|
{
|
||||||
return file->f_op->poll;
|
return 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)
|
static inline bool file_can_poll(struct file *file)
|
||||||
{
|
{
|
||||||
if (unlikely(!file->f_op->poll))
|
return file->f_op->poll || file_has_poll_mask(file);
|
||||||
return DEFAULT_POLLMASK;
|
|
||||||
return file->f_op->poll(file, pt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__poll_t vfs_poll(struct file *file, struct poll_table_struct *pt);
|
||||||
|
|
||||||
struct poll_table_entry {
|
struct poll_table_entry {
|
||||||
struct file *filp;
|
struct file *filp;
|
||||||
__poll_t key;
|
__poll_t key;
|
||||||
|
|
Loading…
Reference in New Issue