|
@@ -32,6 +32,7 @@
|
|
|
#include <linux/hugetlb.h>
|
|
|
#include <linux/hugetlb_cgroup.h>
|
|
|
#include <linux/node.h>
|
|
|
+#include <linux/userfaultfd_k.h>
|
|
|
#include "internal.h"
|
|
|
|
|
|
int hugepages_treat_as_movable;
|
|
@@ -3680,6 +3681,38 @@ retry:
|
|
|
size = i_size_read(mapping->host) >> huge_page_shift(h);
|
|
|
if (idx >= size)
|
|
|
goto out;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Check for page in userfault range
|
|
|
+ */
|
|
|
+ if (userfaultfd_missing(vma)) {
|
|
|
+ u32 hash;
|
|
|
+ struct vm_fault vmf = {
|
|
|
+ .vma = vma,
|
|
|
+ .address = address,
|
|
|
+ .flags = flags,
|
|
|
+ /*
|
|
|
+ * Hard to debug if it ends up being
|
|
|
+ * used by a callee that assumes
|
|
|
+ * something about the other
|
|
|
+ * uninitialized fields... same as in
|
|
|
+ * memory.c
|
|
|
+ */
|
|
|
+ };
|
|
|
+
|
|
|
+ /*
|
|
|
+ * hugetlb_fault_mutex must be dropped before
|
|
|
+ * handling userfault. Reacquire after handling
|
|
|
+ * fault to make calling code simpler.
|
|
|
+ */
|
|
|
+ hash = hugetlb_fault_mutex_hash(h, mm, vma, mapping,
|
|
|
+ idx, address);
|
|
|
+ mutex_unlock(&hugetlb_fault_mutex_table[hash]);
|
|
|
+ ret = handle_userfault(&vmf, VM_UFFD_MISSING);
|
|
|
+ mutex_lock(&hugetlb_fault_mutex_table[hash]);
|
|
|
+ goto out;
|
|
|
+ }
|
|
|
+
|
|
|
page = alloc_huge_page(vma, address, 0);
|
|
|
if (IS_ERR(page)) {
|
|
|
ret = PTR_ERR(page);
|