/* Get the "struct epitem" from an epoll queue wrapper */
#define EP_ITEM_FROM_EPQUEUE(p) (container_of(p, struct ep_pqueue, pt)->epi)
-/*
- * This is used to optimize the event transfer to userspace. Since this
- * is kept on stack, it should be pretty small.
- */
-#define EP_MAX_BUF_EVENTS 32
-
-
-
/*
* Node that is linked into the "wake_task_list" member of the "struct poll_safewake".
* It is used to keep track on all tasks that are currently inside the wake_up() code
static void ep_unregister_pollwait(struct eventpoll *ep, struct epitem *epi);
static int ep_unlink(struct eventpoll *ep, struct epitem *epi);
static int ep_remove(struct eventpoll *ep, struct epitem *epi);
-static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync);
+static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *key);
static int ep_eventpoll_close(struct inode *inode, struct file *file);
static unsigned int ep_eventpoll_poll(struct file *file, poll_table *wait);
static int ep_collect_ready_items(struct eventpoll *ep,
DNPRINTK(3, (KERN_INFO "[%p] eventpoll: sys_epoll_create(%d)\n",
current, size));
+ /* Sanity check on the size parameter */
+ error = -EINVAL;
+ if (size <= 0)
+ goto eexit_1;
+
/* Correctly size the hash */
hashbits = ep_get_hash_bits((unsigned int) size);
* machanism. It is called by the stored file descriptors when they
* have events to report.
*/
-static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync)
+static int ep_poll_callback(wait_queue_t *wait, unsigned mode, int sync, void *key)
{
int pwake = 0;
unsigned long flags;
static int ep_send_events(struct eventpoll *ep, struct list_head *txlist,
struct epoll_event __user *events)
{
- int eventcnt = 0, eventbuf = 0;
+ int eventcnt = 0;
unsigned int revents;
struct list_head *lnk;
struct epitem *epi;
- struct epoll_event event[EP_MAX_BUF_EVENTS];
/*
* We can loop without lock because this is a task private list.
epi->revents = revents & epi->event.events;
if (epi->revents) {
- event[eventbuf] = epi->event;
- event[eventbuf].events &= revents;
- eventbuf++;
- if (eventbuf == EP_MAX_BUF_EVENTS) {
- if (__copy_to_user(&events[eventcnt], event,
- eventbuf * sizeof(struct epoll_event)))
- return -EFAULT;
- eventcnt += eventbuf;
- eventbuf = 0;
- }
+ if (__put_user(epi->revents,
+ &events[eventcnt].events) ||
+ __put_user(epi->event.data,
+ &events[eventcnt].data))
+ return -EFAULT;
if (epi->event.events & EPOLLONESHOT)
epi->event.events &= EP_PRIVATE_BITS;
+ eventcnt++;
}
}
-
- if (eventbuf) {
- if (__copy_to_user(&events[eventcnt], event,
- eventbuf * sizeof(struct epoll_event)))
- return -EFAULT;
- eventcnt += eventbuf;
- }
-
return eventcnt;
}
ep_poll_safewake_init(&psw);
/* Allocates slab cache used to allocate "struct epitem" items */
- error = -ENOMEM;
- epi_cache = kmem_cache_create("eventpoll_epi",
- sizeof(struct epitem),
- 0,
- SLAB_HWCACHE_ALIGN | EPI_SLAB_DEBUG, NULL, NULL);
- if (!epi_cache)
- goto eexit_1;
+ epi_cache = kmem_cache_create("eventpoll_epi", sizeof(struct epitem),
+ 0, SLAB_HWCACHE_ALIGN|EPI_SLAB_DEBUG|SLAB_PANIC,
+ NULL, NULL);
/* Allocates slab cache used to allocate "struct eppoll_entry" */
- error = -ENOMEM;
pwq_cache = kmem_cache_create("eventpoll_pwq",
- sizeof(struct eppoll_entry),
- 0,
- EPI_SLAB_DEBUG, NULL, NULL);
- if (!pwq_cache)
- goto eexit_2;
+ sizeof(struct eppoll_entry), 0,
+ EPI_SLAB_DEBUG|SLAB_PANIC, NULL, NULL);
/*
* Register the virtual file system that will be the source of inodes
*/
error = register_filesystem(&eventpoll_fs_type);
if (error)
- goto eexit_3;
+ goto epanic;
/* Mount the above commented virtual file system */
eventpoll_mnt = kern_mount(&eventpoll_fs_type);
error = PTR_ERR(eventpoll_mnt);
if (IS_ERR(eventpoll_mnt))
- goto eexit_4;
-
- DNPRINTK(3, (KERN_INFO "[%p] eventpoll: successfully initialized.\n", current));
+ goto epanic;
+ DNPRINTK(3, (KERN_INFO "[%p] eventpoll: successfully initialized.\n",
+ current));
return 0;
-eexit_4:
- unregister_filesystem(&eventpoll_fs_type);
-eexit_3:
- kmem_cache_destroy(pwq_cache);
-eexit_2:
- kmem_cache_destroy(epi_cache);
-eexit_1:
-
- return error;
+epanic:
+ panic("eventpoll_init() failed\n");
}
module_exit(eventpoll_exit);
MODULE_LICENSE("GPL");
-