no 100% when charge ok pin is no full state, and reset cw2015 when Over-discharge...
[firefly-linux-kernel-4.4.55.git] / fs / aio.c
index 250b0a73c8a8ca92b78c3a0282d2425ce7649dcf..278ed7dc71bbc11cbadb4603fe40507e75d20741 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -34,8 +34,6 @@
 #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>
@@ -65,14 +63,6 @@ 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 *);
 
@@ -85,9 +75,8 @@ static int __init aio_setup(void)
        kiocb_cachep = KMEM_CACHE(kiocb, SLAB_HWCACHE_ALIGN|SLAB_PANIC);
        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);
+       aio_wq = alloc_workqueue("aio", 0, 1);  /* used to limit concurrency */
+       BUG_ON(!aio_wq);
 
        pr_debug("aio_setup: sizeof(struct page) = %d\n", (int)sizeof(struct page));
 
@@ -239,15 +228,17 @@ static void __put_ioctx(struct kioctx *ctx)
        call_rcu(&ctx->rcu_head, ctx_rcu_free);
 }
 
-#define get_ioctx(kioctx) do {                                         \
-       BUG_ON(atomic_read(&(kioctx)->users) <= 0);                     \
-       atomic_inc(&(kioctx)->users);                                   \
-} while (0)
-#define put_ioctx(kioctx) do {                                         \
-       BUG_ON(atomic_read(&(kioctx)->users) <= 0);                     \
-       if (unlikely(atomic_dec_and_test(&(kioctx)->users)))            \
-               __put_ioctx(kioctx);                                    \
-} while (0)
+static inline int try_get_ioctx(struct kioctx *kioctx)
+{
+       return atomic_inc_not_zero(&kioctx->users);
+}
+
+static inline void put_ioctx(struct kioctx *kioctx)
+{
+       BUG_ON(atomic_read(&kioctx->users) <= 0);
+       if (unlikely(atomic_dec_and_test(&kioctx->users)))
+               __put_ioctx(kioctx);
+}
 
 /* ioctx_alloc
  *     Allocates and initializes an ioctx.  Returns an ERR_PTR if it failed.
@@ -276,7 +267,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events)
        mm = ctx->mm = current->mm;
        atomic_inc(&mm->mm_count);
 
-       atomic_set(&ctx->users, 1);
+       atomic_set(&ctx->users, 2);
        spin_lock_init(&ctx->ctx_lock);
        spin_lock_init(&ctx->ring_info.ring_lock);
        init_waitqueue_head(&ctx->wait);
@@ -512,7 +503,7 @@ static inline void really_put_req(struct kioctx *ctx, struct kiocb *req)
        ctx->reqs_active--;
 
        if (unlikely(!ctx->reqs_active && ctx->dead))
-               wake_up(&ctx->wait);
+               wake_up_all(&ctx->wait);
 }
 
 static void aio_fput_routine(struct work_struct *data)
@@ -530,11 +521,16 @@ static void aio_fput_routine(struct work_struct *data)
                        fput(req->ki_filp);
 
                /* Link the iocb into the context's free list */
+               rcu_read_lock();
                spin_lock_irq(&ctx->ctx_lock);
                really_put_req(ctx, req);
+               /*
+                * at that point ctx might've been killed, but actual
+                * freeing is RCU'd
+                */
                spin_unlock_irq(&ctx->ctx_lock);
+               rcu_read_unlock();
 
-               put_ioctx(ctx);
                spin_lock_irq(&fput_lock);
        }
        spin_unlock_irq(&fput_lock);
@@ -565,11 +561,10 @@ static int __aio_put_req(struct kioctx *ctx, struct kiocb *req)
         * this function will be executed w/out any aio kthread wakeup.
         */
        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);
+               schedule_work(&fput_work);
        } else {
                req->ki_filp = NULL;
                really_put_req(ctx, req);
@@ -601,8 +596,13 @@ static struct kioctx *lookup_ioctx(unsigned long ctx_id)
        rcu_read_lock();
 
        hlist_for_each_entry_rcu(ctx, n, &mm->ioctx_list, list) {
-               if (ctx->user_id == ctx_id && !ctx->dead) {
-                       get_ioctx(ctx);
+               /*
+                * RCU protects us against accessing freed memory but
+                * we have to be careful not to get a reference when the
+                * reference count already dropped to 0 (ctx->dead test
+                * is unreliable because of races).
+                */
+               if (ctx->user_id == ctx_id && !ctx->dead && try_get_ioctx(ctx)){
                        ret = ctx;
                        break;
                }
@@ -798,29 +798,12 @@ static void aio_queue_work(struct kioctx * ctx)
        queue_delayed_work(aio_wq, &ctx->wq, timeout);
 }
 
-
 /*
- * aio_run_iocbs:
- *     Process all pending retries queued on the ioctx
- *     run list.
- * Assumes it is operating within the aio issuer's mm
- * context.
- */
-static inline void aio_run_iocbs(struct kioctx *ctx)
-{
-       int requeue;
-
-       spin_lock_irq(&ctx->ctx_lock);
-
-       requeue = __aio_run_iocbs(ctx);
-       spin_unlock_irq(&ctx->ctx_lock);
-       if (requeue)
-               aio_queue_work(ctx);
-}
-
-/*
- * just like aio_run_iocbs, but keeps running them until
- * the list stays empty
+ * aio_run_all_iocbs:
+ *     Process all pending retries queued on the ioctx
+ *     run list, and keep running them until the list
+ *     stays empty.
+ * Assumes it is operating within the aio issuer's mm context.
  */
 static inline void aio_run_all_iocbs(struct kioctx *ctx)
 {
@@ -1233,7 +1216,7 @@ static void io_destroy(struct kioctx *ioctx)
         * by other CPUs at this point.  Right now, we rely on the
         * locking done by the above calls to ensure this consistency.
         */
-       wake_up(&ioctx->wait);
+       wake_up_all(&ioctx->wait);
        put_ioctx(ioctx);       /* once for the lookup */
 }
 
@@ -1271,10 +1254,10 @@ 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);
-               if (!ret)
+               if (!ret) {
+                       put_ioctx(ioctx);
                        return 0;
-
-               get_ioctx(ioctx); /* io_destroy() expects us to hold a ref */
+               }
                io_destroy(ioctx);
        }
 
@@ -1412,6 +1395,10 @@ static ssize_t aio_setup_vectored_rw(int type, struct kiocb *kiocb, bool compat)
        if (ret < 0)
                goto out;
 
+       ret = rw_verify_area(type, kiocb->ki_filp, &kiocb->ki_pos, ret);
+       if (ret < 0)
+               goto out;
+
        kiocb->ki_nr_segs = kiocb->ki_nbytes;
        kiocb->ki_cur_seg = 0;
        /* ki_nbytes/left now reflect bytes instead of segs */
@@ -1423,11 +1410,17 @@ out:
        return ret;
 }
 
-static ssize_t aio_setup_single_vector(struct kiocb *kiocb)
+static ssize_t aio_setup_single_vector(int type, struct file * file, struct kiocb *kiocb)
 {
+       int bytes;
+
+       bytes = rw_verify_area(type, file, &kiocb->ki_pos, kiocb->ki_left);
+       if (bytes < 0)
+               return bytes;
+
        kiocb->ki_iovec = &kiocb->ki_inline_vec;
        kiocb->ki_iovec->iov_base = kiocb->ki_buf;
-       kiocb->ki_iovec->iov_len = kiocb->ki_left;
+       kiocb->ki_iovec->iov_len = bytes;
        kiocb->ki_nr_segs = 1;
        kiocb->ki_cur_seg = 0;
        return 0;
@@ -1452,10 +1445,7 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat)
                if (unlikely(!access_ok(VERIFY_WRITE, kiocb->ki_buf,
                        kiocb->ki_left)))
                        break;
-               ret = security_file_permission(file, MAY_READ);
-               if (unlikely(ret))
-                       break;
-               ret = aio_setup_single_vector(kiocb);
+               ret = aio_setup_single_vector(READ, file, kiocb);
                if (ret)
                        break;
                ret = -EINVAL;
@@ -1470,10 +1460,7 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat)
                if (unlikely(!access_ok(VERIFY_READ, kiocb->ki_buf,
                        kiocb->ki_left)))
                        break;
-               ret = security_file_permission(file, MAY_WRITE);
-               if (unlikely(ret))
-                       break;
-               ret = aio_setup_single_vector(kiocb);
+               ret = aio_setup_single_vector(WRITE, file, kiocb);
                if (ret)
                        break;
                ret = -EINVAL;
@@ -1484,9 +1471,6 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat)
                ret = -EBADF;
                if (unlikely(!(file->f_mode & FMODE_READ)))
                        break;
-               ret = security_file_permission(file, MAY_READ);
-               if (unlikely(ret))
-                       break;
                ret = aio_setup_vectored_rw(READ, kiocb, compat);
                if (ret)
                        break;
@@ -1498,9 +1482,6 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat)
                ret = -EBADF;
                if (unlikely(!(file->f_mode & FMODE_WRITE)))
                        break;
-               ret = security_file_permission(file, MAY_WRITE);
-               if (unlikely(ret))
-                       break;
                ret = aio_setup_vectored_rw(WRITE, kiocb, compat);
                if (ret)
                        break;
@@ -1529,45 +1510,8 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb, bool compat)
        return 0;
 }
 
-static void aio_batch_add(struct address_space *mapping,
-                         struct hlist_head *batch_hash)
-{
-       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;
-       }
-
-       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 hlist_head *batch_hash,
-                        bool compat)
+                        struct iocb *iocb, bool compat)
 {
        struct kiocb *req;
        struct file *file;
@@ -1634,6 +1578,23 @@ static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
                goto out_put_req;
 
        spin_lock_irq(&ctx->ctx_lock);
+       /*
+        * We could have raced with io_destroy() and are currently holding a
+        * reference to ctx which should be destroyed. We cannot submit IO
+        * since ctx gets freed as soon as io_submit() puts its reference.  The
+        * check here is reliable: io_destroy() sets ctx->dead before waiting
+        * for outstanding IO and the barrier between these two is realized by
+        * unlock of mm->ioctx_lock and lock of ctx->ctx_lock.  Analogously we
+        * increment ctx->reqs_active before checking for ctx->dead and the
+        * barrier is realized by unlock and lock of ctx->ctx_lock. Thus if we
+        * don't see ctx->dead set here, io_destroy() waits for our IO to
+        * finish.
+        */
+       if (ctx->dead) {
+               spin_unlock_irq(&ctx->ctx_lock);
+               ret = -EINVAL;
+               goto out_put_req;
+       }
        aio_run_iocb(req);
        if (!list_empty(&ctx->run_list)) {
                /* drain the run list */
@@ -1641,11 +1602,6 @@ 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;
@@ -1662,7 +1618,7 @@ long do_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, }, };
+       struct blk_plug plug;
 
        if (unlikely(nr < 0))
                return -EINVAL;
@@ -1679,6 +1635,8 @@ long do_io_submit(aio_context_t ctx_id, long nr,
                return -EINVAL;
        }
 
+       blk_start_plug(&plug);
+
        /*
         * AKPM: should this return a partial result if some of the IOs were
         * successfully submitted?
@@ -1697,11 +1655,11 @@ long do_io_submit(aio_context_t ctx_id, long nr,
                        break;
                }
 
-               ret = io_submit_one(ctx, user_iocb, &tmp, batch_hash, compat);
+               ret = io_submit_one(ctx, user_iocb, &tmp, compat);
                if (ret)
                        break;
        }
-       aio_batch_free(batch_hash);
+       blk_finish_plug(&plug);
 
        put_ioctx(ctx);
        return i ? i : ret;
@@ -1827,7 +1785,7 @@ SYSCALL_DEFINE5(io_getevents, aio_context_t, ctx_id,
        long ret = -EINVAL;
 
        if (likely(ioctx)) {
-               if (likely(min_nr <= nr && min_nr >= 0 && nr >= 0))
+               if (likely(min_nr <= nr && min_nr >= 0))
                        ret = read_events(ioctx, min_nr, nr, events, timeout);
                put_ioctx(ioctx);
        }