]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blobdiff - mm/memory-failure.c
UBUNTU: Ubuntu-4.15.0-96.97
[mirror_ubuntu-bionic-kernel.git] / mm / memory-failure.c
index 4acdf393a80181336084f4f6da6539f78249ba30..670011006418051b1a9cc79f73c2b36b1cb65653 100644 (file)
@@ -339,7 +339,8 @@ static void kill_procs(struct list_head *to_kill, int forcekill, int trapno,
                        if (fail || tk->addr_valid == 0) {
                                pr_err("Memory failure: %#lx: forcibly killing %s:%d because of failure to unmap corrupted page\n",
                                       pfn, tk->tsk->comm, tk->tsk->pid);
-                               force_sig(SIGKILL, tk->tsk);
+                               do_send_sig_info(SIGKILL, SEND_SIG_PRIV,
+                                                tk->tsk, PIDTYPE_PID);
                        }
 
                        /*
@@ -508,6 +509,7 @@ static const char * const action_page_types[] = {
        [MF_MSG_POISONED_HUGE]          = "huge page already hardware poisoned",
        [MF_MSG_HUGE]                   = "huge page",
        [MF_MSG_FREE_HUGE]              = "free huge page",
+       [MF_MSG_NON_PMD_HUGE]           = "non-pmd-sized huge page",
        [MF_MSG_UNMAP_FAILED]           = "unmapping failed page",
        [MF_MSG_DIRTY_SWAPCACHE]        = "dirty swapcache page",
        [MF_MSG_CLEAN_SWAPCACHE]        = "clean swapcache page",
@@ -1090,6 +1092,21 @@ static int memory_failure_hugetlb(unsigned long pfn, int trapno, int flags)
                return 0;
        }
 
+       /*
+        * TODO: hwpoison for pud-sized hugetlb doesn't work right now, so
+        * simply disable it. In order to make it work properly, we need
+        * make sure that:
+        *  - conversion of a pud that maps an error hugetlb into hwpoison
+        *    entry properly works, and
+        *  - other mm code walking over page table is aware of pud-aligned
+        *    hwpoison entries.
+        */
+       if (huge_page_size(page_hstate(head)) > PMD_SIZE) {
+               action_result(pfn, MF_MSG_NON_PMD_HUGE, MF_IGNORED);
+               res = -EBUSY;
+               goto out;
+       }
+
        if (!hwpoison_user_mappings(p, pfn, trapno, flags, &head)) {
                action_result(pfn, MF_MSG_UNMAP_FAILED, MF_IGNORED);
                res = -EBUSY;
@@ -1146,8 +1163,6 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
                return 0;
        }
 
-       arch_unmap_kpfn(pfn);
-
        orig_head = hpage = compound_head(p);
        num_poisoned_pages_inc();
 
@@ -1686,19 +1701,17 @@ static int soft_offline_in_use_page(struct page *page, int flags)
        struct page *hpage = compound_head(page);
 
        if (!PageHuge(page) && PageTransHuge(hpage)) {
-               lock_page(hpage);
-               if (!PageAnon(hpage) || unlikely(split_huge_page(hpage))) {
-                       unlock_page(hpage);
-                       if (!PageAnon(hpage))
+               lock_page(page);
+               if (!PageAnon(page) || unlikely(split_huge_page(page))) {
+                       unlock_page(page);
+                       if (!PageAnon(page))
                                pr_info("soft offline: %#lx: non anonymous thp\n", page_to_pfn(page));
                        else
                                pr_info("soft offline: %#lx: thp split failed\n", page_to_pfn(page));
-                       put_hwpoison_page(hpage);
+                       put_hwpoison_page(page);
                        return -EBUSY;
                }
-               unlock_page(hpage);
-               get_hwpoison_page(page);
-               put_hwpoison_page(hpage);
+               unlock_page(page);
        }
 
        if (PageHuge(page))