OSDN Git Service

crypto: talitos - HMAC SNOOP NO AFEU mode requires SW icv checking.
[android-x86/kernel.git] / mm / memory-failure.c
index 19e796d..d6524dc 100644 (file)
@@ -336,7 +336,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);
                        }
 
                        /*
@@ -535,6 +536,13 @@ static int delete_from_lru_cache(struct page *p)
                 */
                ClearPageActive(p);
                ClearPageUnevictable(p);
+
+               /*
+                * Poisoned page might never drop its ref count to 0 so we have
+                * to uncharge it manually from its memcg.
+                */
+               mem_cgroup_uncharge(p);
+
                /*
                 * drop the page count elevated by isolate_lru_page()
                 */
@@ -914,6 +922,7 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
        int ret;
        int kill = 1, forcekill;
        struct page *hpage = *hpagep;
+       bool mlocked = PageMlocked(hpage);
 
        /*
         * Here we are interested only in user-mapped pages, so skip any
@@ -978,6 +987,13 @@ static int hwpoison_user_mappings(struct page *p, unsigned long pfn,
                       pfn, page_mapcount(hpage));
 
        /*
+        * try_to_unmap() might put mlocked page in lru cache, so call
+        * shake_page() again to ensure that it's flushed.
+        */
+       if (mlocked)
+               shake_page(hpage, 0);
+
+       /*
         * Now that the dirty bit has been propagated to the
         * struct page and all unmaps done we can decide if
         * killing is needed or not.  Only kill when the page
@@ -1176,7 +1192,10 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
         * page_remove_rmap() in try_to_unmap_one(). So to determine page status
         * correctly, we save a copy of the page flags at this time.
         */
-       page_flags = p->flags;
+       if (PageHuge(p))
+               page_flags = hpage->flags;
+       else
+               page_flags = p->flags;
 
        /*
         * unpoison always clear PG_hwpoison inside page lock
@@ -1587,12 +1606,8 @@ static int soft_offline_huge_page(struct page *page, int flags)
        if (ret) {
                pr_info("soft offline: %#lx: migration failed %d, type %lx\n",
                        pfn, ret, page->flags);
-               /*
-                * We know that soft_offline_huge_page() tries to migrate
-                * only one hugepage pointed to by hpage, so we need not
-                * run through the pagelist here.
-                */
-               putback_active_hugepage(hpage);
+               if (!list_empty(&pagelist))
+                       putback_movable_pages(&pagelist);
                if (ret > 0)
                        ret = -EIO;
        } else {
@@ -1690,19 +1705,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))