aboutsummaryrefslogtreecommitdiffstats
path: root/mm/memory-failure.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/memory-failure.c')
-rw-r--r--mm/memory-failure.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 620b0b461593..378b0f61fd3c 100644
--- a/mm/memory-failure.c
+++ b/mm/memory-failure.c
@@ -45,6 +45,7 @@
45#include <linux/page-isolation.h> 45#include <linux/page-isolation.h>
46#include <linux/suspend.h> 46#include <linux/suspend.h>
47#include <linux/slab.h> 47#include <linux/slab.h>
48#include <linux/swapops.h>
48#include "internal.h" 49#include "internal.h"
49 50
50int sysctl_memory_failure_early_kill __read_mostly = 0; 51int sysctl_memory_failure_early_kill __read_mostly = 0;
@@ -1296,3 +1297,32 @@ done:
1296 /* keep elevated page count for bad page */ 1297 /* keep elevated page count for bad page */
1297 return ret; 1298 return ret;
1298} 1299}
1300
1301int is_hwpoison_address(unsigned long addr)
1302{
1303 pgd_t *pgdp;
1304 pud_t pud, *pudp;
1305 pmd_t pmd, *pmdp;
1306 pte_t pte, *ptep;
1307 swp_entry_t entry;
1308
1309 pgdp = pgd_offset(current->mm, addr);
1310 if (!pgd_present(*pgdp))
1311 return 0;
1312 pudp = pud_offset(pgdp, addr);
1313 pud = *pudp;
1314 if (!pud_present(pud) || pud_large(pud))
1315 return 0;
1316 pmdp = pmd_offset(pudp, addr);
1317 pmd = *pmdp;
1318 if (!pmd_present(pmd) || pmd_large(pmd))
1319 return 0;
1320 ptep = pte_offset_map(pmdp, addr);
1321 pte = *ptep;
1322 pte_unmap(ptep);
1323 if (!is_swap_pte(pte))
1324 return 0;
1325 entry = pte_to_swp_entry(pte);
1326 return is_hwpoison_entry(entry);
1327}
1328EXPORT_SYMBOL_GPL(is_hwpoison_address);