|
|
@@ -469,6 +469,49 @@ void prep_transhuge_page(struct page *page)
|
|
|
set_compound_page_dtor(page, TRANSHUGE_PAGE_DTOR);
|
|
|
}
|
|
|
|
|
|
+unsigned long __thp_get_unmapped_area(struct file *filp, unsigned long len,
|
|
|
+ loff_t off, unsigned long flags, unsigned long size)
|
|
|
+{
|
|
|
+ unsigned long addr;
|
|
|
+ loff_t off_end = off + len;
|
|
|
+ loff_t off_align = round_up(off, size);
|
|
|
+ unsigned long len_pad;
|
|
|
+
|
|
|
+ if (off_end <= off_align || (off_end - off_align) < size)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ len_pad = len + size;
|
|
|
+ if (len_pad < len || (off + len_pad) < off)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ addr = current->mm->get_unmapped_area(filp, 0, len_pad,
|
|
|
+ off >> PAGE_SHIFT, flags);
|
|
|
+ if (IS_ERR_VALUE(addr))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ addr += (off - addr) & (size - 1);
|
|
|
+ return addr;
|
|
|
+}
|
|
|
+
|
|
|
+unsigned long thp_get_unmapped_area(struct file *filp, unsigned long addr,
|
|
|
+ unsigned long len, unsigned long pgoff, unsigned long flags)
|
|
|
+{
|
|
|
+ loff_t off = (loff_t)pgoff << PAGE_SHIFT;
|
|
|
+
|
|
|
+ if (addr)
|
|
|
+ goto out;
|
|
|
+ if (!IS_DAX(filp->f_mapping->host) || !IS_ENABLED(CONFIG_FS_DAX_PMD))
|
|
|
+ goto out;
|
|
|
+
|
|
|
+ addr = __thp_get_unmapped_area(filp, len, off, flags, PMD_SIZE);
|
|
|
+ if (addr)
|
|
|
+ return addr;
|
|
|
+
|
|
|
+ out:
|
|
|
+ return current->mm->get_unmapped_area(filp, addr, len, pgoff, flags);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL_GPL(thp_get_unmapped_area);
|
|
|
+
|
|
|
static int __do_huge_pmd_anonymous_page(struct fault_env *fe, struct page *page,
|
|
|
gfp_t gfp)
|
|
|
{
|