patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / fs / eventpoll.c
index dbec5f9..bc30a3c 100644 (file)
 /* 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
@@ -309,7 +301,7 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi,
 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,
@@ -507,6 +499,11 @@ asmlinkage long sys_epoll_create(int size)
        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);
 
@@ -1296,7 +1293,7 @@ eexit_1:
  * 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;
@@ -1430,11 +1427,10 @@ static int ep_collect_ready_items(struct eventpoll *ep, struct list_head *txlist
 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.
@@ -1460,28 +1456,16 @@ static int ep_send_events(struct eventpoll *ep, struct list_head *txlist,
                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;
 }
 
@@ -1695,22 +1679,14 @@ static int __init eventpoll_init(void)
        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
@@ -1718,27 +1694,20 @@ static int __init eventpoll_init(void)
         */
        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");
 }
 
 
@@ -1755,4 +1724,3 @@ module_init(eventpoll_init);
 module_exit(eventpoll_exit);
 
 MODULE_LICENSE("GPL");
-