Merge git://git.linux-xtensa.org/kernel/xtensa-feed
[pandora-kernel.git] / fs / aio.c
index 0b4ee0a..dbe699e 100644 (file)
--- 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>
@@ -68,10 +69,8 @@ static void aio_queue_work(struct kioctx *);
  */
 static int __init aio_setup(void)
 {
-       kiocb_cachep = kmem_cache_create("kiocb", sizeof(struct kiocb),
-                               0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
-       kioctx_cachep = kmem_cache_create("kioctx", sizeof(struct kioctx),
-                               0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL, NULL);
+       kiocb_cachep = KMEM_CACHE(kiocb, SLAB_HWCACHE_ALIGN|SLAB_PANIC);
+       kioctx_cachep = KMEM_CACHE(kioctx,SLAB_HWCACHE_ALIGN|SLAB_PANIC);
 
        aio_wq = create_workqueue("aio");
 
@@ -136,7 +135,6 @@ static int aio_setup_ring(struct kioctx *ctx)
                                  0);
        if (IS_ERR((void *)info->mmap_base)) {
                up_write(&ctx->mm->mmap_sem);
-               printk("mmap err: %ld\n", -info->mmap_base);
                info->mmap_size = 0;
                aio_free_ring(ctx);
                return -EAGAIN;
@@ -349,10 +347,9 @@ void fastcall exit_aio(struct mm_struct *mm)
 
                wait_for_all_aios(ctx);
                /*
-                * this is an overkill, but ensures we don't leave
-                * the ctx on the aio_wq
+                * Ensure we don't leave the ctx on the aio_wq
                 */
-               flush_workqueue(aio_wq);
+               cancel_work_sync(&ctx->wq.work);
 
                if (1 != atomic_read(&ctx->users))
                        printk(KERN_DEBUG
@@ -375,7 +372,7 @@ void fastcall __put_ioctx(struct kioctx *ctx)
        BUG_ON(ctx->reqs_active);
 
        cancel_delayed_work(&ctx->wq);
-       flush_workqueue(aio_wq);
+       cancel_work_sync(&ctx->wq.work);
        aio_free_ring(ctx);
        mmdrop(ctx->mm);
        ctx->mm = NULL;
@@ -421,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.
@@ -462,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)
@@ -946,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.
@@ -1530,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;
        }
@@ -1555,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);