KVM: MMU: invalidate and flush on spte small->large page size change
[safe/jmp/linux-2.6] / fs / aio.c
index 8fa77e2..1ccf25c 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 <linux/compat.h>
 
 #include <asm/kmap_types.h>
 #include <asm/uaccess.h>
-#include <asm/mmu_context.h>
 
 #if DEBUG > 1
 #define dprintk                printk
@@ -60,6 +65,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 +86,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 +396,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 +460,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 +502,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 +525,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 +550,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,17 +558,22 @@ 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 final 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))) {
+       if (unlikely(!fput_atomic(req->ki_filp))) {
                get_ioctx(ctx);
                spin_lock(&fput_lock);
                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 +590,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 +603,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 +712,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 +865,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 +878,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 +980,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 +1001,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 
@@ -1413,13 +1385,22 @@ static ssize_t aio_fsync(struct kiocb *iocb)
        return ret;
 }
 
-static ssize_t aio_setup_vectored_rw(int type, struct kiocb *kiocb)
+static ssize_t aio_setup_vectored_rw(int type, struct kiocb *kiocb, bool compat)
 {
        ssize_t ret;
 
-       ret = rw_copy_check_uvector(type, (struct iovec __user *)kiocb->ki_buf,
-                                   kiocb->ki_nbytes, 1,
-                                   &kiocb->ki_inline_vec, &kiocb->ki_iovec);
+#ifdef CONFIG_COMPAT
+       if (compat)
+               ret = compat_rw_copy_check_uvector(type,
+                               (struct compat_iovec __user *)kiocb->ki_buf,
+                               kiocb->ki_nbytes, 1, &kiocb->ki_inline_vec,
+                               &kiocb->ki_iovec);
+       else
+#endif
+               ret = rw_copy_check_uvector(type,
+                               (struct iovec __user *)kiocb->ki_buf,
+                               kiocb->ki_nbytes, 1, &kiocb->ki_inline_vec,
+                               &kiocb->ki_iovec);
        if (ret < 0)
                goto out;
 
@@ -1449,7 +1430,7 @@ static ssize_t aio_setup_single_vector(struct kiocb *kiocb)
  *     Performs the initial checks and aio retry method
  *     setup for the kiocb at the time of io submission.
  */
-static ssize_t aio_setup_iocb(struct kiocb *kiocb)
+static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat)
 {
        struct file *file = kiocb->ki_filp;
        ssize_t ret = 0;
@@ -1498,7 +1479,7 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb)
                ret = security_file_permission(file, MAY_READ);
                if (unlikely(ret))
                        break;
-               ret = aio_setup_vectored_rw(READ, kiocb);
+               ret = aio_setup_vectored_rw(READ, kiocb, compat);
                if (ret)
                        break;
                ret = -EINVAL;
@@ -1512,7 +1493,7 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb)
                ret = security_file_permission(file, MAY_WRITE);
                if (unlikely(ret))
                        break;
-               ret = aio_setup_vectored_rw(WRITE, kiocb);
+               ret = aio_setup_vectored_rw(WRITE, kiocb, compat);
                if (ret)
                        break;
                ret = -EINVAL;
@@ -1540,33 +1521,45 @@ 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,
+                        bool compat)
 {
        struct kiocb *req;
        struct file *file;
@@ -1605,9 +1598,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,10 +1619,8 @@ 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);
+       ret = aio_setup_iocb(req, compat);
 
        if (ret)
                goto out_put_req;
@@ -1641,6 +1633,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;
 
@@ -1650,24 +1648,13 @@ out_put_req:
        return ret;
 }
 
-/* sys_io_submit:
- *     Queue the nr iocbs pointed to by iocbpp for processing.  Returns
- *     the number of iocbs queued.  May return -EINVAL if the aio_context
- *     specified by ctx_id is invalid, if nr is < 0, if the iocb at
- *     *iocbpp[0] is not properly initialized, if the operation specified
- *     is invalid for the file descriptor in the iocb.  May fail with
- *     -EFAULT if any of the data structures point to invalid data.  May
- *     fail with -EBADF if the file descriptor specified in the first
- *     iocb is invalid.  May fail with -EAGAIN if insufficient resources
- *     are available to queue any iocbs.  Will return 0 if nr is 0.  Will
- *     fail with -ENOSYS if not implemented.
- */
-SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr,
-               struct iocb __user * __user *, iocbpp)
+long do_io_submit(aio_context_t ctx_id, long nr,
+                 struct iocb __user *__user *iocbpp, bool compat)
 {
        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,15 +1686,34 @@ 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, compat);
                if (ret)
                        break;
        }
+       aio_batch_free(batch_hash);
 
        put_ioctx(ctx);
        return i ? i : ret;
 }
 
+/* sys_io_submit:
+ *     Queue the nr iocbs pointed to by iocbpp for processing.  Returns
+ *     the number of iocbs queued.  May return -EINVAL if the aio_context
+ *     specified by ctx_id is invalid, if nr is < 0, if the iocb at
+ *     *iocbpp[0] is not properly initialized, if the operation specified
+ *     is invalid for the file descriptor in the iocb.  May fail with
+ *     -EFAULT if any of the data structures point to invalid data.  May
+ *     fail with -EBADF if the file descriptor specified in the first
+ *     iocb is invalid.  May fail with -EAGAIN if insufficient resources
+ *     are available to queue any iocbs.  Will return 0 if nr is 0.  Will
+ *     fail with -ENOSYS if not implemented.
+ */
+SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr,
+               struct iocb __user * __user *, iocbpp)
+{
+       return do_io_submit(ctx_id, nr, iocbpp, 0);
+}
+
 /* lookup_kiocb
  *     Finds a given iocb for cancellation.
  */
@@ -1817,9 +1823,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);