mmap: allow MAP_HUGETLB for hugetlbfs files v2
[firefly-linux-kernel-4.4.55.git] / mm / mmap.c
index f681e1842fadc1ccd8d7188a7ca1688c73548111..0718c175db8f3eb6236e167d561e25fcad818972 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -955,7 +955,7 @@ can_vma_merge_after(struct vm_area_struct *vma, unsigned long vm_flags,
        if (is_mergeable_vma(vma, file, vm_flags) &&
            is_mergeable_anon_vma(anon_vma, vma->anon_vma, vma)) {
                pgoff_t vm_pglen;
-               vm_pglen = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
+               vm_pglen = vma_pages(vma);
                if (vma->vm_pgoff + vm_pglen == vm_pgoff)
                        return 1;
        }
@@ -1358,13 +1358,14 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
 
        if (!(flags & MAP_ANONYMOUS)) {
                audit_mmap_fd(fd, flags);
-               if (unlikely(flags & MAP_HUGETLB))
-                       return -EINVAL;
                file = fget(fd);
                if (!file)
                        goto out;
                if (is_file_hugepages(file))
                        len = ALIGN(len, huge_page_size(hstate_file(file)));
+               retval = -EINVAL;
+               if (unlikely(flags & MAP_HUGETLB && !is_file_hugepages(file)))
+                       goto out_fput;
        } else if (flags & MAP_HUGETLB) {
                struct user_struct *user = NULL;
                struct hstate *hs = hstate_sizelog((flags >> MAP_HUGE_SHIFT) &
@@ -1391,6 +1392,7 @@ SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
        flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
 
        retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+out_fput:
        if (file)
                fput(file);
 out: