diff options
Diffstat (limited to 'mm/memory-failure.c')
-rw-r--r-- | mm/memory-failure.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/mm/memory-failure.c b/mm/memory-failure.c index d0b420aba726..9c26eeca1342 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 <linux/hugetlb.h> | 49 | #include <linux/hugetlb.h> |
49 | #include "internal.h" | 50 | #include "internal.h" |
50 | 51 | ||
@@ -1356,3 +1357,35 @@ done: | |||
1356 | /* keep elevated page count for bad page */ | 1357 | /* keep elevated page count for bad page */ |
1357 | return ret; | 1358 | return ret; |
1358 | } | 1359 | } |
1360 | |||
1361 | /* | ||
1362 | * The caller must hold current->mm->mmap_sem in read mode. | ||
1363 | */ | ||
1364 | int is_hwpoison_address(unsigned long addr) | ||
1365 | { | ||
1366 | pgd_t *pgdp; | ||
1367 | pud_t pud, *pudp; | ||
1368 | pmd_t pmd, *pmdp; | ||
1369 | pte_t pte, *ptep; | ||
1370 | swp_entry_t entry; | ||
1371 | |||
1372 | pgdp = pgd_offset(current->mm, addr); | ||
1373 | if (!pgd_present(*pgdp)) | ||
1374 | return 0; | ||
1375 | pudp = pud_offset(pgdp, addr); | ||
1376 | pud = *pudp; | ||
1377 | if (!pud_present(pud) || pud_large(pud)) | ||
1378 | return 0; | ||
1379 | pmdp = pmd_offset(pudp, addr); | ||
1380 | pmd = *pmdp; | ||
1381 | if (!pmd_present(pmd) || pmd_large(pmd)) | ||
1382 | return 0; | ||
1383 | ptep = pte_offset_map(pmdp, addr); | ||
1384 | pte = *ptep; | ||
1385 | pte_unmap(ptep); | ||
1386 | if (!is_swap_pte(pte)) | ||
1387 | return 0; | ||
1388 | entry = pte_to_swp_entry(pte); | ||
1389 | return is_hwpoison_entry(entry); | ||
1390 | } | ||
1391 | EXPORT_SYMBOL_GPL(is_hwpoison_address); | ||