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.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/mm/memory-failure.c b/mm/memory-failure.c
index 620b0b461593..6b44e52cacaa 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,35 @@ 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
1301/*
1302 * The caller must hold current->mm->mmap_sem in read mode.
1303 */
1304int is_hwpoison_address(unsigned long addr)
1305{
1306 pgd_t *pgdp;
1307 pud_t pud, *pudp;
1308 pmd_t pmd, *pmdp;
1309 pte_t pte, *ptep;
1310 swp_entry_t entry;
1311
1312 pgdp = pgd_offset(current->mm, addr);
1313 if (!pgd_present(*pgdp))
1314 return 0;
1315 pudp = pud_offset(pgdp, addr);
1316 pud = *pudp;
1317 if (!pud_present(pud) || pud_large(pud))
1318 return 0;
1319 pmdp = pmd_offset(pudp, addr);
1320 pmd = *pmdp;
1321 if (!pmd_present(pmd) || pmd_large(pmd))
1322 return 0;
1323 ptep = pte_offset_map(pmdp, addr);
1324 pte = *ptep;
1325 pte_unmap(ptep);
1326 if (!is_swap_pte(pte))
1327 return 0;
1328 entry = pte_to_swp_entry(pte);
1329 return is_hwpoison_entry(entry);
1330}
1331EXPORT_SYMBOL_GPL(is_hwpoison_address);