Merge master.kernel.org:/home/rmk/linux-2.6-arm
[pandora-kernel.git] / fs / aio.c
index a82214d..d6b1551 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -29,6 +29,7 @@
 #include <linux/highmem.h>
 #include <linux/workqueue.h>
 #include <linux/security.h>
+#include <linux/rcuref.h>
 
 #include <asm/kmap_types.h>
 #include <asm/uaccess.h>
@@ -40,9 +41,6 @@
 #define dprintk(x...)  do { ; } while (0)
 #endif
 
-static long aio_run = 0; /* for testing only */
-static long aio_wakeups = 0; /* for testing only */
-
 /*------ sysctl variables----*/
 atomic_t aio_nr = ATOMIC_INIT(0);      /* current system wide number of aio requests */
 unsigned aio_max_nr = 0x10000; /* system wide maximum number of aio requests */
@@ -61,6 +59,7 @@ static DEFINE_SPINLOCK(fput_lock);
 static LIST_HEAD(fput_head);
 
 static void aio_kick_handler(void *);
+static void aio_queue_work(struct kioctx *);
 
 /* aio_setup
  *     Creates the slab caches used by the aio routines, panic on
@@ -405,7 +404,6 @@ static struct kiocb fastcall *__aio_get_req(struct kioctx *ctx)
        req->ki_ctx = ctx;
        req->ki_cancel = NULL;
        req->ki_retry = NULL;
-       req->ki_obj.user = NULL;
        req->ki_dtor = NULL;
        req->private = NULL;
        INIT_LIST_HEAD(&req->ki_run_list);
@@ -451,11 +449,6 @@ static inline void really_put_req(struct kioctx *ctx, struct kiocb *req)
 {
        if (req->ki_dtor)
                req->ki_dtor(req);
-       req->ki_ctx = NULL;
-       req->ki_filp = NULL;
-       req->ki_obj.user = NULL;
-       req->ki_dtor = NULL;
-       req->private = NULL;
        kmem_cache_free(kiocb_cachep, req);
        ctx->reqs_active--;
 
@@ -507,7 +500,7 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
        /* Must be done under the lock to serialise against cancellation.
         * Call this aio_fput as it duplicates fput via the fput_work.
         */
-       if (unlikely(atomic_dec_and_test(&req->ki_filp->f_count))) {
+       if (unlikely(rcuref_dec_and_test(&req->ki_filp->f_count))) {
                get_ioctx(ctx);
                spin_lock(&fput_lock);
                list_add(&req->ki_list, &fput_head);
@@ -554,6 +547,25 @@ struct kioctx *lookup_ioctx(unsigned long ctx_id)
        return ioctx;
 }
 
+static int lock_kiocb_action(void *param)
+{
+       schedule();
+       return 0;
+}
+
+static inline void lock_kiocb(struct kiocb *iocb)
+{
+       wait_on_bit_lock(&iocb->ki_flags, KIF_LOCKED, lock_kiocb_action,
+                        TASK_UNINTERRUPTIBLE);
+}
+
+static inline void unlock_kiocb(struct kiocb *iocb)
+{
+       kiocbClearLocked(iocb);
+       smp_mb__after_clear_bit();
+       wake_up_bit(&iocb->ki_flags, KIF_LOCKED);
+}
+
 /*
  * use_mm
  *     Makes the calling kernel thread take on the specified
@@ -575,6 +587,10 @@ static void use_mm(struct mm_struct *mm)
        atomic_inc(&mm->mm_count);
        tsk->mm = mm;
        tsk->active_mm = mm;
+       /*
+        * Note that on UML this *requires* PF_BORROWED_MM to be set, otherwise
+        * it won't work. Update it accordingly if you change it here
+        */
        activate_mm(active_mm, mm);
        task_unlock(tsk);
 
@@ -623,7 +639,6 @@ static inline int __queue_kicked_iocb(struct kiocb *iocb)
        if (list_empty(&iocb->ki_run_list)) {
                list_add_tail(&iocb->ki_run_list,
                        &ctx->run_list);
-               iocb->ki_queued++;
                return 1;
        }
        return 0;
@@ -664,10 +679,8 @@ static ssize_t aio_run_iocb(struct kiocb *iocb)
        }
 
        if (!(iocb->ki_retried & 0xff)) {
-               pr_debug("%ld retry: %d of %d (kick %ld, Q %ld run %ld, wake %ld)\n",
-                       iocb->ki_retried,
-                       iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes,
-                       iocb->ki_kicked, iocb->ki_queued, aio_run, aio_wakeups);
+               pr_debug("%ld retry: %d of %d\n", iocb->ki_retried,
+                       iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes);
        }
 
        if (!(retry = iocb->ki_retry)) {
@@ -728,19 +741,9 @@ static ssize_t aio_run_iocb(struct kiocb *iocb)
        ret = retry(iocb);
        current->io_wait = NULL;
 
-       if (-EIOCBRETRY != ret) {
-               if (-EIOCBQUEUED != ret) {
-                       BUG_ON(!list_empty(&iocb->ki_wait.task_list));
-                       aio_complete(iocb, ret, 0);
-                       /* must not access the iocb after this */
-               }
-       } else {
-               /*
-                * Issue an additional retry to avoid waiting forever if
-                * no waits were queued (e.g. in case of a short read).
-                */
-               if (list_empty(&iocb->ki_wait.task_list))
-                       kiocbSetKicked(iocb);
+       if (ret != -EIOCBRETRY && ret != -EIOCBQUEUED) {
+               BUG_ON(!list_empty(&iocb->ki_wait.task_list));
+               aio_complete(iocb, ret, 0);
        }
 out:
        spin_lock_irq(&ctx->ctx_lock);
@@ -759,6 +762,14 @@ out:
                 * has already been kicked */
                if (kiocbIsKicked(iocb)) {
                        __queue_kicked_iocb(iocb);
+
+                       /*
+                        * __queue_kicked_iocb will always return 1 here, because
+                        * iocb->ki_run_list is empty at this point so it should
+                        * be safe to unconditionally queue the context into the
+                        * work queue.
+                        */
+                       aio_queue_work(ctx);
                }
        }
        return ret;
@@ -774,7 +785,6 @@ out:
 static int __aio_run_iocbs(struct kioctx *ctx)
 {
        struct kiocb *iocb;
-       int count = 0;
        LIST_HEAD(run_list);
 
        list_splice_init(&ctx->run_list, &run_list);
@@ -786,12 +796,12 @@ static int __aio_run_iocbs(struct kioctx *ctx)
                 * Hold an extra reference while retrying i/o.
                 */
                iocb->ki_users++;       /* grab extra reference */
+               lock_kiocb(iocb);
                aio_run_iocb(iocb);
+               unlock_kiocb(iocb);
                if (__aio_put_req(ctx, iocb))  /* drop extra ref */
                        put_ioctx(ctx);
-               count++;
        }
-       aio_run++;
        if (!list_empty(&ctx->run_list))
                return 1;
        return 0;
@@ -879,21 +889,27 @@ static void aio_kick_handler(void *data)
  * and if required activate the aio work queue to process
  * it
  */
-static void queue_kicked_iocb(struct kiocb *iocb)
+static void try_queue_kicked_iocb(struct kiocb *iocb)
 {
        struct kioctx   *ctx = iocb->ki_ctx;
        unsigned long flags;
        int run = 0;
 
-       WARN_ON((!list_empty(&iocb->ki_wait.task_list)));
+       /* 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);
-       run = __queue_kicked_iocb(iocb);
+       /* 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 */
+       if (!kiocbTryKick(iocb))
+               run = __queue_kicked_iocb(iocb);
        spin_unlock_irqrestore(&ctx->ctx_lock, flags);
-       if (run) {
+       if (run)
                aio_queue_work(ctx);
-               aio_wakeups++;
-       }
 }
 
 /*
@@ -913,11 +929,7 @@ void fastcall kick_iocb(struct kiocb *iocb)
                return;
        }
 
-       iocb->ki_kicked++;
-       /* If its already kicked we shouldn't queue it again */
-       if (!kiocbTryKick(iocb)) {
-               queue_kicked_iocb(iocb);
-       }
+       try_queue_kicked_iocb(iocb);
 }
 EXPORT_SYMBOL(kick_iocb);
 
@@ -984,7 +996,8 @@ int fastcall aio_complete(struct kiocb *iocb, long res, long res2)
 
        tail = info->tail;
        event = aio_ring_event(info, tail, KM_IRQ0);
-       tail = (tail + 1) % info->nr;
+       if (++tail >= info->nr)
+               tail = 0;
 
        event->obj = (u64)(unsigned long)iocb->ki_obj.user;
        event->data = iocb->ki_user_data;
@@ -1008,10 +1021,8 @@ int fastcall aio_complete(struct kiocb *iocb, long res, long res2)
 
        pr_debug("added to ring %p at [%lu]\n", iocb, tail);
 
-       pr_debug("%ld retries: %d of %d (kicked %ld, Q %ld run %ld wake %ld)\n",
-               iocb->ki_retried,
-               iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes,
-               iocb->ki_kicked, iocb->ki_queued, aio_run, aio_wakeups);
+       pr_debug("%ld retries: %d of %d\n", iocb->ki_retried,
+               iocb->ki_nbytes - iocb->ki_left, iocb->ki_nbytes);
 put_rq:
        /* everything turned out well, dispose of the aiocb. */
        ret = __aio_put_req(ctx, iocb);
@@ -1119,7 +1130,6 @@ static int read_events(struct kioctx *ctx,
        int                     i = 0;
        struct io_event         ent;
        struct aio_timeout      to;
-       int                     event_loop = 0; /* testing only */
        int                     retry = 0;
 
        /* needed to zero any padding within an entry (there shouldn't be 
@@ -1186,7 +1196,6 @@ retry:
                        if (to.timed_out)       /* Only check after read evt */
                                break;
                        schedule();
-                       event_loop++;
                        if (signal_pending(tsk)) {
                                ret = -EINTR;
                                break;
@@ -1214,9 +1223,6 @@ retry:
        if (timeout)
                clear_timeout(&to);
 out:
-       pr_debug("event loop executed %d times\n", event_loop);
-       pr_debug("aio_run %ld\n", aio_run);
-       pr_debug("aio_wakeups %ld\n", aio_wakeups);
        return i ? i : ret;
 }
 
@@ -1311,8 +1317,11 @@ asmlinkage long sys_io_destroy(aio_context_t ctx)
 }
 
 /*
- * Default retry method for aio_read (also used for first time submit)
- * Responsible for updating iocb state as retries progress
+ * aio_p{read,write} are the default  ki_retry methods for
+ * IO_CMD_P{READ,WRITE}.  They maintains kiocb retry state around potentially
+ * multiple calls to f_op->aio_read().  They loop around partial progress
+ * instead of returning -EIOCBRETRY because they don't have the means to call
+ * kick_iocb().
  */
 static ssize_t aio_pread(struct kiocb *iocb)
 {
@@ -1321,25 +1330,25 @@ static ssize_t aio_pread(struct kiocb *iocb)
        struct inode *inode = mapping->host;
        ssize_t ret = 0;
 
-       ret = file->f_op->aio_read(iocb, iocb->ki_buf,
-               iocb->ki_left, iocb->ki_pos);
+       do {
+               ret = file->f_op->aio_read(iocb, iocb->ki_buf,
+                       iocb->ki_left, iocb->ki_pos);
+               /*
+                * Can't just depend on iocb->ki_left to determine
+                * whether we are done. This may have been a short read.
+                */
+               if (ret > 0) {
+                       iocb->ki_buf += ret;
+                       iocb->ki_left -= ret;
+               }
 
-       /*
-        * Can't just depend on iocb->ki_left to determine
-        * whether we are done. This may have been a short read.
-        */
-       if (ret > 0) {
-               iocb->ki_buf += ret;
-               iocb->ki_left -= ret;
                /*
-                * For pipes and sockets we return once we have
-                * some data; for regular files we retry till we
-                * complete the entire read or find that we can't
-                * read any more data (e.g short reads).
+                * For pipes and sockets we return once we have some data; for
+                * regular files we retry till we complete the entire read or
+                * find that we can't read any more data (e.g short reads).
                 */
-               if (!S_ISFIFO(inode->i_mode) && !S_ISSOCK(inode->i_mode))
-                       ret = -EIOCBRETRY;
-       }
+       } while (ret > 0 && iocb->ki_left > 0 &&
+                !S_ISFIFO(inode->i_mode) && !S_ISSOCK(inode->i_mode));
 
        /* This means we must have transferred all that we could */
        /* No need to retry anymore */
@@ -1349,27 +1358,21 @@ static ssize_t aio_pread(struct kiocb *iocb)
        return ret;
 }
 
-/*
- * Default retry method for aio_write (also used for first time submit)
- * Responsible for updating iocb state as retries progress
- */
+/* see aio_pread() */
 static ssize_t aio_pwrite(struct kiocb *iocb)
 {
        struct file *file = iocb->ki_filp;
        ssize_t ret = 0;
 
-       ret = file->f_op->aio_write(iocb, iocb->ki_buf,
-               iocb->ki_left, iocb->ki_pos);
-
-       if (ret > 0) {
-               iocb->ki_buf += ret;
-               iocb->ki_left -= ret;
-
-               ret = -EIOCBRETRY;
-       }
+       do {
+               ret = file->f_op->aio_write(iocb, iocb->ki_buf,
+                       iocb->ki_left, iocb->ki_pos);
+               if (ret > 0) {
+                       iocb->ki_buf += ret;
+                       iocb->ki_left -= ret;
+               }
+       } while (ret > 0 && iocb->ki_left > 0);
 
-       /* This means we must have transferred all that we could */
-       /* No need to retry anymore */
        if ((ret == 0) || (iocb->ki_left == 0))
                ret = iocb->ki_nbytes - iocb->ki_left;
 
@@ -1515,8 +1518,7 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
        }
 
        req->ki_filp = file;
-       iocb->aio_key = req->ki_key;
-       ret = put_user(iocb->aio_key, &user_iocb->aio_key);
+       ret = put_user(req->ki_key, &user_iocb->aio_key);
        if (unlikely(ret)) {
                dprintk("EFAULT: aio_key\n");
                goto out_put_req;
@@ -1531,13 +1533,7 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
        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);
-       req->ki_run_list.next = req->ki_run_list.prev = NULL;
-       req->ki_retry = NULL;
        req->ki_retried = 0;
-       req->ki_kicked = 0;
-       req->ki_queued = 0;
-       aio_run = 0;
-       aio_wakeups = 0;
 
        ret = aio_setup_iocb(req);
 
@@ -1545,10 +1541,13 @@ int fastcall io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
                goto out_put_req;
 
        spin_lock_irq(&ctx->ctx_lock);
-       list_add_tail(&req->ki_run_list, &ctx->run_list);
-       /* drain the run list */
-       while (__aio_run_iocbs(ctx))
-               ;
+       aio_run_iocb(req);
+       unlock_kiocb(req);
+       if (!list_empty(&ctx->run_list)) {
+               /* drain the run list */
+               while (__aio_run_iocbs(ctx))
+                       ;
+       }
        spin_unlock_irq(&ctx->ctx_lock);
        aio_put_req(req);       /* drop extra ref to req */
        return 0;
@@ -1675,6 +1674,7 @@ asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb,
        if (NULL != cancel) {
                struct io_event tmp;
                pr_debug("calling cancel\n");
+               lock_kiocb(kiocb);
                memset(&tmp, 0, sizeof(tmp));
                tmp.obj = (u64)(unsigned long)kiocb->ki_obj.user;
                tmp.data = kiocb->ki_user_data;
@@ -1686,8 +1686,9 @@ asmlinkage long sys_io_cancel(aio_context_t ctx_id, struct iocb __user *iocb,
                        if (copy_to_user(result, &tmp, sizeof(tmp)))
                                ret = -EFAULT;
                }
+               unlock_kiocb(kiocb);
        } else
-               printk(KERN_DEBUG "iocb has no cancel operation\n");
+               ret = -EINVAL;
 
        put_ioctx(ctx);