Merge git://git.kvack.org/~bcrl/aio-next
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 16 Aug 2014 14:56:27 +0000 (08:56 -0600)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 16 Aug 2014 14:56:27 +0000 (08:56 -0600)
Pull aio updates from Ben LaHaise.

* git://git.kvack.org/~bcrl/aio-next:
  aio: use iovec array rather than the single one
  aio: fix some comments
  aio: use the macro rather than the inline magic number
  aio: remove the needless registration of ring file's private_data
  aio: remove no longer needed preempt_disable()
  aio: kill the misleading rcu read locks in ioctx_add_table() and kill_ioctx()
  aio: change exit_aio() to load mm->ioctx_table once and avoid rcu_read_lock()

1  2 
fs/aio.c

diff --combined fs/aio.c
index bd7ec2cc2674d73ab71405769ce53b922a0c0082,0fd9181d8c0cfb7533dd546e4639e914d4833b8d..ae635872affb4b9a3fa993652cfad3009894532a
+++ b/fs/aio.c
@@@ -192,7 -192,6 +192,6 @@@ static struct file *aio_private_file(st
        }
  
        file->f_flags = O_RDWR;
-       file->private_data = ctx;
        return file;
  }
  
@@@ -202,7 -201,7 +201,7 @@@ static struct dentry *aio_mount(struct 
        static const struct dentry_operations ops = {
                .d_dname        = simple_dname,
        };
-       return mount_pseudo(fs_type, "aio:", NULL, &ops, 0xa10a10a1);
+       return mount_pseudo(fs_type, "aio:", NULL, &ops, AIO_RING_MAGIC);
  }
  
  /* aio_setup
@@@ -506,8 -505,6 +505,8 @@@ static void free_ioctx(struct work_stru
  
        aio_free_ring(ctx);
        free_percpu(ctx->cpu);
 +      percpu_ref_exit(&ctx->reqs);
 +      percpu_ref_exit(&ctx->users);
        kmem_cache_free(kioctx_cachep, ctx);
  }
  
@@@ -556,8 -553,7 +555,7 @@@ static int ioctx_add_table(struct kioct
        struct aio_ring *ring;
  
        spin_lock(&mm->ioctx_lock);
-       rcu_read_lock();
-       table = rcu_dereference(mm->ioctx_table);
+       table = rcu_dereference_raw(mm->ioctx_table);
  
        while (1) {
                if (table)
                                if (!table->table[i]) {
                                        ctx->id = i;
                                        table->table[i] = ctx;
-                                       rcu_read_unlock();
                                        spin_unlock(&mm->ioctx_lock);
  
                                        /* While kioctx setup is in progress,
                                }
  
                new_nr = (table ? table->nr : 1) * 4;
-               rcu_read_unlock();
                spin_unlock(&mm->ioctx_lock);
  
                table = kzalloc(sizeof(*table) + sizeof(struct kioctx *) *
                table->nr = new_nr;
  
                spin_lock(&mm->ioctx_lock);
-               rcu_read_lock();
-               old = rcu_dereference(mm->ioctx_table);
+               old = rcu_dereference_raw(mm->ioctx_table);
  
                if (!old) {
                        rcu_assign_pointer(mm->ioctx_table, table);
@@@ -717,8 -709,8 +711,8 @@@ err_ctx
  err:
        mutex_unlock(&ctx->ring_lock);
        free_percpu(ctx->cpu);
 -      free_percpu(ctx->reqs.pcpu_count);
 -      free_percpu(ctx->users.pcpu_count);
 +      percpu_ref_exit(&ctx->reqs);
 +      percpu_ref_exit(&ctx->users);
        kmem_cache_free(kioctx_cachep, ctx);
        pr_debug("error allocating ioctx %d\n", err);
        return ERR_PTR(err);
@@@ -739,12 -731,9 +733,9 @@@ static int kill_ioctx(struct mm_struct 
  
  
        spin_lock(&mm->ioctx_lock);
-       rcu_read_lock();
-       table = rcu_dereference(mm->ioctx_table);
+       table = rcu_dereference_raw(mm->ioctx_table);
        WARN_ON(ctx != table->table[ctx->id]);
        table->table[ctx->id] = NULL;
-       rcu_read_unlock();
        spin_unlock(&mm->ioctx_lock);
  
        /* percpu_ref_kill() will do the necessary call_rcu() */
@@@ -793,40 -782,30 +784,30 @@@ EXPORT_SYMBOL(wait_on_sync_kiocb)
   */
  void exit_aio(struct mm_struct *mm)
  {
-       struct kioctx_table *table;
-       struct kioctx *ctx;
-       unsigned i = 0;
-       while (1) {
-               rcu_read_lock();
-               table = rcu_dereference(mm->ioctx_table);
-               do {
-                       if (!table || i >= table->nr) {
-                               rcu_read_unlock();
-                               rcu_assign_pointer(mm->ioctx_table, NULL);
-                               if (table)
-                                       kfree(table);
-                               return;
-                       }
+       struct kioctx_table *table = rcu_dereference_raw(mm->ioctx_table);
+       int i;
  
-                       ctx = table->table[i++];
-               } while (!ctx);
+       if (!table)
+               return;
  
-               rcu_read_unlock();
+       for (i = 0; i < table->nr; ++i) {
+               struct kioctx *ctx = table->table[i];
  
+               if (!ctx)
+                       continue;
                /*
-                * We don't need to bother with munmap() here -
-                * exit_mmap(mm) is coming and it'll unmap everything.
-                * Since aio_free_ring() uses non-zero ->mmap_size
-                * as indicator that it needs to unmap the area,
-                * just set it to 0; aio_free_ring() is the only
-                * place that uses ->mmap_size, so it's safe.
+                * We don't need to bother with munmap() here - exit_mmap(mm)
+                * is coming and it'll unmap everything. And we simply can't,
+                * this is not necessarily our ->mm.
+                * Since kill_ioctx() uses non-zero ->mmap_size as indicator
+                * that it needs to unmap the area, just set it to 0.
                 */
                ctx->mmap_size = 0;
                kill_ioctx(mm, ctx, NULL);
        }
+       RCU_INIT_POINTER(mm->ioctx_table, NULL);
+       kfree(table);
  }
  
  static void put_reqs_available(struct kioctx *ctx, unsigned nr)
        struct kioctx_cpu *kcpu;
        unsigned long flags;
  
-       preempt_disable();
-       kcpu = this_cpu_ptr(ctx->cpu);
        local_irq_save(flags);
+       kcpu = this_cpu_ptr(ctx->cpu);
        kcpu->reqs_available += nr;
  
        while (kcpu->reqs_available >= ctx->req_batch * 2) {
        }
  
        local_irq_restore(flags);
-       preempt_enable();
  }
  
  static bool get_reqs_available(struct kioctx *ctx)
        bool ret = false;
        unsigned long flags;
  
-       preempt_disable();
-       kcpu = this_cpu_ptr(ctx->cpu);
        local_irq_save(flags);
+       kcpu = this_cpu_ptr(ctx->cpu);
        if (!kcpu->reqs_available) {
                int old, avail = atomic_read(&ctx->reqs_available);
  
        kcpu->reqs_available--;
  out:
        local_irq_restore(flags);
-       preempt_enable();
        return ret;
  }
  
@@@ -1047,7 -1020,7 +1022,7 @@@ void aio_complete(struct kiocb *iocb, l
  }
  EXPORT_SYMBOL(aio_complete);
  
- /* aio_read_events
+ /* aio_read_events_ring
   *    Pull an event off of the ioctx's event ring.  Returns the number of
   *    events fetched
   */
@@@ -1270,12 -1243,12 +1245,12 @@@ static ssize_t aio_setup_vectored_rw(st
        if (compat)
                ret = compat_rw_copy_check_uvector(rw,
                                (struct compat_iovec __user *)buf,
-                               *nr_segs, 1, *iovec, iovec);
+                               *nr_segs, UIO_FASTIOV, *iovec, iovec);
        else
  #endif
                ret = rw_copy_check_uvector(rw,
                                (struct iovec __user *)buf,
-                               *nr_segs, 1, *iovec, iovec);
+                               *nr_segs, UIO_FASTIOV, *iovec, iovec);
        if (ret < 0)
                return ret;
  
@@@ -1299,9 -1272,8 +1274,8 @@@ static ssize_t aio_setup_single_vector(
  }
  
  /*
-  * aio_setup_iocb:
-  *    Performs the initial checks and aio retry method
-  *    setup for the kiocb at the time of io submission.
+  * aio_run_iocb:
+  *    Performs the initial checks and io submission.
   */
  static ssize_t aio_run_iocb(struct kiocb *req, unsigned opcode,
                            char __user *buf, bool compat)
        fmode_t mode;
        aio_rw_op *rw_op;
        rw_iter_op *iter_op;
-       struct iovec inline_vec, *iovec = &inline_vec;
+       struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs;
        struct iov_iter iter;
  
        switch (opcode) {
@@@ -1348,7 -1320,7 +1322,7 @@@ rw_common
                if (!ret)
                        ret = rw_verify_area(rw, file, &req->ki_pos, req->ki_nbytes);
                if (ret < 0) {
-                       if (iovec != &inline_vec)
+                       if (iovec != inline_vecs)
                                kfree(iovec);
                        return ret;
                }
                return -EINVAL;
        }
  
-       if (iovec != &inline_vec)
+       if (iovec != inline_vecs)
                kfree(iovec);
  
        if (ret != -EIOCBQUEUED) {