[PATCH] dm: consolidate creation functions
[safe/jmp/linux-2.6] / fs / eventpoll.c
index 403b90a..9c677bb 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  fs/eventpoll.c ( Efficent event polling implementation )
- *  Copyright (C) 2001,...,2003         Davide Libenzi
+ *  Copyright (C) 2001,...,2006         Davide Libenzi
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -34,6 +34,7 @@
 #include <linux/eventpoll.h>
 #include <linux/mount.h>
 #include <linux/bitops.h>
+#include <linux/mutex.h>
 #include <asm/uaccess.h>
 #include <asm/system.h>
 #include <asm/io.h>
@@ -46,7 +47,7 @@
  * LOCKING:
  * There are three level of locking required by epoll :
  *
- * 1) epsem (semaphore)
+ * 1) epmutex (mutex)
  * 2) ep->sem (rw_semaphore)
  * 3) ep->lock (rw_lock)
  *
@@ -67,9 +68,9 @@
  * if a file has been pushed inside an epoll set and it is then
  * close()d without a previous call toepoll_ctl(EPOLL_CTL_DEL).
  * It is possible to drop the "ep->sem" and to use the global
- * semaphore "epsem" (together with "ep->lock") to have it working,
+ * semaphore "epmutex" (together with "ep->lock") to have it working,
  * but having "ep->sem" will make the interface more scalable.
- * Events that require holding "epsem" are very rare, while for
+ * Events that require holding "epmutex" are very rare, while for
  * normal operations the epoll private "ep->sem" will guarantee
  * a greater scalability.
  */
 /* Maximum number of poll wake up nests we are allowing */
 #define EP_MAX_POLLWAKE_NESTS 4
 
+/* Maximum msec timeout value storeable in a long int */
+#define EP_MAX_MSTIMEO min(1000ULL * MAX_SCHEDULE_TIMEOUT / HZ, (LONG_MAX - 999ULL) / HZ)
+
+
 struct epoll_filefd {
        struct file *file;
        int fd;
@@ -263,29 +268,29 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
                   int maxevents, long timeout);
 static int eventpollfs_delete_dentry(struct dentry *dentry);
 static struct inode *ep_eventpoll_inode(void);
-static struct super_block *eventpollfs_get_sb(struct file_system_type *fs_type,
-                                             int flags, const char *dev_name,
-                                             void *data);
+static int eventpollfs_get_sb(struct file_system_type *fs_type,
+                             int flags, const char *dev_name,
+                             void *data, struct vfsmount *mnt);
 
 /*
  * This semaphore is used to serialize ep_free() and eventpoll_release_file().
  */
-static struct semaphore epsem;
+static struct mutex epmutex;
 
 /* Safe wake up implementation */
 static struct poll_safewake psw;
 
 /* Slab cache used to allocate "struct epitem" */
-static kmem_cache_t *epi_cache;
+static kmem_cache_t *epi_cache __read_mostly;
 
 /* Slab cache used to allocate "struct eppoll_entry" */
-static kmem_cache_t *pwq_cache;
+static kmem_cache_t *pwq_cache __read_mostly;
 
 /* Virtual fs used to allocate inodes for eventpoll files */
-static struct vfsmount *eventpoll_mnt;
+static struct vfsmount *eventpoll_mnt __read_mostly;
 
 /* File callbacks that implement the eventpoll file behaviour */
-static struct file_operations eventpoll_fops = {
+static const struct file_operations eventpoll_fops = {
        .release        = ep_eventpoll_close,
        .poll           = ep_eventpoll_poll
 };
@@ -332,20 +337,20 @@ static inline int ep_cmp_ffd(struct epoll_filefd *p1,
 /* Special initialization for the rb-tree node to detect linkage */
 static inline void ep_rb_initnode(struct rb_node *n)
 {
-       n->rb_parent = n;
+       rb_set_parent(n, n);
 }
 
 /* Removes a node from the rb-tree and marks it for a fast is-linked check */
 static inline void ep_rb_erase(struct rb_node *n, struct rb_root *r)
 {
        rb_erase(n, r);
-       n->rb_parent = n;
+       rb_set_parent(n, n);
 }
 
 /* Fast check to verify that the item is linked to the main rb-tree */
 static inline int ep_rb_linked(struct rb_node *n)
 {
-       return n->rb_parent != n;
+       return rb_parent(n) != n;
 }
 
 /*
@@ -447,15 +452,6 @@ static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq)
 }
 
 
-/* Used to initialize the epoll bits inside the "struct file" */
-void eventpoll_init_file(struct file *file)
-{
-
-       INIT_LIST_HEAD(&file->f_ep_links);
-       spin_lock_init(&file->f_ep_lock);
-}
-
-
 /*
  * This is called from eventpoll_release() to unlink files from the eventpoll
  * interface. We need to have this facility to cleanup correctly files that are
@@ -473,10 +469,10 @@ void eventpoll_release_file(struct file *file)
         * cleanup path, and this means that noone is using this file anymore.
         * The only hit might come from ep_free() but by holding the semaphore
         * will correctly serialize the operation. We do need to acquire
-        * "ep->sem" after "epsem" because ep_remove() requires it when called
+        * "ep->sem" after "epmutex" because ep_remove() requires it when called
         * from anywhere but ep_free().
         */
-       down(&epsem);
+       mutex_lock(&epmutex);
 
        while (!list_empty(lsthead)) {
                epi = list_entry(lsthead->next, struct epitem, fllink);
@@ -488,7 +484,7 @@ void eventpoll_release_file(struct file *file)
                up_write(&ep->sem);
        }
 
-       up(&epsem);
+       mutex_unlock(&epmutex);
 }
 
 
@@ -815,9 +811,9 @@ static void ep_free(struct eventpoll *ep)
         * We do not need to hold "ep->sem" here because the epoll file
         * is on the way to be removed and no one has references to it
         * anymore. The only hit might come from eventpoll_release_file() but
-        * holding "epsem" is sufficent here.
+        * holding "epmutex" is sufficent here.
         */
-       down(&epsem);
+       mutex_lock(&epmutex);
 
        /*
         * Walks through the whole tree by unregistering poll callbacks.
@@ -839,7 +835,7 @@ static void ep_free(struct eventpoll *ep)
                ep_remove(ep, epi);
        }
 
-       up(&epsem);
+       mutex_unlock(&epmutex);
 }
 
 
@@ -1008,7 +1004,7 @@ static int ep_insert(struct eventpoll *ep, struct epoll_event *event,
 
                /* Notify waiting tasks that events are available */
                if (waitqueue_active(&ep->wq))
-                       wake_up(&ep->wq);
+                       __wake_up_locked(&ep->wq, TASK_UNINTERRUPTIBLE | TASK_INTERRUPTIBLE);
                if (waitqueue_active(&ep->poll_wait))
                        pwake++;
        }
@@ -1087,7 +1083,8 @@ static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_even
 
                                /* Notify waiting tasks that events are available */
                                if (waitqueue_active(&ep->wq))
-                                       wake_up(&ep->wq);
+                                       __wake_up_locked(&ep->wq, TASK_UNINTERRUPTIBLE |
+                                                        TASK_INTERRUPTIBLE);
                                if (waitqueue_active(&ep->poll_wait))
                                        pwake++;
                        }
@@ -1264,7 +1261,8 @@ is_linked:
         * wait list.
         */
        if (waitqueue_active(&ep->wq))
-               wake_up(&ep->wq);
+               __wake_up_locked(&ep->wq, TASK_UNINTERRUPTIBLE |
+                                TASK_INTERRUPTIBLE);
        if (waitqueue_active(&ep->poll_wait))
                pwake++;
 
@@ -1448,7 +1446,8 @@ static void ep_reinject_items(struct eventpoll *ep, struct list_head *txlist)
                 * wait list.
                 */
                if (waitqueue_active(&ep->wq))
-                       wake_up(&ep->wq);
+                       __wake_up_locked(&ep->wq, TASK_UNINTERRUPTIBLE |
+                                        TASK_INTERRUPTIBLE);
                if (waitqueue_active(&ep->poll_wait))
                        pwake++;
        }
@@ -1506,8 +1505,8 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events,
         * and the overflow condition. The passed timeout is in milliseconds,
         * that why (t * HZ) / 1000.
         */
-       jtimeout = timeout == -1 || timeout > (MAX_SCHEDULE_TIMEOUT - 1000) / HZ ?
-               MAX_SCHEDULE_TIMEOUT: (timeout * HZ + 999) / 1000;
+       jtimeout = (timeout < 0 || timeout >= EP_MAX_MSTIMEO) ?
+               MAX_SCHEDULE_TIMEOUT : (timeout * HZ + 999) / 1000;
 
 retry:
        write_lock_irqsave(&ep->lock, flags);
@@ -1520,7 +1519,7 @@ retry:
                 * ep_poll_callback() when events will become available.
                 */
                init_waitqueue_entry(&wait, current);
-               add_wait_queue(&ep->wq, &wait);
+               __add_wait_queue(&ep->wq, &wait);
 
                for (;;) {
                        /*
@@ -1540,7 +1539,7 @@ retry:
                        jtimeout = schedule_timeout(jtimeout);
                        write_lock_irqsave(&ep->lock, flags);
                }
-               remove_wait_queue(&ep->wq, &wait);
+               __remove_wait_queue(&ep->wq, &wait);
 
                set_current_state(TASK_RUNNING);
        }
@@ -1599,11 +1598,12 @@ eexit_1:
 }
 
 
-static struct super_block *
+static int
 eventpollfs_get_sb(struct file_system_type *fs_type, int flags,
-                  const char *dev_name, void *data)
+                  const char *dev_name, void *data, struct vfsmount *mnt)
 {
-       return get_sb_pseudo(fs_type, "eventpoll:", NULL, EVENTPOLLFS_MAGIC);
+       return get_sb_pseudo(fs_type, "eventpoll:", NULL, EVENTPOLLFS_MAGIC,
+                            mnt);
 }
 
 
@@ -1611,7 +1611,7 @@ static int __init eventpoll_init(void)
 {
        int error;
 
-       init_MUTEX(&epsem);
+       mutex_init(&epmutex);
 
        /* Initialize the structure used to perform safe poll wait head wake ups */
        ep_poll_safewake_init(&psw);