mmc: s3c6410: enable ADMA feature in 6410 sdhci controller
[safe/jmp/linux-2.6] / fs / aio.c
index 8fa77e2..1cf12b3 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -15,6 +15,7 @@
 #include <linux/aio_abi.h>
 #include <linux/module.h>
 #include <linux/syscalls.h>
+#include <linux/backing-dev.h>
 #include <linux/uio.h>
 
 #define DEBUG 0
@@ -24,6 +25,7 @@
 #include <linux/file.h>
 #include <linux/mm.h>
 #include <linux/mman.h>
+#include <linux/mmu_context.h>
 #include <linux/slab.h>
 #include <linux/timer.h>
 #include <linux/aio.h>
 #include <linux/workqueue.h>
 #include <linux/security.h>
 #include <linux/eventfd.h>
+#include <linux/blkdev.h>
+#include <linux/mempool.h>
+#include <linux/hash.h>
 
 #include <asm/kmap_types.h>
 #include <asm/uaccess.h>
-#include <asm/mmu_context.h>
 
 #if DEBUG > 1
 #define dprintk                printk
@@ -60,6 +64,14 @@ static DECLARE_WORK(fput_work, aio_fput_routine);
 static DEFINE_SPINLOCK(fput_lock);
 static LIST_HEAD(fput_head);
 
+#define AIO_BATCH_HASH_BITS    3 /* allocated on-stack, so don't go crazy */
+#define AIO_BATCH_HASH_SIZE    (1 << AIO_BATCH_HASH_BITS)
+struct aio_batch_entry {
+       struct hlist_node list;
+       struct address_space *mapping;
+};
+mempool_t *abe_pool;
+
 static void aio_kick_handler(struct work_struct *);
 static void aio_queue_work(struct kioctx *);
 
@@ -73,11 +85,14 @@ static int __init aio_setup(void)
        kioctx_cachep = KMEM_CACHE(kioctx,SLAB_HWCACHE_ALIGN|SLAB_PANIC);
 
        aio_wq = create_workqueue("aio");
+       abe_pool = mempool_create_kmalloc_pool(1, sizeof(struct aio_batch_entry));
+       BUG_ON(!abe_pool);
 
        pr_debug("aio_setup: sizeof(struct page) = %d\n", (int)sizeof(struct page));
 
        return 0;
 }
+__initcall(aio_setup);
 
 static void aio_free_ring(struct kioctx *ctx)
 {
@@ -380,6 +395,7 @@ ssize_t wait_on_sync_kiocb(struct kiocb *iocb)
        __set_current_state(TASK_RUNNING);
        return iocb->ki_user_data;
 }
+EXPORT_SYMBOL(wait_on_sync_kiocb);
 
 /* exit_aio: called when the last user of mm goes away.  At this point, 
  * there is no way for any new requests to be submited or any of the 
@@ -443,7 +459,7 @@ static struct kiocb *__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);
+       req->ki_eventfd = NULL;
 
        /* Check if the completion queue has enough free space to
         * accept an event from this io.
@@ -485,8 +501,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_eventfd != NULL)
+               eventfd_ctx_put(req->ki_eventfd);
        if (req->ki_dtor)
                req->ki_dtor(req);
        if (req->ki_iovec != &req->ki_inline_vec)
@@ -508,8 +524,9 @@ static void aio_fput_routine(struct work_struct *data)
                list_del(&req->ki_list);
                spin_unlock_irq(&fput_lock);
 
-               /* Complete the fput */
-               __fput(req->ki_filp);
+               /* Complete the fput(s) */
+               if (req->ki_filp != NULL)
+                       __fput(req->ki_filp);
 
                /* Link the iocb into the context's free list */
                spin_lock_irq(&ctx->ctx_lock);
@@ -532,7 +549,7 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
 
        assert_spin_locked(&ctx->ctx_lock);
 
-       req->ki_users --;
+       req->ki_users--;
        BUG_ON(req->ki_users < 0);
        if (likely(req->ki_users))
                return 0;
@@ -540,8 +557,11 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
        req->ki_cancel = NULL;
        req->ki_retry = NULL;
 
-       /* Must be done under the lock to serialise against cancellation.
-        * Call this aio_fput as it duplicates fput via the fput_work.
+       /*
+        * Try to optimize the aio and eventfd file* puts, by avoiding to
+        * schedule work in case it is not __fput() time. In normal cases,
+        * we would not be holding the last reference to the file*, so
+        * this function will be executed w/out any aio kthread wakeup.
         */
        if (unlikely(atomic_long_dec_and_test(&req->ki_filp->f_count))) {
                get_ioctx(ctx);
@@ -549,8 +569,10 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
                list_add(&req->ki_list, &fput_head);
                spin_unlock(&fput_lock);
                queue_work(aio_wq, &fput_work);
-       } else
+       } else {
+               req->ki_filp = NULL;
                really_put_req(ctx, req);
+       }
        return 1;
 }
 
@@ -567,11 +589,12 @@ int aio_put_req(struct kiocb *req)
        spin_unlock_irq(&ctx->ctx_lock);
        return ret;
 }
+EXPORT_SYMBOL(aio_put_req);
 
 static struct kioctx *lookup_ioctx(unsigned long ctx_id)
 {
        struct mm_struct *mm = current->mm;
-       struct kioctx *ctx = NULL;
+       struct kioctx *ctx, *ret = NULL;
        struct hlist_node *n;
 
        rcu_read_lock();
@@ -579,57 +602,13 @@ static struct kioctx *lookup_ioctx(unsigned long ctx_id)
        hlist_for_each_entry_rcu(ctx, n, &mm->ioctx_list, list) {
                if (ctx->user_id == ctx_id && !ctx->dead) {
                        get_ioctx(ctx);
+                       ret = ctx;
                        break;
                }
        }
 
        rcu_read_unlock();
-       return ctx;
-}
-
-/*
- * use_mm
- *     Makes the calling kernel thread take on the specified
- *     mm context.
- *     Called by the retry thread execute retries within the
- *     iocb issuer's mm context, so that copy_from/to_user
- *     operations work seamlessly for aio.
- *     (Note: this routine is intended to be called only
- *     from a kernel thread context)
- */
-static void use_mm(struct mm_struct *mm)
-{
-       struct mm_struct *active_mm;
-       struct task_struct *tsk = current;
-
-       task_lock(tsk);
-       active_mm = tsk->active_mm;
-       atomic_inc(&mm->mm_count);
-       tsk->mm = mm;
-       tsk->active_mm = mm;
-       switch_mm(active_mm, mm, tsk);
-       task_unlock(tsk);
-
-       mmdrop(active_mm);
-}
-
-/*
- * unuse_mm
- *     Reverses the effect of use_mm, i.e. releases the
- *     specified mm context which was earlier taken on
- *     by the calling kernel thread
- *     (Note: this routine is intended to be called only
- *     from a kernel thread context)
- */
-static void unuse_mm(struct mm_struct *mm)
-{
-       struct task_struct *tsk = current;
-
-       task_lock(tsk);
-       tsk->mm = NULL;
-       /* active_mm is still 'mm' */
-       enter_lazy_tlb(mm, tsk);
-       task_unlock(tsk);
+       return ret;
 }
 
 /*
@@ -732,10 +711,8 @@ static ssize_t aio_run_iocb(struct kiocb *iocb)
         */
        ret = retry(iocb);
 
-       if (ret != -EIOCBRETRY && ret != -EIOCBQUEUED) {
-               BUG_ON(!list_empty(&iocb->ki_wait.task_list));
+       if (ret != -EIOCBRETRY && ret != -EIOCBQUEUED)
                aio_complete(iocb, ret, 0);
-       }
 out:
        spin_lock_irq(&ctx->ctx_lock);
 
@@ -887,13 +864,6 @@ static void try_queue_kicked_iocb(struct kiocb *iocb)
        unsigned long flags;
        int run = 0;
 
-       /* We're supposed to be the only path putting the iocb back on the run
-        * list.  If we find that the iocb is *back* on a wait queue already
-        * than retry has happened before we could queue the iocb.  This also
-        * means that the retry could have completed and freed our iocb, no
-        * good. */
-       BUG_ON((!list_empty(&iocb->ki_wait.task_list)));
-
        spin_lock_irqsave(&ctx->ctx_lock, flags);
        /* set this inside the lock so that we can't race with aio_run_iocb()
         * testing it and putting the iocb on the run list under the lock */
@@ -907,7 +877,7 @@ static void try_queue_kicked_iocb(struct kiocb *iocb)
 /*
  * kick_iocb:
  *      Called typically from a wait queue callback context
- *      (aio_wake_function) to trigger a retry of the iocb.
+ *      to trigger a retry of the iocb.
  *      The retry is usually executed by aio workqueue
  *      threads (See aio_kick_handler).
  */
@@ -1009,7 +979,7 @@ int aio_complete(struct kiocb *iocb, long res, long res2)
         * eventfd. The eventfd_signal() function is safe to be called
         * from IRQ context.
         */
-       if (!IS_ERR(iocb->ki_eventfd))
+       if (iocb->ki_eventfd != NULL)
                eventfd_signal(iocb->ki_eventfd, 1);
 
 put_rq:
@@ -1030,6 +1000,7 @@ put_rq:
        spin_unlock_irqrestore(&ctx->ctx_lock, flags);
        return ret;
 }
+EXPORT_SYMBOL(aio_complete);
 
 /* aio_read_evt
  *     Pull an event off of the ioctx's event ring.  Returns the number of 
@@ -1540,33 +1511,44 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb)
        return 0;
 }
 
-/*
- * aio_wake_function:
- *     wait queue callback function for aio notification,
- *     Simply triggers a retry of the operation via kick_iocb.
- *
- *     This callback is specified in the wait queue entry in
- *     a kiocb.
- *
- * Note:
- * This routine is executed with the wait queue lock held.
- * Since kick_iocb acquires iocb->ctx->ctx_lock, it nests
- * the ioctx lock inside the wait queue lock. This is safe
- * because this callback isn't used for wait queues which
- * are nested inside ioctx lock (i.e. ctx->wait)
- */
-static int aio_wake_function(wait_queue_t *wait, unsigned mode,
-                            int sync, void *key)
+static void aio_batch_add(struct address_space *mapping,
+                         struct hlist_head *batch_hash)
 {
-       struct kiocb *iocb = container_of(wait, struct kiocb, ki_wait);
+       struct aio_batch_entry *abe;
+       struct hlist_node *pos;
+       unsigned bucket;
+
+       bucket = hash_ptr(mapping, AIO_BATCH_HASH_BITS);
+       hlist_for_each_entry(abe, pos, &batch_hash[bucket], list) {
+               if (abe->mapping == mapping)
+                       return;
+       }
 
-       list_del_init(&wait->task_list);
-       kick_iocb(iocb);
-       return 1;
+       abe = mempool_alloc(abe_pool, GFP_KERNEL);
+       BUG_ON(!igrab(mapping->host));
+       abe->mapping = mapping;
+       hlist_add_head(&abe->list, &batch_hash[bucket]);
+       return;
+}
+
+static void aio_batch_free(struct hlist_head *batch_hash)
+{
+       struct aio_batch_entry *abe;
+       struct hlist_node *pos, *n;
+       int i;
+
+       for (i = 0; i < AIO_BATCH_HASH_SIZE; i++) {
+               hlist_for_each_entry_safe(abe, pos, n, &batch_hash[i], list) {
+                       blk_run_address_space(abe->mapping);
+                       iput(abe->mapping->host);
+                       hlist_del(&abe->list);
+                       mempool_free(abe, abe_pool);
+               }
+       }
 }
 
 static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
-                        struct iocb *iocb)
+                        struct iocb *iocb, struct hlist_head *batch_hash)
 {
        struct kiocb *req;
        struct file *file;
@@ -1605,9 +1587,10 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
                 * 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);
+               req->ki_eventfd = eventfd_ctx_fdget((int) iocb->aio_resfd);
                if (IS_ERR(req->ki_eventfd)) {
                        ret = PTR_ERR(req->ki_eventfd);
+                       req->ki_eventfd = NULL;
                        goto out_put_req;
                }
        }
@@ -1625,8 +1608,6 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
        req->ki_buf = (char __user *)(unsigned long)iocb->aio_buf;
        req->ki_left = req->ki_nbytes = iocb->aio_nbytes;
        req->ki_opcode = iocb->aio_lio_opcode;
-       init_waitqueue_func_entry(&req->ki_wait, aio_wake_function);
-       INIT_LIST_HEAD(&req->ki_wait.task_list);
 
        ret = aio_setup_iocb(req);
 
@@ -1641,6 +1622,12 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
                        ;
        }
        spin_unlock_irq(&ctx->ctx_lock);
+       if (req->ki_opcode == IOCB_CMD_PREAD ||
+           req->ki_opcode == IOCB_CMD_PREADV ||
+           req->ki_opcode == IOCB_CMD_PWRITE ||
+           req->ki_opcode == IOCB_CMD_PWRITEV)
+               aio_batch_add(file->f_mapping, batch_hash);
+
        aio_put_req(req);       /* drop extra ref to req */
        return 0;
 
@@ -1668,6 +1655,7 @@ SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr,
        struct kioctx *ctx;
        long ret = 0;
        int i;
+       struct hlist_head batch_hash[AIO_BATCH_HASH_SIZE] = { { 0, }, };
 
        if (unlikely(nr < 0))
                return -EINVAL;
@@ -1699,10 +1687,11 @@ SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr,
                        break;
                }
 
-               ret = io_submit_one(ctx, user_iocb, &tmp);
+               ret = io_submit_one(ctx, user_iocb, &tmp, batch_hash);
                if (ret)
                        break;
        }
+       aio_batch_free(batch_hash);
 
        put_ioctx(ctx);
        return i ? i : ret;
@@ -1817,9 +1806,3 @@ SYSCALL_DEFINE5(io_getevents, aio_context_t, ctx_id,
        asmlinkage_protect(5, ret, ctx_id, min_nr, nr, events, timeout);
        return ret;
 }
-
-__initcall(aio_setup);
-
-EXPORT_SYMBOL(aio_complete);
-EXPORT_SYMBOL(aio_put_req);
-EXPORT_SYMBOL(wait_on_sync_kiocb);