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 @@
/* 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)
/* 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 {
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);
......@@ -201,7 +209,7 @@ static void ep_free(struct eventpoll *ep);
static struct epitem *ep_find(struct eventpoll *ep, struct file *file);
static void ep_use_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_modify(struct eventpoll *ep, struct epitem *dpi, unsigned int events);
static int ep_unlink(struct eventpoll *ep, 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
* 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 */
if (dpi->nwait < EP_MAX_POLL_QUEUE) {
......@@ -809,7 +817,7 @@ static int ep_insert(struct eventpoll *ep, struct pollfd *pfd, struct file *tfil
int error, i, revents;
unsigned long flags;
struct epitem *dpi;
poll_table pt;
struct ep_pqueue epq;
error = -ENOMEM;
if (!(dpi = DPI_MEM_ALLOC()))
......@@ -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 */
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 */
write_lock_irqsave(&ep->lock, flags);
......@@ -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)));
/* 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 ((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
write_unlock_irqrestore(&ep->lock, flags);
poll_freewait(&pt);
poll_freewait(&epq.pt);
DNPRINTK(3, (KERN_INFO "[%p] eventpoll: ep_insert(%p, %d)\n",
current, ep, pfd->fd));
......@@ -874,20 +883,11 @@ static int ep_modify(struct eventpoll *ep, struct epitem *dpi, unsigned int even
{
unsigned int revents;
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);
/* 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 */
dpi->pfd.events = events;
......@@ -906,8 +906,6 @@ static int ep_modify(struct eventpoll *ep, struct epitem *dpi, unsigned int even
write_unlock_irqrestore(&ep->lock, flags);
poll_freewait(&pt);
return 0;
}
......@@ -1066,15 +1064,6 @@ static int ep_events_transfer(struct eventpoll *ep, struct pollfd *events, int m
unsigned long flags;
struct list_head *lsthead = &ep->rdllist;
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);
......@@ -1093,7 +1082,7 @@ static int ep_events_transfer(struct eventpoll *ep, struct pollfd *events, int m
continue;
/* 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) {
eventbuf[ebufcnt] = dpi->pfd;
......@@ -1108,10 +1097,8 @@ static int ep_events_transfer(struct eventpoll *ep, struct pollfd *events, int m
*/
write_unlock_irqrestore(&ep->lock, flags);
if (__copy_to_user(&events[eventcnt], eventbuf,
ebufcnt * sizeof(struct pollfd))) {
poll_freewait(&pt);
ebufcnt * sizeof(struct pollfd)))
return -EFAULT;
}
eventcnt += ebufcnt;
ebufcnt = 0;
write_lock_irqsave(&ep->lock, flags);
......@@ -1129,8 +1116,6 @@ static int ep_events_transfer(struct eventpoll *ep, struct pollfd *events, int m
eventcnt += ebufcnt;
}
poll_freewait(&pt);
return eventcnt;
}
......
......@@ -77,14 +77,6 @@ void __pollwait(struct file * filp, wait_queue_head_t * wait_address, poll_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)) {
struct poll_table_page *new_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 __OUT(fds, n) (fds->out + n)
#define __EX(fds, n) (fds->ex + n)
......
......@@ -11,11 +11,12 @@
#include <asm/uaccess.h>
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 {
int queue;
void *priv;
void (*qproc)(void *, wait_queue_head_t *);
poll_queue_proc qproc;
int error;
struct poll_table_page * table;
} poll_table;
......@@ -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)
{
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,
void (*qproc)(void *, wait_queue_head_t *),
void *priv)
static inline void poll_initwait_ex(poll_table* pt, poll_queue_proc qproc)
{
pt->queue = queue;
pt->qproc = qproc;
pt->priv = priv;
pt->error = 0;
pt->table = NULL;
}
......@@ -42,7 +39,7 @@ static inline void poll_initwait_ex(poll_table* pt, int queue,
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);
......
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