Add the new vma_set_file() function to allow changing
vma->vm_file with the necessary refcount dance.
v2: add more users of this.
v3: add missing EXPORT_SYMBOL, rebase on mmap cleanup,
    add comments why we drop the reference on two occasions.
v4: make it clear that changing an anonymous vma is illegal.
v5: move vma_set_file to mm/util.c
Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch> (v2)
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Acked-by: Andrew Morton <akpm@linux-foundation.org>
Link: https://patchwork.freedesktop.org/patch/399360/
                return -EINVAL;
 
        /* readjust the vma */
-       fput(vma->vm_file);
-       vma->vm_file = get_file(dmabuf->file);
+       vma_set_file(vma, dmabuf->file);
        vma->vm_pgoff = pgoff;
 
        return dmabuf->ops->mmap(dmabuf, vma);
 
                 * address_space (so unmap_mapping_range does what we want,
                 * in particular in the case of mmap'd dmabufs)
                 */
-               fput(vma->vm_file);
-               get_file(etnaviv_obj->base.filp);
                vma->vm_pgoff = 0;
-               vma->vm_file  = etnaviv_obj->base.filp;
+               vma_set_file(vma, etnaviv_obj->base.filp);
 
                vma->vm_page_prot = vm_page_prot;
        }
 
        if (ret)
                return ret;
 
-       fput(vma->vm_file);
-       vma->vm_file = get_file(obj->base.filp);
+       vma_set_file(vma, obj->base.filp);
 
        return 0;
 }
 
         * requires avoiding extraneous references to their filp, hence why
         * we prefer to use an anonymous file for their mmaps.
         */
-       fput(vma->vm_file);
-       vma->vm_file = anon;
+       vma_set_file(vma, anon);
+       /* Drop the initial creation reference, the vma is now holding one. */
+       fput(anon);
 
        switch (mmo->mmap_type) {
        case I915_MMAP_TYPE_WC:
 
                 * address_space (so unmap_mapping_range does what we want,
                 * in particular in the case of mmap'd dmabufs)
                 */
-               fput(vma->vm_file);
-               get_file(obj->filp);
                vma->vm_pgoff = 0;
-               vma->vm_file  = obj->filp;
+               vma_set_file(vma, obj->filp);
 
                vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
        }
 
                 * address_space (so unmap_mapping_range does what we want,
                 * in particular in the case of mmap'd dmabufs)
                 */
-               fput(vma->vm_file);
                vma->vm_pgoff = 0;
-               vma->vm_file  = get_file(obj->filp);
+               vma_set_file(vma, obj->filp);
 
                vma->vm_page_prot = vm_get_page_prot(vma->vm_flags);
        }
 
        if (ret)
                return ret;
 
-       fput(vma->vm_file);
-       vma->vm_file = get_file(obj->filp);
+       vma_set_file(vma, obj->filp);
        vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
        vma->vm_page_prot = pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
 
 
                vma_set_anonymous(vma);
        }
 
-       if (vma->vm_file)
-               fput(vma->vm_file);
-       vma->vm_file = asma->file;
+       vma_set_file(vma, asma->file);
+       /* XXX: merge this with the get_file() above if possible */
+       fput(asma->file);
 
 out:
        mutex_unlock(&ashmem_mutex);
 
 }
 #endif
 
+void vma_set_file(struct vm_area_struct *vma, struct file *file);
+
 #ifdef CONFIG_NUMA_BALANCING
 unsigned long change_prot_numa(struct vm_area_struct *vma,
                        unsigned long start, unsigned long end);
 
        return (vma->vm_start <= KSTK_ESP(t) && vma->vm_end >= KSTK_ESP(t));
 }
 
+/*
+ * Change backing file, only valid to use during initial VMA setup.
+ */
+void vma_set_file(struct vm_area_struct *vma, struct file *file)
+{
+       /* Changing an anonymous vma with this is illegal */
+       get_file(file);
+       swap(vma->vm_file, file);
+       fput(file);
+}
+EXPORT_SYMBOL(vma_set_file);
+
 #ifndef STACK_RND_MASK
 #define STACK_RND_MASK (0x7ff >> (PAGE_SHIFT - 12))     /* 8MB of VA */
 #endif