Merge branch 'for-linus' of git://git390.marist.edu/pub/scm/linux-2.6
[safe/jmp/linux-2.6] / fs / aio.c
index cf0bef4..48fdeeb 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
@@ -35,6 +36,7 @@
 #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>
@@ -710,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);
 
@@ -865,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 */
@@ -885,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).
  */
@@ -1392,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;
 
@@ -1428,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;
@@ -1477,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;
@@ -1491,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;
@@ -1519,31 +1521,6 @@ 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)
-{
-       struct kiocb *iocb = container_of(wait, struct kiocb, ki_wait);
-
-       list_del_init(&wait->task_list);
-       kick_iocb(iocb);
-       return 1;
-}
-
 static void aio_batch_add(struct address_space *mapping,
                          struct hlist_head *batch_hash)
 {
@@ -1581,7 +1558,8 @@ static void aio_batch_free(struct hlist_head *batch_hash)
 }
 
 static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
-                        struct iocb *iocb, struct hlist_head *batch_hash)
+                        struct iocb *iocb, struct hlist_head *batch_hash,
+                        bool compat)
 {
        struct kiocb *req;
        struct file *file;
@@ -1641,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;
@@ -1672,20 +1648,8 @@ 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;
@@ -1722,7 +1686,7 @@ SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr,
                        break;
                }
 
-               ret = io_submit_one(ctx, user_iocb, &tmp, batch_hash);
+               ret = io_submit_one(ctx, user_iocb, &tmp, batch_hash, compat);
                if (ret)
                        break;
        }
@@ -1732,6 +1696,24 @@ SYSCALL_DEFINE3(io_submit, aio_context_t, ctx_id, long, nr,
        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.
  */