Merge git://git.kvack.org/~bcrl/aio-next
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 14 Dec 2014 21:36:57 +0000 (13:36 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 14 Dec 2014 21:36:57 +0000 (13:36 -0800)
Pull aio updates from Benjamin LaHaise.

* git://git.kvack.org/~bcrl/aio-next:
  aio: Skip timer for io_getevents if timeout=0
  aio: Make it possible to remap aio ring

fs/aio.c
include/linux/fs.h
mm/mremap.c

index 14b9315..1b7893e 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -286,12 +286,37 @@ static void aio_free_ring(struct kioctx *ctx)
 
 static int aio_ring_mmap(struct file *file, struct vm_area_struct *vma)
 {
+       vma->vm_flags |= VM_DONTEXPAND;
        vma->vm_ops = &generic_file_vm_ops;
        return 0;
 }
 
+static void aio_ring_remap(struct file *file, struct vm_area_struct *vma)
+{
+       struct mm_struct *mm = vma->vm_mm;
+       struct kioctx_table *table;
+       int i;
+
+       spin_lock(&mm->ioctx_lock);
+       rcu_read_lock();
+       table = rcu_dereference(mm->ioctx_table);
+       for (i = 0; i < table->nr; i++) {
+               struct kioctx *ctx;
+
+               ctx = table->table[i];
+               if (ctx && ctx->aio_ring_file == file) {
+                       ctx->user_id = ctx->mmap_base = vma->vm_start;
+                       break;
+               }
+       }
+
+       rcu_read_unlock();
+       spin_unlock(&mm->ioctx_lock);
+}
+
 static const struct file_operations aio_ring_fops = {
        .mmap = aio_ring_mmap,
+       .mremap = aio_ring_remap,
 };
 
 #if IS_ENABLED(CONFIG_MIGRATION)
@@ -1228,8 +1253,12 @@ static long read_events(struct kioctx *ctx, long min_nr, long nr,
         * the ringbuffer empty. So in practice we should be ok, but it's
         * something to be aware of when touching this code.
         */
-       wait_event_interruptible_hrtimeout(ctx->wait,
-                       aio_read_events(ctx, min_nr, nr, event, &ret), until);
+       if (until.tv64 == 0)
+               aio_read_events(ctx, min_nr, nr, event, &ret);
+       else
+               wait_event_interruptible_hrtimeout(ctx->wait,
+                               aio_read_events(ctx, min_nr, nr, event, &ret),
+                               until);
 
        if (!ret && signal_pending(current))
                ret = -EINTR;
index 4193a0b..8f7fc8d 100644 (file)
@@ -1518,6 +1518,7 @@ struct file_operations {
        long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long);
        long (*compat_ioctl) (struct file *, unsigned int, unsigned long);
        int (*mmap) (struct file *, struct vm_area_struct *);
+       void (*mremap)(struct file *, struct vm_area_struct *);
        int (*open) (struct inode *, struct file *);
        int (*flush) (struct file *, fl_owner_t id);
        int (*release) (struct inode *, struct file *);
index 84aa36f..17fa018 100644 (file)
@@ -288,7 +288,8 @@ static unsigned long move_vma(struct vm_area_struct *vma,
                old_len = new_len;
                old_addr = new_addr;
                new_addr = -ENOMEM;
-       }
+       } else if (vma->vm_file && vma->vm_file->f_op->mremap)
+               vma->vm_file->f_op->mremap(vma->vm_file, new_vma);
 
        /* Conceal VM_ACCOUNT so old reservation is not undone */
        if (vm_flags & VM_ACCOUNT) {