}
static void virqfd_ptable_queue_proc(struct file *file,
- wait_queue_head_t *wqh, poll_table *pt)
+ wait_queue_head_t *wqh, poll_table *pt,
+ unsigned long unused)
{
struct virqfd *virqfd = container_of(pt, struct virqfd, pt);
add_wait_queue(wqh, &virqfd->wait);
#define vhost_avail_event(vq) ((__virtio16 __user *)&vq->used->ring[vq->num])
static void vhost_poll_func(struct file *file, wait_queue_head_t *wqh,
- poll_table *pt)
+ poll_table *pt, unsigned long unused)
{
struct vhost_poll *poll;
/* Number of active wait queue attached to poll operations */
int nwait;
+ /* fd always raises this fixed event. */
+ unsigned long fixed_event;
+
/* List containing poll wait queues */
struct list_head pwqlist;
}
static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
- poll_table *pt);
+ poll_table *pt, unsigned long fixed_event);
struct readyevents_arg {
struct eventpoll *ep;
struct epitem *epi = ep_item_from_wait(wait);
struct eventpoll *ep = epi->ep;
+ /*
+ * If this fd type has a hardwired event which should override the key
+ * (e.g. if it is waiting on a non-file waitqueue), jam it in here.
+ */
+ if (epi->fixed_event)
+ key = (void *)epi->fixed_event;
+
if ((unsigned long)key & POLLFREE) {
ep_pwq_from_wait(wait)->whead = NULL;
/*
* target file wakeup lists.
*/
static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead,
- poll_table *pt)
+ poll_table *pt, unsigned long fixed_event)
{
struct epitem *epi = ep_item_from_epqueue(pt);
struct eppoll_entry *pwq;
+ if (fixed_event & !(epi->event.events & fixed_event))
+ return;
+
+ if (fixed_event)
+ epi->fixed_event = fixed_event;
+
if (epi->nwait >= 0 && (pwq = kmem_cache_alloc(pwq_cache, GFP_KERNEL))) {
init_waitqueue_func_entry(&pwq->wait, ep_poll_callback);
pwq->whead = whead;
ep_set_ffd(&epi->ffd, tfile, fd);
epi->event = *event;
epi->nwait = 0;
+ epi->fixed_event = 0;
epi->next = EP_UNACTIVE_PTR;
if (epi->event.events & EPOLLWAKEUP) {
error = ep_create_wakeup_source(epi);
* poll table.
*/
static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
- poll_table *p);
+ poll_table *p, unsigned long fixed_event);
void poll_initwait(struct poll_wqueues *pwq)
{
struct poll_table_entry *entry;
entry = container_of(wait, struct poll_table_entry, wait);
+
+ /*
+ * If this fd type has a hardwired key which should override the key
+ * (e.g. if it is waiting on a non-file waitqueue), jam it in here.
+ */
+ if (entry->fixed_key)
+ key = (void *)entry->fixed_key;
+
if (key && !((unsigned long)key & entry->key))
return 0;
+
return __pollwake(wait, mode, sync, key);
}
/* Add a new entry */
static void __pollwait(struct file *filp, wait_queue_head_t *wait_address,
- poll_table *p)
+ poll_table *p, unsigned long fixed_event)
{
struct poll_wqueues *pwq = container_of(p, struct poll_wqueues, pt);
- struct poll_table_entry *entry = poll_get_entry(pwq);
+ struct poll_table_entry *entry;
+
+ if (fixed_event && !(p->_key & fixed_event))
+ return;
+
+ entry = poll_get_entry(pwq);
if (!entry)
return;
+
entry->filp = get_file(filp);
entry->wait_address = wait_address;
- entry->key = p->_key;
+ entry->key = p->_key;
+ entry->fixed_key = fixed_event;
init_waitqueue_func_entry(&entry->wait, pollwake);
entry->wait.private = pwq;
add_wait_queue(wait_address, &entry->wait);
struct waitfd_ctx *ctx = file->private_data;
long value;
- printk(KERN_INFO "DEBUG: %i: about to sleep on waitqueue at %p\n", current->pid, ¤t->signal->wait_chldexit);
- poll_wait(file, ¤t->signal->wait_chldexit, wait);
- printk(KERN_INFO "DEBUG: waitfd poll woken up and checking pid %i, options are %i\n", ctx->upid, ctx->options);
+ poll_wait_fixed(file, ¤t->signal->wait_chldexit, wait,
+ POLLIN);
value = do_waitid(ctx->which, ctx->upid, NULL,
ctx->options | WNOHANG | WNOWAIT, NULL);
if (value > 0 || value == -ECHILD)
return POLLIN | POLLRDNORM;
- printk(KERN_INFO "DEBUG: waitfd poll returning zilch\n");
-
return 0;
}
/*
* structures and helpers for f_op->poll implementations
*/
-typedef void (*poll_queue_proc)(struct file *, wait_queue_head_t *, struct poll_table_struct *);
+typedef void (*poll_queue_proc)(struct file *, wait_queue_head_t *, struct poll_table_struct *,
+ unsigned long fixed_event);
/*
* Do not touch the structure directly, use the access functions
static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
{
if (p && p->_qproc && wait_address)
- p->_qproc(filp, wait_address, p);
+ p->_qproc(filp, wait_address, p, 0);
+}
+
+static inline void poll_wait_fixed(struct file * filp, wait_queue_head_t * wait_address, poll_table *p,
+ unsigned long fixed_event)
+{
+ if (p && p->_qproc && wait_address)
+ p->_qproc(filp, wait_address, p, fixed_event);
}
/*
struct poll_table_entry {
struct file *filp;
unsigned long key;
+ unsigned long fixed_key;
wait_queue_t wait;
wait_queue_head_t *wait_address;
};
*/
static void
-p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p)
+p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p,
+ unsigned long unused)
{
struct p9_conn *m = container_of(p, struct p9_conn, pt);
struct p9_poll_wait *pwait = NULL;
static void
irqfd_ptable_queue_proc(struct file *file, wait_queue_head_t *wqh,
- poll_table *pt)
+ poll_table *pt, unsigned long unused)
{
struct _irqfd *irqfd = container_of(pt, struct _irqfd, pt);
add_wait_queue(wqh, &irqfd->wait);