mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
Signed-off-by: Christian Limpach <Christian.Limpach@xensource.com> --HG-- rename : patches/linux-2.6.16.13/blktap-aio-16_03_06.patch => patches/linux-2.6.16.29/blktap-aio-16_03_06.patch rename : patches/linux-2.6.16.13/device_bind.patch => patches/linux-2.6.16.29/device_bind.patch rename : patches/linux-2.6.16.13/fix-hz-suspend.patch => patches/linux-2.6.16.29/fix-hz-suspend.patch rename : patches/linux-2.6.16.13/fix-ide-cd-pio-mode.patch => patches/linux-2.6.16.29/fix-ide-cd-pio-mode.patch rename : patches/linux-2.6.16.13/i386-mach-io-check-nmi.patch => patches/linux-2.6.16.29/i386-mach-io-check-nmi.patch rename : patches/linux-2.6.16.13/ipv6-no-autoconf.patch => patches/linux-2.6.16.29/ipv6-no-autoconf.patch rename : patches/linux-2.6.16.13/net-csum.patch => patches/linux-2.6.16.29/net-csum.patch rename : patches/linux-2.6.16.13/net-gso-0-base.patch => patches/linux-2.6.16.29/net-gso-0-base.patch rename : patches/linux-2.6.16.13/net-gso-1-check-dodgy.patch => patches/linux-2.6.16.29/net-gso-1-check-dodgy.patch rename : patches/linux-2.6.16.13/net-gso-2-checksum-fix.patch => patches/linux-2.6.16.29/net-gso-2-checksum-fix.patch rename : patches/linux-2.6.16.13/net-gso-3-fix-errorcheck.patch => patches/linux-2.6.16.29/net-gso-3-fix-errorcheck.patch rename : patches/linux-2.6.16.13/net-gso-4-kill-warnon.patch => patches/linux-2.6.16.29/net-gso-4-kill-warnon.patch rename : patches/linux-2.6.16.13/pmd-shared.patch => patches/linux-2.6.16.29/pmd-shared.patch rename : patches/linux-2.6.16.13/rcu_needs_cpu.patch => patches/linux-2.6.16.29/rcu_needs_cpu.patch rename : patches/linux-2.6.16.13/rename-TSS_sysenter_esp0-SYSENTER_stack_esp0.patch => patches/linux-2.6.16.29/rename-TSS_sysenter_esp0-SYSENTER_stack_esp0.patch rename : patches/linux-2.6.16.13/series => patches/linux-2.6.16.29/series rename : patches/linux-2.6.16.13/smp-alts.patch => patches/linux-2.6.16.29/smp-alts.patch rename : patches/linux-2.6.16.13/tpm_plugin_2.6.17.patch => patches/linux-2.6.16.29/tpm_plugin_2.6.17.patch rename : patches/linux-2.6.16.13/x86-elfnote-as-preprocessor-macro.patch => patches/linux-2.6.16.29/x86-elfnote-as-preprocessor-macro.patch rename : patches/linux-2.6.16.13/x86-increase-interrupt-vector-range.patch => patches/linux-2.6.16.29/x86-increase-interrupt-vector-range.patch rename : patches/linux-2.6.16.13/x86-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch => patches/linux-2.6.16.29/x86-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch rename : patches/linux-2.6.16.13/x86_64-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch => patches/linux-2.6.16.29/x86_64-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch rename : patches/linux-2.6.16.13/xen-hotplug.patch => patches/linux-2.6.16.29/xen-hotplug.patch rename : patches/linux-2.6.16.13/xenoprof-generic.patch => patches/linux-2.6.16.29/xenoprof-generic.patch
295 lines
8.7 KiB
Diff
295 lines
8.7 KiB
Diff
diff -pruN ../orig-linux-2.6.16.29/fs/aio.c ./fs/aio.c
|
|
--- ../orig-linux-2.6.16.29/fs/aio.c 2006-09-12 19:02:10.000000000 +0100
|
|
+++ ./fs/aio.c 2006-09-19 13:58:49.000000000 +0100
|
|
@@ -34,6 +34,11 @@
|
|
#include <asm/uaccess.h>
|
|
#include <asm/mmu_context.h>
|
|
|
|
+#ifdef CONFIG_EPOLL
|
|
+#include <linux/poll.h>
|
|
+#include <linux/eventpoll.h>
|
|
+#endif
|
|
+
|
|
#if DEBUG > 1
|
|
#define dprintk printk
|
|
#else
|
|
@@ -1016,6 +1021,10 @@ put_rq:
|
|
if (waitqueue_active(&ctx->wait))
|
|
wake_up(&ctx->wait);
|
|
|
|
+#ifdef CONFIG_EPOLL
|
|
+ if (ctx->file && waitqueue_active(&ctx->poll_wait))
|
|
+ wake_up(&ctx->poll_wait);
|
|
+#endif
|
|
if (ret)
|
|
put_ioctx(ctx);
|
|
|
|
@@ -1025,6 +1034,8 @@ put_rq:
|
|
/* aio_read_evt
|
|
* Pull an event off of the ioctx's event ring. Returns the number of
|
|
* events fetched (0 or 1 ;-)
|
|
+ * If ent parameter is 0, just returns the number of events that would
|
|
+ * be fetched.
|
|
* FIXME: make this use cmpxchg.
|
|
* TODO: make the ringbuffer user mmap()able (requires FIXME).
|
|
*/
|
|
@@ -1047,13 +1058,18 @@ static int aio_read_evt(struct kioctx *i
|
|
|
|
head = ring->head % info->nr;
|
|
if (head != ring->tail) {
|
|
- struct io_event *evp = aio_ring_event(info, head, KM_USER1);
|
|
- *ent = *evp;
|
|
- head = (head + 1) % info->nr;
|
|
- smp_mb(); /* finish reading the event before updatng the head */
|
|
- ring->head = head;
|
|
- ret = 1;
|
|
- put_aio_ring_event(evp, KM_USER1);
|
|
+ if (ent) { /* event requested */
|
|
+ struct io_event *evp =
|
|
+ aio_ring_event(info, head, KM_USER1);
|
|
+ *ent = *evp;
|
|
+ head = (head + 1) % info->nr;
|
|
+ /* finish reading the event before updatng the head */
|
|
+ smp_mb();
|
|
+ ring->head = head;
|
|
+ ret = 1;
|
|
+ put_aio_ring_event(evp, KM_USER1);
|
|
+ } else /* only need to know availability */
|
|
+ ret = 1;
|
|
}
|
|
spin_unlock(&info->ring_lock);
|
|
|
|
@@ -1236,9 +1252,78 @@ static void io_destroy(struct kioctx *io
|
|
|
|
aio_cancel_all(ioctx);
|
|
wait_for_all_aios(ioctx);
|
|
+#ifdef CONFIG_EPOLL
|
|
+ /* forget the poll file, but it's up to the user to close it */
|
|
+ if (ioctx->file) {
|
|
+ ioctx->file->private_data = 0;
|
|
+ ioctx->file = 0;
|
|
+ }
|
|
+#endif
|
|
put_ioctx(ioctx); /* once for the lookup */
|
|
}
|
|
|
|
+#ifdef CONFIG_EPOLL
|
|
+
|
|
+static int aio_queue_fd_close(struct inode *inode, struct file *file)
|
|
+{
|
|
+ struct kioctx *ioctx = file->private_data;
|
|
+ if (ioctx) {
|
|
+ file->private_data = 0;
|
|
+ spin_lock_irq(&ioctx->ctx_lock);
|
|
+ ioctx->file = 0;
|
|
+ spin_unlock_irq(&ioctx->ctx_lock);
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static unsigned int aio_queue_fd_poll(struct file *file, poll_table *wait)
|
|
+{ unsigned int pollflags = 0;
|
|
+ struct kioctx *ioctx = file->private_data;
|
|
+
|
|
+ if (ioctx) {
|
|
+
|
|
+ spin_lock_irq(&ioctx->ctx_lock);
|
|
+ /* Insert inside our poll wait queue */
|
|
+ poll_wait(file, &ioctx->poll_wait, wait);
|
|
+
|
|
+ /* Check our condition */
|
|
+ if (aio_read_evt(ioctx, 0))
|
|
+ pollflags = POLLIN | POLLRDNORM;
|
|
+ spin_unlock_irq(&ioctx->ctx_lock);
|
|
+ }
|
|
+
|
|
+ return pollflags;
|
|
+}
|
|
+
|
|
+static struct file_operations aioq_fops = {
|
|
+ .release = aio_queue_fd_close,
|
|
+ .poll = aio_queue_fd_poll
|
|
+};
|
|
+
|
|
+/* make_aio_fd:
|
|
+ * Create a file descriptor that can be used to poll the event queue.
|
|
+ * Based and piggybacked on the excellent epoll code.
|
|
+ */
|
|
+
|
|
+static int make_aio_fd(struct kioctx *ioctx)
|
|
+{
|
|
+ int error, fd;
|
|
+ struct inode *inode;
|
|
+ struct file *file;
|
|
+
|
|
+ error = ep_getfd(&fd, &inode, &file, NULL, &aioq_fops);
|
|
+ if (error)
|
|
+ return error;
|
|
+
|
|
+ /* associate the file with the IO context */
|
|
+ file->private_data = ioctx;
|
|
+ ioctx->file = file;
|
|
+ init_waitqueue_head(&ioctx->poll_wait);
|
|
+ return fd;
|
|
+}
|
|
+#endif
|
|
+
|
|
+
|
|
/* sys_io_setup:
|
|
* Create an aio_context capable of receiving at least nr_events.
|
|
* ctxp must not point to an aio_context that already exists, and
|
|
@@ -1251,18 +1336,30 @@ static void io_destroy(struct kioctx *io
|
|
* resources are available. May fail with -EFAULT if an invalid
|
|
* pointer is passed for ctxp. Will fail with -ENOSYS if not
|
|
* implemented.
|
|
+ *
|
|
+ * To request a selectable fd, the user context has to be initialized
|
|
+ * to 1, instead of 0, and the return value is the fd.
|
|
+ * This keeps the system call compatible, since a non-zero value
|
|
+ * was not allowed so far.
|
|
*/
|
|
asmlinkage long sys_io_setup(unsigned nr_events, aio_context_t __user *ctxp)
|
|
{
|
|
struct kioctx *ioctx = NULL;
|
|
unsigned long ctx;
|
|
long ret;
|
|
+ int make_fd = 0;
|
|
|
|
ret = get_user(ctx, ctxp);
|
|
if (unlikely(ret))
|
|
goto out;
|
|
|
|
ret = -EINVAL;
|
|
+#ifdef CONFIG_EPOLL
|
|
+ if (ctx == 1) {
|
|
+ make_fd = 1;
|
|
+ ctx = 0;
|
|
+ }
|
|
+#endif
|
|
if (unlikely(ctx || nr_events == 0)) {
|
|
pr_debug("EINVAL: io_setup: ctx %lu nr_events %u\n",
|
|
ctx, nr_events);
|
|
@@ -1273,8 +1370,12 @@ asmlinkage long sys_io_setup(unsigned nr
|
|
ret = PTR_ERR(ioctx);
|
|
if (!IS_ERR(ioctx)) {
|
|
ret = put_user(ioctx->user_id, ctxp);
|
|
- if (!ret)
|
|
- return 0;
|
|
+#ifdef CONFIG_EPOLL
|
|
+ if (make_fd && ret >= 0)
|
|
+ ret = make_aio_fd(ioctx);
|
|
+#endif
|
|
+ if (ret >= 0)
|
|
+ return ret;
|
|
|
|
get_ioctx(ioctx); /* io_destroy() expects us to hold a ref */
|
|
io_destroy(ioctx);
|
|
diff -pruN ../orig-linux-2.6.16.29/fs/eventpoll.c ./fs/eventpoll.c
|
|
--- ../orig-linux-2.6.16.29/fs/eventpoll.c 2006-09-12 19:02:10.000000000 +0100
|
|
+++ ./fs/eventpoll.c 2006-09-19 13:58:49.000000000 +0100
|
|
@@ -235,8 +235,6 @@ struct ep_pqueue {
|
|
|
|
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 int ep_getfd(int *efd, struct inode **einode, struct file **efile,
|
|
- struct eventpoll *ep);
|
|
static int ep_alloc(struct eventpoll **pep);
|
|
static void ep_free(struct eventpoll *ep);
|
|
static struct epitem *ep_find(struct eventpoll *ep, struct file *file, int fd);
|
|
@@ -266,7 +264,7 @@ static int ep_events_transfer(struct eve
|
|
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 inode *ep_eventpoll_inode(struct file_operations *fops);
|
|
static struct super_block *eventpollfs_get_sb(struct file_system_type *fs_type,
|
|
int flags, const char *dev_name,
|
|
void *data);
|
|
@@ -525,7 +523,7 @@ asmlinkage long sys_epoll_create(int siz
|
|
* Creates all the items needed to setup an eventpoll file. That is,
|
|
* a file structure, and inode and a free file descriptor.
|
|
*/
|
|
- error = ep_getfd(&fd, &inode, &file, ep);
|
|
+ error = ep_getfd(&fd, &inode, &file, ep, &eventpoll_fops);
|
|
if (error)
|
|
goto eexit_2;
|
|
|
|
@@ -710,8 +708,8 @@ eexit_1:
|
|
/*
|
|
* Creates the file descriptor to be used by the epoll interface.
|
|
*/
|
|
-static int ep_getfd(int *efd, struct inode **einode, struct file **efile,
|
|
- struct eventpoll *ep)
|
|
+int ep_getfd(int *efd, struct inode **einode, struct file **efile,
|
|
+ struct eventpoll *ep, struct file_operations *fops)
|
|
{
|
|
struct qstr this;
|
|
char name[32];
|
|
@@ -727,7 +725,7 @@ static int ep_getfd(int *efd, struct ino
|
|
goto eexit_1;
|
|
|
|
/* Allocates an inode from the eventpoll file system */
|
|
- inode = ep_eventpoll_inode();
|
|
+ inode = ep_eventpoll_inode(fops);
|
|
error = PTR_ERR(inode);
|
|
if (IS_ERR(inode))
|
|
goto eexit_2;
|
|
@@ -758,7 +756,7 @@ static int ep_getfd(int *efd, struct ino
|
|
|
|
file->f_pos = 0;
|
|
file->f_flags = O_RDONLY;
|
|
- file->f_op = &eventpoll_fops;
|
|
+ file->f_op = fops;
|
|
file->f_mode = FMODE_READ;
|
|
file->f_version = 0;
|
|
file->private_data = ep;
|
|
@@ -1574,7 +1572,7 @@ static int eventpollfs_delete_dentry(str
|
|
}
|
|
|
|
|
|
-static struct inode *ep_eventpoll_inode(void)
|
|
+static struct inode *ep_eventpoll_inode(struct file_operations *fops)
|
|
{
|
|
int error = -ENOMEM;
|
|
struct inode *inode = new_inode(eventpoll_mnt->mnt_sb);
|
|
@@ -1582,7 +1580,7 @@ static struct inode *ep_eventpoll_inode(
|
|
if (!inode)
|
|
goto eexit_1;
|
|
|
|
- inode->i_fop = &eventpoll_fops;
|
|
+ inode->i_fop = fops;
|
|
|
|
/*
|
|
* Mark the inode dirty from the very beginning,
|
|
diff -pruN ../orig-linux-2.6.16.29/include/linux/aio.h ./include/linux/aio.h
|
|
--- ../orig-linux-2.6.16.29/include/linux/aio.h 2006-09-12 19:02:10.000000000 +0100
|
|
+++ ./include/linux/aio.h 2006-09-19 13:58:49.000000000 +0100
|
|
@@ -191,6 +191,11 @@ struct kioctx {
|
|
struct aio_ring_info ring_info;
|
|
|
|
struct work_struct wq;
|
|
+#ifdef CONFIG_EPOLL
|
|
+ // poll integration
|
|
+ wait_queue_head_t poll_wait;
|
|
+ struct file *file;
|
|
+#endif
|
|
};
|
|
|
|
/* prototypes */
|
|
diff -pruN ../orig-linux-2.6.16.29/include/linux/eventpoll.h ./include/linux/eventpoll.h
|
|
--- ../orig-linux-2.6.16.29/include/linux/eventpoll.h 2006-09-12 19:02:10.000000000 +0100
|
|
+++ ./include/linux/eventpoll.h 2006-09-19 13:58:49.000000000 +0100
|
|
@@ -86,6 +86,12 @@ static inline void eventpoll_release(str
|
|
}
|
|
|
|
|
|
+/*
|
|
+ * called by aio code to create fd that can poll the aio event queueQ
|
|
+ */
|
|
+struct eventpoll;
|
|
+int ep_getfd(int *efd, struct inode **einode, struct file **efile,
|
|
+ struct eventpoll *ep, struct file_operations *fops);
|
|
#else
|
|
|
|
static inline void eventpoll_init_file(struct file *file) {}
|