Commit d9bfacba authored by Davide Libenzi's avatar Davide Libenzi Committed by Andy Grover

[PATCH] remove code duplication from fs/eventpoll.c

Clean up poll queue handling, avoid doing any wait-queue operations
when we only want to get the current state.
parent a3a67b1f
...@@ -107,6 +107,8 @@ ...@@ -107,6 +107,8 @@
/* Get the "struct epitem" from a wait queue pointer */ /* Get the "struct epitem" from a wait queue pointer */
#define EP_ITEM_FROM_WAIT(p) ((struct epitem *) container_of(p, struct eppoll_entry, wait)->base) #define EP_ITEM_FROM_WAIT(p) ((struct epitem *) container_of(p, struct eppoll_entry, wait)->base)
/* Get the "struct epitem" from an epoll queue wrapper */
#define EP_ITEM_FROM_EPQUEUE(p) (container_of(p, struct ep_pqueue, pt)->dpi)
...@@ -187,6 +189,12 @@ struct epitem { ...@@ -187,6 +189,12 @@ struct epitem {
atomic_t usecnt; atomic_t usecnt;
}; };
/* Wrapper struct used by poll queueing */
struct ep_pqueue {
poll_table pt;
struct epitem *dpi;
};
static unsigned int ep_get_hash_bits(unsigned int hintsize); static unsigned int ep_get_hash_bits(unsigned int hintsize);
...@@ -201,7 +209,7 @@ static void ep_free(struct eventpoll *ep); ...@@ -201,7 +209,7 @@ static void ep_free(struct eventpoll *ep);
static struct epitem *ep_find(struct eventpoll *ep, struct file *file); static struct epitem *ep_find(struct eventpoll *ep, struct file *file);
static void ep_use_epitem(struct epitem *dpi); static void ep_use_epitem(struct epitem *dpi);
static void ep_release_epitem(struct epitem *dpi); static void ep_release_epitem(struct epitem *dpi);
static void ep_ptable_queue_proc(void *priv, wait_queue_head_t *whead); static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead, poll_table *pt);
static int ep_insert(struct eventpoll *ep, struct pollfd *pfd, struct file *tfile); static int ep_insert(struct eventpoll *ep, struct pollfd *pfd, struct file *tfile);
static int ep_modify(struct eventpoll *ep, struct epitem *dpi, unsigned int events); static int ep_modify(struct eventpoll *ep, struct epitem *dpi, unsigned int events);
static int ep_unlink(struct eventpoll *ep, struct epitem *dpi); static int ep_unlink(struct eventpoll *ep, struct epitem *dpi);
...@@ -791,9 +799,9 @@ static void ep_release_epitem(struct epitem *dpi) ...@@ -791,9 +799,9 @@ static void ep_release_epitem(struct epitem *dpi)
* This is the callback that is used to add our wait queue to the * This is the callback that is used to add our wait queue to the
* target file wakeup lists. * target file wakeup lists.
*/ */
static void ep_ptable_queue_proc(void *priv, wait_queue_head_t *whead) static void ep_ptable_queue_proc(struct file *file, wait_queue_head_t *whead, poll_table *pt)
{ {
struct epitem *dpi = priv; struct epitem *dpi = EP_ITEM_FROM_EPQUEUE(pt);
/* No more than EP_MAX_POLL_QUEUE wait queue are supported */ /* No more than EP_MAX_POLL_QUEUE wait queue are supported */
if (dpi->nwait < EP_MAX_POLL_QUEUE) { if (dpi->nwait < EP_MAX_POLL_QUEUE) {
...@@ -809,7 +817,7 @@ static int ep_insert(struct eventpoll *ep, struct pollfd *pfd, struct file *tfil ...@@ -809,7 +817,7 @@ static int ep_insert(struct eventpoll *ep, struct pollfd *pfd, struct file *tfil
int error, i, revents; int error, i, revents;
unsigned long flags; unsigned long flags;
struct epitem *dpi; struct epitem *dpi;
poll_table pt; struct ep_pqueue epq;
error = -ENOMEM; error = -ENOMEM;
if (!(dpi = DPI_MEM_ALLOC())) if (!(dpi = DPI_MEM_ALLOC()))
...@@ -830,7 +838,8 @@ static int ep_insert(struct eventpoll *ep, struct pollfd *pfd, struct file *tfil ...@@ -830,7 +838,8 @@ static int ep_insert(struct eventpoll *ep, struct pollfd *pfd, struct file *tfil
} }
/* Initialize the poll table using the queue callback */ /* Initialize the poll table using the queue callback */
poll_initwait_ex(&pt, 1, ep_ptable_queue_proc, dpi); epq.dpi = dpi;
poll_initwait_ex(&epq.pt, ep_ptable_queue_proc);
/* We have to drop the new item inside our item list to keep track of it */ /* We have to drop the new item inside our item list to keep track of it */
write_lock_irqsave(&ep->lock, flags); write_lock_irqsave(&ep->lock, flags);
...@@ -839,7 +848,7 @@ static int ep_insert(struct eventpoll *ep, struct pollfd *pfd, struct file *tfil ...@@ -839,7 +848,7 @@ static int ep_insert(struct eventpoll *ep, struct pollfd *pfd, struct file *tfil
list_add(&dpi->llink, ep_hash_entry(ep, ep_hash_index(ep, tfile))); list_add(&dpi->llink, ep_hash_entry(ep, ep_hash_index(ep, tfile)));
/* Attach the item to the poll hooks and get current event bits */ /* Attach the item to the poll hooks and get current event bits */
revents = tfile->f_op->poll(tfile, &pt); revents = tfile->f_op->poll(tfile, &epq.pt);
/* If the file is already "ready" we drop it inside the ready list */ /* If the file is already "ready" we drop it inside the ready list */
if ((revents & pfd->events) && !EP_IS_LINKED(&dpi->rdllink)) { if ((revents & pfd->events) && !EP_IS_LINKED(&dpi->rdllink)) {
...@@ -854,7 +863,7 @@ static int ep_insert(struct eventpoll *ep, struct pollfd *pfd, struct file *tfil ...@@ -854,7 +863,7 @@ static int ep_insert(struct eventpoll *ep, struct pollfd *pfd, struct file *tfil
write_unlock_irqrestore(&ep->lock, flags); write_unlock_irqrestore(&ep->lock, flags);
poll_freewait(&pt); poll_freewait(&epq.pt);
DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_insert(%p, %d)\n", DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_insert(%p, %d)\n",
current, ep, pfd->fd)); current, ep, pfd->fd));
...@@ -874,20 +883,11 @@ static int ep_modify(struct eventpoll *ep, struct epitem *dpi, unsigned int even ...@@ -874,20 +883,11 @@ static int ep_modify(struct eventpoll *ep, struct epitem *dpi, unsigned int even
{ {
unsigned int revents; unsigned int revents;
unsigned long flags; unsigned long flags;
poll_table pt;
/*
* This is a special poll table initialization that will
* make poll_wait() to not perform any wait queue insertion when
* called by file->f_op->poll(). This is a fast way to retrieve
* file events with perform any queue insertion, hence saving CPU cycles.
*/
poll_initwait_ex(&pt, 0, NULL, NULL);
write_lock_irqsave(&ep->lock, flags); write_lock_irqsave(&ep->lock, flags);
/* Get current event bits */ /* Get current event bits */
revents = dpi->file->f_op->poll(dpi->file, &pt); revents = dpi->file->f_op->poll(dpi->file, NULL);
/* Set the new event interest mask */ /* Set the new event interest mask */
dpi->pfd.events = events; dpi->pfd.events = events;
...@@ -906,8 +906,6 @@ static int ep_modify(struct eventpoll *ep, struct epitem *dpi, unsigned int even ...@@ -906,8 +906,6 @@ static int ep_modify(struct eventpoll *ep, struct epitem *dpi, unsigned int even
write_unlock_irqrestore(&ep->lock, flags); write_unlock_irqrestore(&ep->lock, flags);
poll_freewait(&pt);
return 0; return 0;
} }
...@@ -1066,15 +1064,6 @@ static int ep_events_transfer(struct eventpoll *ep, struct pollfd *events, int m ...@@ -1066,15 +1064,6 @@ static int ep_events_transfer(struct eventpoll *ep, struct pollfd *events, int m
unsigned long flags; unsigned long flags;
struct list_head *lsthead = &ep->rdllist; struct list_head *lsthead = &ep->rdllist;
struct pollfd eventbuf[EP_EVENT_BUFF_SIZE]; struct pollfd eventbuf[EP_EVENT_BUFF_SIZE];
poll_table pt;
/*
* This is a special poll table initialization that will
* make poll_wait() to not perform any wait queue insertion when
* called by file->f_op->poll(). This is a fast way to retrieve
* file events with perform any queue insertion, hence saving CPU cycles.
*/
poll_initwait_ex(&pt, 0, NULL, NULL);
write_lock_irqsave(&ep->lock, flags); write_lock_irqsave(&ep->lock, flags);
...@@ -1093,7 +1082,7 @@ static int ep_events_transfer(struct eventpoll *ep, struct pollfd *events, int m ...@@ -1093,7 +1082,7 @@ static int ep_events_transfer(struct eventpoll *ep, struct pollfd *events, int m
continue; continue;
/* Fetch event bits from the signaled file */ /* Fetch event bits from the signaled file */
revents = dpi->file->f_op->poll(dpi->file, &pt); revents = dpi->file->f_op->poll(dpi->file, NULL);
if (revents & dpi->pfd.events) { if (revents & dpi->pfd.events) {
eventbuf[ebufcnt] = dpi->pfd; eventbuf[ebufcnt] = dpi->pfd;
...@@ -1108,10 +1097,8 @@ static int ep_events_transfer(struct eventpoll *ep, struct pollfd *events, int m ...@@ -1108,10 +1097,8 @@ static int ep_events_transfer(struct eventpoll *ep, struct pollfd *events, int m
*/ */
write_unlock_irqrestore(&ep->lock, flags); write_unlock_irqrestore(&ep->lock, flags);
if (__copy_to_user(&events[eventcnt], eventbuf, if (__copy_to_user(&events[eventcnt], eventbuf,
ebufcnt * sizeof(struct pollfd))) { ebufcnt * sizeof(struct pollfd)))
poll_freewait(&pt);
return -EFAULT; return -EFAULT;
}
eventcnt += ebufcnt; eventcnt += ebufcnt;
ebufcnt = 0; ebufcnt = 0;
write_lock_irqsave(&ep->lock, flags); write_lock_irqsave(&ep->lock, flags);
...@@ -1129,8 +1116,6 @@ static int ep_events_transfer(struct eventpoll *ep, struct pollfd *events, int m ...@@ -1129,8 +1116,6 @@ static int ep_events_transfer(struct eventpoll *ep, struct pollfd *events, int m
eventcnt += ebufcnt; eventcnt += ebufcnt;
} }
poll_freewait(&pt);
return eventcnt; return eventcnt;
} }
......
...@@ -77,14 +77,6 @@ void __pollwait(struct file * filp, wait_queue_head_t * wait_address, poll_table ...@@ -77,14 +77,6 @@ void __pollwait(struct file * filp, wait_queue_head_t * wait_address, poll_table
{ {
struct poll_table_page *table = p->table; struct poll_table_page *table = p->table;
if (!p->queue)
return;
if (p->qproc) {
p->qproc(p->priv, wait_address);
return;
}
if (!table || POLL_TABLE_FULL(table)) { if (!table || POLL_TABLE_FULL(table)) {
struct poll_table_page *new_table; struct poll_table_page *new_table;
...@@ -112,6 +104,7 @@ void __pollwait(struct file * filp, wait_queue_head_t * wait_address, poll_table ...@@ -112,6 +104,7 @@ void __pollwait(struct file * filp, wait_queue_head_t * wait_address, poll_table
} }
} }
#define __IN(fds, n) (fds->in + n) #define __IN(fds, n) (fds->in + n)
#define __OUT(fds, n) (fds->out + n) #define __OUT(fds, n) (fds->out + n)
#define __EX(fds, n) (fds->ex + n) #define __EX(fds, n) (fds->ex + n)
......
...@@ -11,11 +11,12 @@ ...@@ -11,11 +11,12 @@
#include <asm/uaccess.h> #include <asm/uaccess.h>
struct poll_table_page; struct poll_table_page;
struct poll_table_struct;
typedef void (*poll_queue_proc)(struct file *, wait_queue_head_t *, struct poll_table_struct *);
typedef struct poll_table_struct { typedef struct poll_table_struct {
int queue; poll_queue_proc qproc;
void *priv;
void (*qproc)(void *, wait_queue_head_t *);
int error; int error;
struct poll_table_page * table; struct poll_table_page * table;
} poll_table; } poll_table;
...@@ -25,16 +26,12 @@ extern void __pollwait(struct file * filp, wait_queue_head_t * wait_address, pol ...@@ -25,16 +26,12 @@ extern void __pollwait(struct file * filp, wait_queue_head_t * wait_address, pol
static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p) static inline void poll_wait(struct file * filp, wait_queue_head_t * wait_address, poll_table *p)
{ {
if (p && wait_address) if (p && wait_address)
__pollwait(filp, wait_address, p); p->qproc(filp, wait_address, p);
} }
static inline void poll_initwait_ex(poll_table* pt, int queue, static inline void poll_initwait_ex(poll_table* pt, poll_queue_proc qproc)
void (*qproc)(void *, wait_queue_head_t *),
void *priv)
{ {
pt->queue = queue;
pt->qproc = qproc; pt->qproc = qproc;
pt->priv = priv;
pt->error = 0; pt->error = 0;
pt->table = NULL; pt->table = NULL;
} }
...@@ -42,7 +39,7 @@ static inline void poll_initwait_ex(poll_table* pt, int queue, ...@@ -42,7 +39,7 @@ static inline void poll_initwait_ex(poll_table* pt, int queue,
static inline void poll_initwait(poll_table* pt) static inline void poll_initwait(poll_table* pt)
{ {
poll_initwait_ex(pt, 1, NULL, NULL); poll_initwait_ex(pt, __pollwait);
} }
extern void poll_freewait(poll_table* pt); extern void poll_freewait(poll_table* pt);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment