Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=9c3060bedd84144653a2ad7bea32389f65598d40
Commit:     9c3060bedd84144653a2ad7bea32389f65598d40
Parent:     fdb902b1225e1668315f38e96d2f439452c03a15
Author:     Davide Libenzi <[EMAIL PROTECTED]>
AuthorDate: Thu May 10 22:23:21 2007 -0700
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Fri May 11 08:29:37 2007 -0700

    signal/timer/event: KAIO eventfd support example
    
    This is an example about how to add eventfd support to the current KAIO 
code,
    in order to enable KAIO to post readiness events to a pollable fd (hence
    compatible with POSIX select/poll).  The KAIO code simply signals the 
eventfd
    fd when events are ready, and this triggers a POLLIN in the fd.  This patch
    uses a reserved for future use member of the struct iocb to pass an eventfd
    file descriptor, that KAIO will use to post events every time a request
    completes.  At that point, an aio_getevents() will return the completed 
result
    to a struct io_event.  I made a quick test program to verify the patch, and 
it
    runs fine here:
    
    http://www.xmailserver.org/eventfd-aio-test.c
    
    The test program uses poll(2), but it'd, of course, work with select and 
epoll
    too.
    
    This can allow to schedule both block I/O and other poll-able devices
    requests, and wait for results using select/poll/epoll.  In a typical
    scenario, an application would submit KAIO request using aio_submit(), and
    will also use epoll_ctl() on the whole other class of devices (that with the
    addition of signals, timers and user events, now it's pretty much complete),
    and then would:
    
        epoll_wait(...);
        for_each_event {
                if (curr_event_is_kaiofd) {
                        aio_getevents();
                        dispatch_aio_events();
                } else {
                        dispatch_epoll_event();
                }
        }
    
    Signed-off-by: Davide Libenzi <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 fs/aio.c                |   28 ++++++++++++++++++++++++++--
 include/linux/aio.h     |    6 ++++++
 include/linux/aio_abi.h |   18 +++++++++++++++++-
 3 files changed, 49 insertions(+), 3 deletions(-)

diff --git a/fs/aio.c b/fs/aio.c
index ac1c158..dbe699e 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -30,6 +30,7 @@
 #include <linux/highmem.h>
 #include <linux/workqueue.h>
 #include <linux/security.h>
+#include <linux/eventfd.h>
 
 #include <asm/kmap_types.h>
 #include <asm/uaccess.h>
@@ -417,6 +418,7 @@ static struct kiocb fastcall *__aio_get_req(struct kioctx 
*ctx)
        req->private = NULL;
        req->ki_iovec = NULL;
        INIT_LIST_HEAD(&req->ki_run_list);
+       req->ki_eventfd = ERR_PTR(-EINVAL);
 
        /* Check if the completion queue has enough free space to
         * accept an event from this io.
@@ -458,6 +460,8 @@ static inline void really_put_req(struct kioctx *ctx, 
struct kiocb *req)
 {
        assert_spin_locked(&ctx->ctx_lock);
 
+       if (!IS_ERR(req->ki_eventfd))
+               fput(req->ki_eventfd);
        if (req->ki_dtor)
                req->ki_dtor(req);
        if (req->ki_iovec != &req->ki_inline_vec)
@@ -942,6 +946,14 @@ int fastcall aio_complete(struct kiocb *iocb, long res, 
long res2)
                return 1;
        }
 
+       /*
+        * Check if the user asked us to deliver the result through an
+        * eventfd. The eventfd_signal() function is safe to be called
+        * from IRQ context.
+        */
+       if (!IS_ERR(iocb->ki_eventfd))
+               eventfd_signal(iocb->ki_eventfd, 1);
+
        info = &ctx->ring_info;
 
        /* add a completion event to the ring buffer.
@@ -1526,8 +1538,7 @@ int fastcall io_submit_one(struct kioctx *ctx, struct 
iocb __user *user_iocb,
        ssize_t ret;
 
        /* enforce forwards compatibility on users */
-       if (unlikely(iocb->aio_reserved1 || iocb->aio_reserved2 ||
-                    iocb->aio_reserved3)) {
+       if (unlikely(iocb->aio_reserved1 || iocb->aio_reserved2)) {
                pr_debug("EINVAL: io_submit: reserve field set\n");
                return -EINVAL;
        }
@@ -1551,6 +1562,19 @@ int fastcall io_submit_one(struct kioctx *ctx, struct 
iocb __user *user_iocb,
                fput(file);
                return -EAGAIN;
        }
+       if (iocb->aio_flags & IOCB_FLAG_RESFD) {
+               /*
+                * If the IOCB_FLAG_RESFD flag of aio_flags is set, get an
+                * instance of the file* now. The file descriptor must be
+                * an eventfd() fd, and will be signaled for each completed
+                * event using the eventfd_signal() function.
+                */
+               req->ki_eventfd = eventfd_fget((int) iocb->aio_resfd);
+               if (unlikely(IS_ERR(req->ki_eventfd))) {
+                       ret = PTR_ERR(req->ki_eventfd);
+                       goto out_put_req;
+               }
+       }
 
        req->ki_filp = file;
        ret = put_user(req->ki_key, &user_iocb->aio_key);
diff --git a/include/linux/aio.h b/include/linux/aio.h
index 43dc2eb..b903fc0 100644
--- a/include/linux/aio.h
+++ b/include/linux/aio.h
@@ -119,6 +119,12 @@ struct kiocb {
 
        struct list_head        ki_list;        /* the aio core uses this
                                                 * for cancellation */
+
+       /*
+        * If the aio_resfd field of the userspace iocb is not zero,
+        * this is the underlying file* to deliver event to.
+        */
+       struct file             *ki_eventfd;
 };
 
 #define is_sync_kiocb(iocb)    ((iocb)->ki_key == KIOCB_SYNC_KEY)
diff --git a/include/linux/aio_abi.h b/include/linux/aio_abi.h
index e3ca0a4..9e01729 100644
--- a/include/linux/aio_abi.h
+++ b/include/linux/aio_abi.h
@@ -45,6 +45,14 @@ enum {
        IOCB_CMD_PWRITEV = 8,
 };
 
+/*
+ * Valid flags for the "aio_flags" member of the "struct iocb".
+ *
+ * IOCB_FLAG_RESFD - Set if the "aio_resfd" member of the "struct iocb"
+ *                   is valid.
+ */
+#define IOCB_FLAG_RESFD                (1 << 0)
+
 /* read() from /dev/aio returns these structures. */
 struct io_event {
        __u64           data;           /* the data field from the iocb */
@@ -84,7 +92,15 @@ struct iocb {
 
        /* extra parameters */
        __u64   aio_reserved2;  /* TODO: use this for a (struct sigevent *) */
-       __u64   aio_reserved3;
+
+       /* flags for the "struct iocb" */
+       __u32   aio_flags;
+
+       /*
+        * if the IOCB_FLAG_RESFD flag of "aio_flags" is set, this is an
+        * eventfd to signal AIO readiness to
+        */
+       __u32   aio_resfd;
 }; /* 64 bytes */
 
 #undef IFBIG
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to