- patches.arch/x86_mce_intel_decode_physical_address.patch:
[linux-flexiantxendom0-3.2.10.git] / fs / aio.c
index f2979e2..1ccf25c 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
 #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>
 
-#ifdef CONFIG_EPOLL
-#include <linux/poll.h>
-#include <linux/anon_inodes.h>
-#endif
-
 #if DEBUG > 1
 #define dprintk                printk
 #else
@@ -531,7 +527,7 @@ static void aio_fput_routine(struct work_struct *data)
 
                /* Complete the fput(s) */
                if (req->ki_filp != NULL)
-                       __fput(req->ki_filp);
+                       fput(req->ki_filp);
 
                /* Link the iocb into the context's free list */
                spin_lock_irq(&ctx->ctx_lock);
@@ -564,11 +560,11 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
 
        /*
         * Try to optimize the aio and eventfd file* puts, by avoiding to
-        * schedule work in case it is not __fput() time. In normal cases,
+        * 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);
@@ -1002,11 +998,6 @@ put_rq:
        if (waitqueue_active(&ctx->wait))
                wake_up(&ctx->wait);
 
-#ifdef CONFIG_EPOLL
-       if (ctx->file && waitqueue_active(&ctx->poll_wait))
-               wake_up(&ctx->poll_wait);
-#endif
-
        spin_unlock_irqrestore(&ctx->ctx_lock, flags);
        return ret;
 }
@@ -1015,8 +1006,6 @@ EXPORT_SYMBOL(aio_complete);
 /* aio_read_evt
  *     Pull an event off of the ioctx's event ring.  Returns the number of 
  *     events fetched (0 or 1 ;-)
- *     If ent parameter is 0, just returns the number of events that would
- *     be fetched.
  *     FIXME: make this use cmpxchg.
  *     TODO: make the ringbuffer user mmap()able (requires FIXME).
  */
@@ -1039,18 +1028,13 @@ static int aio_read_evt(struct kioctx *ioctx, struct io_event *ent)
 
        head = ring->head % info->nr;
        if (head != ring->tail) {
-               if (ent) { /* event requested */
-                       struct io_event *evp =
-                               aio_ring_event(info, head, KM_USER1);
-                       *ent = *evp;
-                       head = (head + 1) % info->nr;
-                       /* finish reading the event before updatng the head */
-                       smp_mb();
-                       ring->head = head;
-                       ret = 1;
-                       put_aio_ring_event(evp, KM_USER1);
-               } else /* only need to know availability */
-                       ret = 1;
+               struct io_event *evp = aio_ring_event(info, head, KM_USER1);
+               *ent = *evp;
+               head = (head + 1) % info->nr;
+               smp_mb(); /* finish reading the event before updatng the head */
+               ring->head = head;
+               ret = 1;
+               put_aio_ring_event(evp, KM_USER1);
        }
        spin_unlock(&info->ring_lock);
 
@@ -1235,14 +1219,6 @@ static void io_destroy(struct kioctx *ioctx)
 
        aio_cancel_all(ioctx);
        wait_for_all_aios(ioctx);
-#ifdef CONFIG_EPOLL
-       /* forget the poll file, but it's up to the user to close it */
-       if (ioctx->file) {
-               fput(ioctx->file);
-               ioctx->file->private_data = 0;
-               ioctx->file = 0;
-       }
-#endif
 
        /*
         * Wake up any waiters.  The setting of ctx->dead must be seen
@@ -1253,70 +1229,6 @@ static void io_destroy(struct kioctx *ioctx)
        put_ioctx(ioctx);       /* once for the lookup */
 }
 
-#ifdef CONFIG_EPOLL
-
-static int aio_queue_fd_close(struct inode *inode, struct file *file)
-{
-       struct kioctx *ioctx = file->private_data;
-       if (ioctx) {
-               file->private_data = 0;
-               spin_lock_irq(&ioctx->ctx_lock);
-               ioctx->file = 0;
-               spin_unlock_irq(&ioctx->ctx_lock);
-               fput(file);
-       }
-       return 0;
-}
-
-static unsigned int aio_queue_fd_poll(struct file *file, poll_table *wait)
-{      unsigned int pollflags = 0;
-       struct kioctx *ioctx = file->private_data;
-
-       if (ioctx) {
-
-               spin_lock_irq(&ioctx->ctx_lock);
-               /* Insert inside our poll wait queue */
-               poll_wait(file, &ioctx->poll_wait, wait);
-
-               /* Check our condition */
-               if (aio_read_evt(ioctx, 0))
-                       pollflags = POLLIN | POLLRDNORM;
-               spin_unlock_irq(&ioctx->ctx_lock);
-       }
-
-       return pollflags;
-}
-
-static const struct file_operations aioq_fops = {
-       .release        = aio_queue_fd_close,
-       .poll           = aio_queue_fd_poll
-};
-
-/* make_aio_fd:
- *  Create a file descriptor that can be used to poll the event queue.
- *  Based on the excellent epoll code.
- */
-
-static int make_aio_fd(struct kioctx *ioctx)
-{
-       int fd;
-       struct file *file;
-
-       fd = anon_inode_getfd("[aioq]", &aioq_fops, ioctx, 0);
-       if (fd < 0)
-               return fd;
-
-       /* associate the file with the IO context */
-       file = fget(fd);
-       if (!file)
-               return -EBADF;
-       file->private_data = ioctx;
-       ioctx->file = file;
-       init_waitqueue_head(&ioctx->poll_wait);
-       return fd;
-}
-#endif
-
 /* sys_io_setup:
  *     Create an aio_context capable of receiving at least nr_events.
  *     ctxp must not point to an aio_context that already exists, and
@@ -1329,30 +1241,18 @@ static int make_aio_fd(struct kioctx *ioctx)
  *     resources are available.  May fail with -EFAULT if an invalid
  *     pointer is passed for ctxp.  Will fail with -ENOSYS if not
  *     implemented.
- *
- *     To request a selectable fd, the user context has to be initialized
- *     to 1, instead of 0, and the return value is the fd.
- *     This keeps the system call compatible, since a non-zero value
- *     was not allowed so far.
  */
 SYSCALL_DEFINE2(io_setup, unsigned, nr_events, aio_context_t __user *, ctxp)
 {
        struct kioctx *ioctx = NULL;
        unsigned long ctx;
        long ret;
-       int make_fd = 0;
 
        ret = get_user(ctx, ctxp);
        if (unlikely(ret))
                goto out;
 
        ret = -EINVAL;
-#ifdef CONFIG_EPOLL
-       if (ctx == 1) {
-               make_fd = 1;
-               ctx = 0;
-       }
-#endif
        if (unlikely(ctx || nr_events == 0)) {
                pr_debug("EINVAL: io_setup: ctx %lu nr_events %u\n",
                         ctx, nr_events);
@@ -1363,12 +1263,8 @@ SYSCALL_DEFINE2(io_setup, unsigned, nr_events, aio_context_t __user *, ctxp)
        ret = PTR_ERR(ioctx);
        if (!IS_ERR(ioctx)) {
                ret = put_user(ioctx->user_id, ctxp);
-#ifdef CONFIG_EPOLL
-               if (make_fd && ret >= 0)
-                       ret = make_aio_fd(ioctx);
-#endif
-               if (ret >= 0)
-                       return ret;
+               if (!ret)
+                       return 0;
 
                get_ioctx(ioctx); /* io_destroy() expects us to hold a ref */
                io_destroy(ioctx);
@@ -1489,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;
 
@@ -1525,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;
@@ -1574,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;
@@ -1588,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;
@@ -1653,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;
@@ -1714,7 +1620,7 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
        req->ki_left = req->ki_nbytes = iocb->aio_nbytes;
        req->ki_opcode = iocb->aio_lio_opcode;
 
-       ret = aio_setup_iocb(req);
+       ret = aio_setup_iocb(req, compat);
 
        if (ret)
                goto out_put_req;
@@ -1742,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;
@@ -1792,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;
        }
@@ -1802,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.
  */