]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - mm/madvise.c
userfaultfd: hugetlbfs: prevent UFFDIO_COPY to fill beyond the end of i_size
[mirror_ubuntu-artful-kernel.git] / mm / madvise.c
index 9976852f1e1cb25c986cf69c1846ba8f17e981fd..4edca1d863395d7f03abe12c213965bcf84ec3b3 100644 (file)
@@ -320,6 +320,7 @@ static int madvise_free_pte_range(pmd_t *pmd, unsigned long addr,
 
        tlb_remove_check_page_size_change(tlb, PAGE_SIZE);
        orig_pte = pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
+       flush_tlb_batched_pending(mm);
        arch_enter_lazy_mmu_mode();
        for (; addr != end; pte++, addr += PAGE_SIZE) {
                ptent = *pte;
@@ -367,8 +368,8 @@ static int madvise_free_pte_range(pmd_t *pmd, unsigned long addr,
                                pte_offset_map_lock(mm, pmd, addr, &ptl);
                                goto out;
                        }
-                       put_page(page);
                        unlock_page(page);
+                       put_page(page);
                        pte = pte_offset_map_lock(mm, pmd, addr, &ptl);
                        pte--;
                        addr -= PAGE_SIZE;
@@ -612,18 +613,27 @@ static int madvise_inject_error(int behavior,
                unsigned long start, unsigned long end)
 {
        struct page *page;
+       struct zone *zone;
+       unsigned int order;
 
        if (!capable(CAP_SYS_ADMIN))
                return -EPERM;
 
-       for (; start < end; start += PAGE_SIZE <<
-                               compound_order(compound_head(page))) {
+
+       for (; start < end; start += PAGE_SIZE << order) {
                int ret;
 
                ret = get_user_pages_fast(start, 1, 0, &page);
                if (ret != 1)
                        return ret;
 
+               /*
+                * When soft offlining hugepages, after migrating the page
+                * we dissolve it, therefore in the second loop "page" will
+                * no longer be a compound page, and order will be 0.
+                */
+               order = compound_order(compound_head(page));
+
                if (PageHWPoison(page)) {
                        put_page(page);
                        continue;
@@ -645,6 +655,11 @@ static int madvise_inject_error(int behavior,
                if (ret)
                        return ret;
        }
+
+       /* Ensure that all poisoned pages are removed from per-cpu lists */
+       for_each_populated_zone(zone)
+               drain_all_pages(zone);
+
        return 0;
 }
 #endif