DM9000: Add ethtool control of msg_enable value
[safe/jmp/linux-2.6] / fs / aio.c
index 0b4ee0a..b74c567 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;
@@ -305,7 +303,7 @@ static void wait_for_all_aios(struct kioctx *ctx)
        set_task_state(tsk, TASK_UNINTERRUPTIBLE);
        while (ctx->reqs_active) {
                spin_unlock_irq(&ctx->ctx_lock);
-               schedule();
+               io_schedule();
                set_task_state(tsk, TASK_UNINTERRUPTIBLE);
                spin_lock_irq(&ctx->ctx_lock);
        }
@@ -319,13 +317,13 @@ out:
 /* wait_on_sync_kiocb:
  *     Waits on the given sync kiocb to complete.
  */
-ssize_t fastcall wait_on_sync_kiocb(struct kiocb *iocb)
+ssize_t wait_on_sync_kiocb(struct kiocb *iocb)
 {
        while (iocb->ki_users) {
                set_current_state(TASK_UNINTERRUPTIBLE);
                if (!iocb->ki_users)
                        break;
-               schedule();
+               io_schedule();
        }
        __set_current_state(TASK_RUNNING);
        return iocb->ki_user_data;
@@ -338,7 +336,7 @@ ssize_t fastcall wait_on_sync_kiocb(struct kiocb *iocb)
  * go away, they will call put_ioctx and release any pinned memory
  * associated with the request (held via struct page * references).
  */
-void fastcall exit_aio(struct mm_struct *mm)
+void exit_aio(struct mm_struct *mm)
 {
        struct kioctx *ctx = mm->ioctx_list;
        mm->ioctx_list = NULL;
@@ -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
@@ -368,14 +365,14 @@ void fastcall exit_aio(struct mm_struct *mm)
  *     Called when the last user of an aio context has gone away,
  *     and the struct needs to be freed.
  */
-void fastcall __put_ioctx(struct kioctx *ctx)
+void __put_ioctx(struct kioctx *ctx)
 {
        unsigned nr_events = ctx->max_reqs;
 
        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;
@@ -400,8 +397,7 @@ void fastcall __put_ioctx(struct kioctx *ctx)
  * This prevents races between the aio code path referencing the
  * req (after submitting it) and aio_complete() freeing the req.
  */
-static struct kiocb *FASTCALL(__aio_get_req(struct kioctx *ctx));
-static struct kiocb fastcall *__aio_get_req(struct kioctx *ctx)
+static struct kiocb *__aio_get_req(struct kioctx *ctx)
 {
        struct kiocb *req = NULL;
        struct aio_ring *ring;
@@ -421,6 +417,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 +459,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)
@@ -533,7 +532,7 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
  *     Returns true if this put was the last user of the kiocb,
  *     false if the request is still in use.
  */
-int fastcall aio_put_req(struct kiocb *req)
+int aio_put_req(struct kiocb *req)
 {
        struct kioctx *ctx = req->ki_ctx;
        int ret;
@@ -710,18 +709,9 @@ static ssize_t aio_run_iocb(struct kiocb *iocb)
 
        /*
         * Now we are all set to call the retry method in async
-        * context. By setting this thread's io_wait context
-        * to point to the wait queue entry inside the currently
-        * running iocb for the duration of the retry, we ensure
-        * that async notification wakeups are queued by the
-        * operation instead of blocking waits, and when notified,
-        * cause the iocb to be kicked for continuation (through
-        * the aio_wake_function callback).
+        * context.
         */
-       BUG_ON(current->io_wait != NULL);
-       current->io_wait = &iocb->ki_wait;
        ret = retry(iocb);
-       current->io_wait = NULL;
 
        if (ret != -EIOCBRETRY && ret != -EIOCBQUEUED) {
                BUG_ON(!list_empty(&iocb->ki_wait.task_list));
@@ -902,7 +892,7 @@ static void try_queue_kicked_iocb(struct kiocb *iocb)
  *      The retry is usually executed by aio workqueue
  *      threads (See aio_kick_handler).
  */
-void fastcall kick_iocb(struct kiocb *iocb)
+void kick_iocb(struct kiocb *iocb)
 {
        /* sync iocbs are easy: they can only ever be executing from a 
         * single context. */
@@ -921,7 +911,7 @@ EXPORT_SYMBOL(kick_iocb);
  *     Returns true if this is the last user of the request.  The 
  *     only other user of the request can be the cancellation code.
  */
-int fastcall aio_complete(struct kiocb *iocb, long res, long res2)
+int aio_complete(struct kiocb *iocb, long res, long res2)
 {
        struct kioctx   *ctx = iocb->ki_ctx;
        struct aio_ring_info    *info;
@@ -946,6 +936,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.
@@ -1162,7 +1160,12 @@ retry:
                        ret = 0;
                        if (to.timed_out)       /* Only check after read evt */
                                break;
-                       schedule();
+                       /* Try to only show up in io wait if there are ops
+                        *  in flight */
+                       if (ctx->reqs_active)
+                               io_schedule();
+                       else
+                               schedule();
                        if (signal_pending(tsk)) {
                                ret = -EINTR;
                                break;
@@ -1326,6 +1329,10 @@ static ssize_t aio_rw_vect_retry(struct kiocb *iocb)
                opcode = IOCB_CMD_PWRITEV;
        }
 
+       /* This matches the pread()/pwrite() logic */
+       if (iocb->ki_pos < 0)
+               return -EINVAL;
+
        do {
                ret = rw_op(iocb, &iocb->ki_iovec[iocb->ki_cur_seg],
                            iocb->ki_nr_segs - iocb->ki_cur_seg,
@@ -1344,6 +1351,13 @@ static ssize_t aio_rw_vect_retry(struct kiocb *iocb)
        if ((ret == 0) || (iocb->ki_left == 0))
                ret = iocb->ki_nbytes - iocb->ki_left;
 
+       /* If we managed to write some out we return that, rather than
+        * the eventual error. */
+       if (opcode == IOCB_CMD_PWRITEV
+           && ret < 0 && ret != -EIOCBQUEUED && ret != -EIOCBRETRY
+           && iocb->ki_nbytes - iocb->ki_left)
+               ret = iocb->ki_nbytes - iocb->ki_left;
+
        return ret;
 }
 
@@ -1500,10 +1514,7 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb)
  *     Simply triggers a retry of the operation via kick_iocb.
  *
  *     This callback is specified in the wait queue entry in
- *     a kiocb (current->io_wait points to this wait queue
- *     entry when an aio operation executes; it is used
- *     instead of a synchronous wait when an i/o blocking
- *     condition is encountered during aio).
+ *     a kiocb.
  *
  * Note:
  * This routine is executed with the wait queue lock held.
@@ -1522,7 +1533,7 @@ static int aio_wake_function(wait_queue_t *wait, unsigned mode,
        return 1;
 }
 
-int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
+int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
                         struct iocb *iocb)
 {
        struct kiocb *req;
@@ -1530,8 +1541,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,8 +1565,21 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
                fput(file);
                return -EAGAIN;
        }
-
        req->ki_filp = file;
+       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;
+               }
+       }
+
        ret = put_user(req->ki_key, &user_iocb->aio_key);
        if (unlikely(ret)) {
                dprintk("EFAULT: aio_key\n");