SOURCES (AC-branch): kernel24-epoll-lt.patch (NEW) - epoll for 2.4...
glen
glen at pld-linux.org
Sat Apr 12 19:48:47 CEST 2008
Author: glen Date: Sat Apr 12 17:48:47 2008 GMT
Module: SOURCES Tag: AC-branch
---- Log message:
- epoll for 2.4 kernel
raw from http://www.xmailserver.org/linux-patches/epoll-lt-2.4.32-0.23.diff
---- Files affected:
SOURCES:
kernel24-epoll-lt.patch (NONE -> 1.1.2.1) (NEW)
---- Diffs:
================================================================
Index: SOURCES/kernel24-epoll-lt.patch
diff -u /dev/null SOURCES/kernel24-epoll-lt.patch:1.1.2.1
--- /dev/null Sat Apr 12 19:48:47 2008
+++ SOURCES/kernel24-epoll-lt.patch Sat Apr 12 19:48:42 2008
@@ -0,0 +1,2624 @@
+diff -urN linux-2.4.32/arch/i386/kernel/entry.S linux-2.4.32-epoll-lt-0.23/arch/i386/kernel/entry.S
+--- linux-2.4.32/arch/i386/kernel/entry.S Mon Apr 21 22:40:57 2003
++++ linux-2.4.32-epoll-lt-0.23/arch/i386/kernel/entry.S Sun Jun 4 22:54:01 2006
+@@ -658,9 +658,9 @@
+ .long SYMBOL_NAME(sys_ni_syscall) /* sys_free_hugepages */
+ .long SYMBOL_NAME(sys_ni_syscall) /* sys_exit_group */
+ .long SYMBOL_NAME(sys_ni_syscall) /* sys_lookup_dcookie */
+- .long SYMBOL_NAME(sys_ni_syscall) /* sys_epoll_create */
+- .long SYMBOL_NAME(sys_ni_syscall) /* sys_epoll_ctl 255 */
+- .long SYMBOL_NAME(sys_ni_syscall) /* sys_epoll_wait */
++ .long SYMBOL_NAME(sys_epoll_create) /* sys_epoll_create */
++ .long SYMBOL_NAME(sys_epoll_ctl) /* sys_epoll_ctl 255 */
++ .long SYMBOL_NAME(sys_epoll_wait) /* sys_epoll_wait */
+ .long SYMBOL_NAME(sys_ni_syscall) /* sys_remap_file_pages */
+ .long SYMBOL_NAME(sys_ni_syscall) /* sys_set_tid_address */
+
+diff -urN linux-2.4.32/arch/ia64/ia32/ia32_entry.S linux-2.4.32-epoll-lt-0.23/arch/ia64/ia32/ia32_entry.S
+--- linux-2.4.32/arch/ia64/ia32/ia32_entry.S Fri Feb 20 07:38:25 2004
++++ linux-2.4.32-epoll-lt-0.23/arch/ia64/ia32/ia32_entry.S Sun Jun 4 22:54:01 2006
+@@ -421,10 +421,37 @@
+ data8 sys_ni_syscall /* reserved for Security */
+ data8 sys_gettid
+ data8 sys_readahead /* 225 */
+- data8 sys_ni_syscall
+- data8 sys_ni_syscall
+- data8 sys_ni_syscall
+- data8 sys_ni_syscall
++ data8 sys32_ni_syscall
++ data8 sys32_ni_syscall
++ data8 sys32_ni_syscall
++ data8 sys32_ni_syscall
++ data8 sys32_ni_syscall /* 230 */
++ data8 sys32_ni_syscall
++ data8 sys32_ni_syscall
++ data8 sys32_ni_syscall
++ data8 sys32_ni_syscall
++ data8 sys32_ni_syscall /* 235 */
++ data8 sys32_ni_syscall
++ data8 sys32_ni_syscall
++ data8 sys32_ni_syscall
++ data8 sys32_ni_syscall
++ data8 sys32_ni_syscall /* 240 */
++ data8 sys32_ni_syscall
++ data8 sys32_ni_syscall
++ data8 sys32_ni_syscall
++ data8 sys32_ni_syscall
++ data8 sys32_ni_syscall /* 245 */
++ data8 sys32_ni_syscall
++ data8 sys32_ni_syscall
++ data8 sys32_ni_syscall
++ data8 sys32_ni_syscall
++ data8 sys32_ni_syscall /* 250 */
++ data8 sys32_ni_syscall
++ data8 sys32_ni_syscall
++ data8 sys32_ni_syscall
++ data8 sys_epoll_create
++ data8 sys32_epoll_ctl /* 255 */
++ data8 sys32_epoll_wait
+ /*
+ * CAUTION: If any system calls are added beyond this point
+ * then the check in `arch/ia64/kernel/ivt.S' will have
+diff -urN linux-2.4.32/arch/ia64/ia32/sys_ia32.c linux-2.4.32-epoll-lt-0.23/arch/ia64/ia32/sys_ia32.c
+--- linux-2.4.32/arch/ia64/ia32/sys_ia32.c Sun Dec 4 22:06:00 2005
++++ linux-2.4.32-epoll-lt-0.23/arch/ia64/ia32/sys_ia32.c Sun Jun 4 22:54:01 2006
+@@ -46,6 +46,7 @@
+ #include <linux/nfsd/xdr.h>
+ #include <linux/nfsd/syscall.h>
+ #include <linux/poll.h>
++#include <linux/eventpoll.h>
+ #include <linux/personality.h>
+ #include <linux/stat.h>
+ #include <linux/ipc.h>
+@@ -4056,6 +4057,82 @@
+ put_unused_fd(fd);
+ fd = error;
+ goto out;
++}
++
++/* Structure for ia32 emulation on ia64 */
++struct epoll_event32
++{
++ u32 events;
++ u64 data;
++} __attribute__((packed));
++
++asmlinkage long
++sys32_epoll_ctl(int epfd, int op, int fd, struct epoll_event32 *event)
++{
++ mm_segment_t old_fs = get_fs();
++ struct epoll_event event64;
++ int error = -EFAULT;
++ u32 data_halfword;
++
++ if ((error = verify_area(VERIFY_READ, event,
++ sizeof(struct epoll_event32))))
++ return error;
++
++ __get_user(event64.events, &event->events);
++ __get_user(data_halfword, (u32*)(&event->data));
++ event64.data = data_halfword;
++ __get_user(data_halfword, ((u32*)(&event->data) + 1));
++ event64.data |= ((u64)data_halfword) << 32;
++
++ set_fs(KERNEL_DS);
++ error = sys_epoll_ctl(epfd, op, fd, &event64);
++ set_fs(old_fs);
++
++ return error;
++}
++
++asmlinkage long
++sys32_epoll_wait(int epfd, struct epoll_event32 *events, int maxevents,
++ int timeout)
++{
++ struct epoll_event *events64 = NULL;
++ mm_segment_t old_fs = get_fs();
++ int i, error, nevents;
++
++ if (maxevents <= 0)
++ return -EINVAL;
++
++ /* Verify that the area passed by the user is writeable */
++ if ((error = verify_area(VERIFY_WRITE, events,
++ maxevents * sizeof(struct epoll_event32))))
++ return error;
++
++ /* Allocate the space needed for the intermediate copy */
++ events64 = kmalloc(maxevents * sizeof(struct epoll_event), GFP_KERNEL);
++ if (events64 == NULL)
++ return -ENOMEM;
++
++ /* Do the system call */
++ set_fs(KERNEL_DS); /* copy_to/from_user should work on kernel mem*/
++ error = nevents = sys_epoll_wait(epfd, events64, maxevents, timeout);
++ set_fs(old_fs);
++
++ /* Don't modify userspace memory if we're returning an error */
++ if (!error) {
++ /* Translate the 64-bit structures back into the 32-bit
++ structures */
++ for (i = 0; i < nevents; i++) {
++ __put_user(events64[i].events,
++ &events[i].events);
++ __put_user((u32)(events64[i].data),
++ (u32*)(&events[i].data));
++ __put_user((u32)(events64[i].data >> 32),
++ ((u32*)(&events[i].data) + 1));
++ }
++ }
++
++ kfree(events64);
++ return error;
+ }
+
+ #ifdef NOTYET /* UNTESTED FOR IA64 FROM HERE DOWN */
+diff -urN linux-2.4.32/arch/ia64/kernel/entry.S linux-2.4.32-epoll-lt-0.23/arch/ia64/kernel/entry.S
+--- linux-2.4.32/arch/ia64/kernel/entry.S Sun Apr 17 15:32:22 2005
++++ linux-2.4.32-epoll-lt-0.23/arch/ia64/kernel/entry.S Sun Jun 4 22:54:01 2006
+@@ -1419,9 +1419,9 @@
+ data8 ia64_ni_syscall // 1240
+ data8 ia64_ni_syscall
+ data8 ia64_ni_syscall
+- data8 ia64_ni_syscall
+- data8 ia64_ni_syscall
+- data8 ia64_ni_syscall // 1245
++ data8 sys_epoll_create
++ data8 sys_epoll_ctl
++ data8 sys_epoll_wait // 1245
+ data8 ia64_ni_syscall
+ data8 ia64_ni_syscall
+ data8 ia64_ni_syscall
+diff -urN linux-2.4.32/arch/ia64/kernel/ivt.S linux-2.4.32-epoll-lt-0.23/arch/ia64/kernel/ivt.S
+--- linux-2.4.32/arch/ia64/kernel/ivt.S Sun Apr 17 15:32:22 2005
++++ linux-2.4.32-epoll-lt-0.23/arch/ia64/kernel/ivt.S Sun Jun 4 22:54:01 2006
+@@ -1509,7 +1509,7 @@
+ alloc r15=ar.pfs,0,0,6,0 // must first in an insn group
+ ;;
+ ld4 r8=[r14],8 // r8 == eax (syscall number)
+- mov r15=230 // number of entries in ia32 system call table
++ mov r15=257 // number of entries in ia32 system call table
+ ;;
+ cmp.ltu.unc p6,p7=r8,r15
+ ld4 out1=[r14],8 // r9 == ecx
+diff -urN linux-2.4.32/arch/sparc64/solaris/timod.c linux-2.4.32-epoll-lt-0.23/arch/sparc64/solaris/timod.c
+--- linux-2.4.32/arch/sparc64/solaris/timod.c Sun Aug 4 12:04:59 2002
++++ linux-2.4.32-epoll-lt-0.23/arch/sparc64/solaris/timod.c Sun Jun 4 22:54:01 2006
+@@ -651,10 +651,11 @@
+ SOLD("LISTEN done");
+ }
+ if (!(filp->f_flags & O_NONBLOCK)) {
+- poll_table wait_table, *wait;
++ struct poll_wqueues wait_table;
++ poll_table *wait;
+
+ poll_initwait(&wait_table);
+- wait = &wait_table;
++ wait = &wait_table.pt;
+ for(;;) {
+ SOLD("loop");
+ set_current_state(TASK_INTERRUPTIBLE);
+diff -urN linux-2.4.32/fs/Makefile linux-2.4.32-epoll-lt-0.23/fs/Makefile
+--- linux-2.4.32/fs/Makefile Fri Feb 20 07:38:31 2004
++++ linux-2.4.32-epoll-lt-0.23/fs/Makefile Sun Jun 4 22:54:01 2006
+@@ -14,7 +14,7 @@
+ super.o block_dev.o char_dev.o stat.o exec.o pipe.o namei.o \
+ fcntl.o ioctl.o readdir.o select.o fifo.o locks.o \
+ dcache.o inode.o attr.o bad_inode.o file.o iobuf.o dnotify.o \
+- filesystems.o namespace.o seq_file.o xattr.o quota.o
++ filesystems.o namespace.o seq_file.o xattr.o quota.o eventpoll.o
+
+ obj-$(CONFIG_QUOTA) += dquot.o quota_v1.o
+ obj-$(CONFIG_QFMT_V2) += quota_v2.o
+diff -urN linux-2.4.32/fs/eventpoll.c linux-2.4.32-epoll-lt-0.23/fs/eventpoll.c
+--- linux-2.4.32/fs/eventpoll.c Thu Jan 1 01:00:00 1970
++++ linux-2.4.32-epoll-lt-0.23/fs/eventpoll.c Sun Jun 4 22:54:52 2006
+@@ -0,0 +1,1776 @@
++/*
++ * fs/eventpoll.c ( Efficent event polling implementation )
++ * 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
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * Davide Libenzi <davidel at xmailserver.org>
++ *
++ * 11 December 2002
++ * Ported from 2.5.51 - janetinc at us.ibm.com
++ *
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/kernel.h>
++#include <linux/sched.h>
++#include <linux/fs.h>
++#include <linux/file.h>
++#include <linux/signal.h>
++#include <linux/errno.h>
++#include <linux/mm.h>
++#include <linux/slab.h>
++#include <linux/poll.h>
++#include <linux/smp_lock.h>
++#include <linux/string.h>
++#include <linux/list.h>
++#include <linux/hash.h>
++#include <linux/spinlock.h>
++#include <linux/rwsem.h>
++#include <linux/wait.h>
++#include <linux/eventpoll.h>
++#include <linux/mount.h>
++#include <asm/bitops.h>
++#include <asm/uaccess.h>
++#include <asm/system.h>
++#include <asm/io.h>
++#include <asm/mman.h>
++#include <asm/atomic.h>
++#include <asm/semaphore.h>
++
++
++/*
++ * LOCKING:
++ * There are three level of locking required by epoll :
++ *
++ * 1) epsem (semaphore)
++ * 2) ep->sem (rw_semaphore)
++ * 3) ep->lock (rw_lock)
++ *
++ * The acquire order is the one listed above, from 1 to 3.
++ * We need a spinlock (ep->lock) because we manipulate objects
++ * from inside the poll callback, that might be triggered from
++ * a wake_up() that in turn might be called from IRQ context.
++ * So we can't sleep inside the poll callback and hence we need
++ * a spinlock. During the event transfer loop (from kernel to
++ * user space) we could end up sleeping due a copy_to_user(), so
++ * we need a lock that will allow us to sleep. This lock is a
++ * read-write semaphore (ep->sem). It is acquired on read during
++ * the event transfer loop and in write during epoll_ctl(EPOLL_CTL_DEL)
++ * and during eventpoll_release(). Then we also need a global
++ * semaphore to serialize eventpoll_release() and ep_free().
++ * This semaphore is acquired by ep_free() during the epoll file
++ * cleanup path and it is also acquired by eventpoll_release()
++ * 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,
++ * but having "ep->sem" will make the interface more scalable.
++ * Events that require holding "epsem" are very rare, while for
++ * normal operations the epoll private "ep->sem" will guarantee
++ * a greater scalability.
++ */
++
++
++#define EVENTPOLLFS_MAGIC 0x03111965 /* My birthday should work for this :) */
++
++#define DEBUG_EPOLL 0
++
++#if DEBUG_EPOLL > 0
++#define DPRINTK(x) printk x
++#define DNPRINTK(n, x) do { if ((n) <= DEBUG_EPOLL) printk x; } while (0)
++#else /* #if DEBUG_EPOLL > 0 */
++#define DPRINTK(x) (void) 0
++#define DNPRINTK(n, x) (void) 0
++#endif /* #if DEBUG_EPOLL > 0 */
++
++#define DEBUG_EPI 0
++
++#if DEBUG_EPI != 0
++#define EPI_SLAB_DEBUG (SLAB_DEBUG_FREE | SLAB_RED_ZONE /* | SLAB_POISON */)
++#else /* #if DEBUG_EPI != 0 */
++#define EPI_SLAB_DEBUG 0
++#endif /* #if DEBUG_EPI != 0 */
++
++/* Epoll private bits inside the event mask */
++#define EP_PRIVATE_BITS (EPOLLONESHOT | EPOLLET)
++
++/* Maximum number of poll wake up nests we are allowing */
++#define EP_MAX_POLLWAKE_NESTS 4
++
++/* Maximum size of the hash in bits ( 2^N ) */
++#define EP_MAX_HASH_BITS 17
++
++/* Minimum size of the hash in bits ( 2^N ) */
++#define EP_MIN_HASH_BITS 9
++
++/* Number of hash entries ( "struct list_head" ) inside a page */
++#define EP_HENTRY_X_PAGE (PAGE_SIZE / sizeof(struct list_head))
++
++/* Maximum size of the hash in pages */
++#define EP_MAX_HPAGES ((1 << EP_MAX_HASH_BITS) / EP_HENTRY_X_PAGE + 1)
++
++/* Number of pages allocated for an "hbits" sized hash table */
++#define EP_HASH_PAGES(hbits) ((int) ((1 << (hbits)) / EP_HENTRY_X_PAGE + \
++ ((1 << (hbits)) % EP_HENTRY_X_PAGE ? 1: 0)))
++
++/* Macro to allocate a "struct epitem" from the slab cache */
++#define EPI_MEM_ALLOC() (struct epitem *) kmem_cache_alloc(epi_cache, SLAB_KERNEL)
++
++/* Macro to free a "struct epitem" to the slab cache */
++#define EPI_MEM_FREE(p) kmem_cache_free(epi_cache, p)
++
++/* Macro to allocate a "struct eppoll_entry" from the slab cache */
++#define PWQ_MEM_ALLOC() (struct eppoll_entry *) kmem_cache_alloc(pwq_cache, SLAB_KERNEL)
++
++/* Macro to free a "struct eppoll_entry" to the slab cache */
++#define PWQ_MEM_FREE(p) kmem_cache_free(pwq_cache, p)
++
++/* Fast test to see if the file is an evenpoll file */
++#define IS_FILE_EPOLL(f) ((f)->f_op == &eventpoll_fops)
++
++/*
++ * Remove the item from the list and perform its initialization.
++ * This is usefull for us because we can test if the item is linked
++ * using "EP_IS_LINKED(p)".
++ */
++#define EP_LIST_DEL(p) do { list_del(p); INIT_LIST_HEAD(p); } while (0)
++
++/* Tells us if the item is currently linked */
++#define EP_IS_LINKED(p) (!list_empty(p))
++
++/* 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)->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
++ * to 1) short-circuit the one coming from the same task and same wait queue head
++ * ( loop ) 2) allow a maximum number of epoll descriptors inclusion nesting
++ * 3) let go the ones coming from other tasks.
++ */
++struct wake_task_node {
++ struct list_head llink;
++ task_t *task;
++ wait_queue_head_t *wq;
++};
++
++/*
++ * This is used to implement the safe poll wake up avoiding to reenter
++ * the poll callback from inside wake_up().
++ */
++struct poll_safewake {
++ struct list_head wake_task_list;
++ spinlock_t lock;
++};
++
++/*
++ * This structure is stored inside the "private_data" member of the file
++ * structure and represent the main data sructure for the eventpoll
++ * interface.
++ */
++struct eventpoll {
++ /* Protect the this structure access */
++ rwlock_t lock;
++
++ /*
++ * This semaphore is used to ensure that files are not removed
++ * while epoll is using them. This is read-held during the event
++ * collection loop and it is write-held during the file cleanup
++ * path, the epoll file exit code and the ctl operations.
++ */
++ struct rw_semaphore sem;
++
++ /* Wait queue used by sys_epoll_wait() */
++ wait_queue_head_t wq;
++
++ /* Wait queue used by file->poll() */
++ wait_queue_head_t poll_wait;
++
++ /* List of ready file descriptors */
++ struct list_head rdllist;
++
++ /* Size of the hash */
++ unsigned int hashbits;
++
++ /* Pages for the "struct epitem" hash */
++ char *hpages[EP_MAX_HPAGES];
++};
++
++/* Wait structure used by the poll hooks */
++struct eppoll_entry {
++ /* List header used to link this structure to the "struct epitem" */
++ struct list_head llink;
++
++ /* The "base" pointer is set to the container "struct epitem" */
++ void *base;
++
++ /*
++ * Wait queue item that will be linked to the target file wait
++ * queue head.
++ */
++ wait_queue_t wait;
++
++ /* The wait queue head that linked the "wait" wait queue item */
++ wait_queue_head_t *whead;
++};
++
++/*
++ * Each file descriptor added to the eventpoll interface will
++ * have an entry of this type linked to the hash.
++ */
++struct epitem {
++ /* List header used to link this structure to the eventpoll hash */
++ struct list_head llink;
++
++ /* List header used to link this structure to the eventpoll ready list */
++ struct list_head rdllink;
++
++ /* Number of active wait queue attached to poll operations */
++ int nwait;
++
++ /* List containing poll wait queues */
++ struct list_head pwqlist;
++
++ /* The "container" of this item */
++ struct eventpoll *ep;
++
++ /* The file descriptor this item refers to */
++ int fd;
++
++ /* The file this item refers to */
++ struct file *file;
++
++ /* The structure that describe the interested events and the source fd */
++ struct epoll_event event;
++
++ /*
++ * Used to keep track of the usage count of the structure. This avoids
++ * that the structure will desappear from underneath our processing.
++ */
++ atomic_t usecnt;
++
++ /* List header used to link this item to the "struct file" items list */
++ struct list_head fllink;
++
++ /* List header used to link the item to the transfer list */
++ struct list_head txlink;
++
++ /*
++ * This is used during the collection/transfer of events to userspace
++ * to pin items empty events set.
++ */
++ unsigned int revents;
++};
++
++/* Wrapper struct used by poll queueing */
++struct ep_pqueue {
++ poll_table pt;
++ struct epitem *epi;
++};
++
++
++
++static void ep_poll_safewake_init(struct poll_safewake *psw);
++static void ep_poll_safewake(struct poll_safewake *psw, wait_queue_head_t *wq);
++static unsigned int ep_get_hash_bits(unsigned int hintsize);
++static int ep_getfd(int *efd, struct inode **einode, struct file **efile);
++static int ep_alloc_pages(char **pages, int numpages);
++static int ep_free_pages(char **pages, int numpages);
++static int ep_file_init(struct file *file, unsigned int hashbits);
++static unsigned int ep_hash_index(struct eventpoll *ep, struct file *file, int fd);
++static struct list_head *ep_hash_entry(struct eventpoll *ep, unsigned int index);
++static int ep_init(struct eventpoll *ep, unsigned int hashbits);
++static void ep_free(struct eventpoll *ep);
++static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd);
++static void ep_use_epitem(struct epitem *epi);
++static void ep_release_epitem(struct epitem *epi);
++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 epoll_event *event,
++ struct file *tfile, int fd);
++static int ep_modify(struct eventpoll *ep, struct epitem *epi, struct epoll_event *event);
++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_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, struct list_head *txlist, int maxevents);
++static int ep_send_events(struct eventpoll *ep, struct list_head *txlist,
++ struct epoll_event *events);
++static void ep_reinject_items(struct eventpoll *ep, struct list_head *txlist);
++static int ep_events_transfer(struct eventpoll *ep, struct epoll_event *events, int maxevents);
++static int ep_poll(struct eventpoll *ep, struct epoll_event *events, int maxevents,
++ long timeout);
++static int eventpollfs_statfs(struct super_block *sb, struct statfs *buf);
++static struct super_block *eventpollfs_read_super(struct super_block *sb, void *data, int silent);
++static int eventpollfs_delete_dentry(struct dentry *dentry);
++static struct inode *ep_eventpoll_inode(void);
++
++/*
++ * This semaphore is used to serialize ep_free() and eventpoll_release().
++ */
++struct semaphore epsem;
++
++/* Safe wake up implementation */
++static struct poll_safewake psw;
++
++/* Slab cache used to allocate "struct epitem" */
++static kmem_cache_t *epi_cache;
++
++/* Slab cache used to allocate "struct eppoll_entry" */
++static kmem_cache_t *pwq_cache;
++
++/* Virtual fs used to allocate inodes for eventpoll files */
++static struct vfsmount *eventpoll_mnt;
++
++/* File callbacks that implement the eventpoll file behaviour */
++static struct file_operations eventpoll_fops = {
++ .release = ep_eventpoll_close,
++ .poll = ep_eventpoll_poll
++};
++
++/* Virtual fs operations */
++static struct super_operations eventpollfs_ops = {
++ .statfs = eventpollfs_statfs,
++};
++
++/* Virtual fs structure declaration */
++static DECLARE_FSTYPE(eventpoll_fs_type, "eventpollfs", eventpollfs_read_super, FS_NOMOUNT);
++
++/* Very basic directory entry operations for the eventpoll virtual file system */
++static struct dentry_operations eventpollfs_dentry_operations = {
++ .d_delete = eventpollfs_delete_dentry,
++};
++
++
++
++
++/* Initialize the poll safe wake up structure */
++static void ep_poll_safewake_init(struct poll_safewake *psw)
++{
++
++ INIT_LIST_HEAD(&psw->wake_task_list);
++ spin_lock_init(&psw->lock);
++}
++
++
++/*
++ * Perform a safe wake up of the poll wait list. The problem is that
<<Diff was trimmed, longer than 597 lines>>
More information about the pld-cvs-commit
mailing list