Skip to content

Commit b37ff71

Browse files
Naoya Horiguchitorvalds
authored andcommitted
mm: hwpoison: change PageHWPoison behavior on hugetlb pages
We'd like to narrow down the error region in memory error on hugetlb pages. However, currently we set PageHWPoison flags on all subpages in the error hugepage and add # of subpages to num_hwpoison_pages, which doesn't fit our purpose. So this patch changes the behavior and we only set PageHWPoison on the head page then increase num_hwpoison_pages only by 1. This is a preparation for narrow-down part which comes in later patches. Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Naoya Horiguchi <[email protected]> Cc: Michal Hocko <[email protected]> Cc: "Aneesh Kumar K.V" <[email protected]> Cc: Anshuman Khandual <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 09612fa commit b37ff71

File tree

2 files changed

+24
-72
lines changed

2 files changed

+24
-72
lines changed

include/linux/swapops.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -196,15 +196,6 @@ static inline void num_poisoned_pages_dec(void)
196196
atomic_long_dec(&num_poisoned_pages);
197197
}
198198

199-
static inline void num_poisoned_pages_add(long num)
200-
{
201-
atomic_long_add(num, &num_poisoned_pages);
202-
}
203-
204-
static inline void num_poisoned_pages_sub(long num)
205-
{
206-
atomic_long_sub(num, &num_poisoned_pages);
207-
}
208199
#else
209200

210201
static inline swp_entry_t make_hwpoison_entry(struct page *page)

mm/memory-failure.c

Lines changed: 24 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1009,22 +1009,6 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,
10091009
return unmap_success;
10101010
}
10111011

1012-
static void set_page_hwpoison_huge_page(struct page *hpage)
1013-
{
1014-
int i;
1015-
int nr_pages = 1 << compound_order(hpage);
1016-
for (i = 0; i < nr_pages; i++)
1017-
SetPageHWPoison(hpage + i);
1018-
}
1019-
1020-
static void clear_page_hwpoison_huge_page(struct page *hpage)
1021-
{
1022-
int i;
1023-
int nr_pages = 1 << compound_order(hpage);
1024-
for (i = 0; i < nr_pages; i++)
1025-
ClearPageHWPoison(hpage + i);
1026-
}
1027-
10281012
/**
10291013
* memory_failure - Handle memory failure of a page.
10301014
* @pfn: Page Number of the corrupted page
@@ -1050,7 +1034,6 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
10501034
struct page *hpage;
10511035
struct page *orig_head;
10521036
int res;
1053-
unsigned int nr_pages;
10541037
unsigned long page_flags;
10551038

10561039
if (!sysctl_memory_failure_recovery)
@@ -1064,24 +1047,23 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
10641047

10651048
p = pfn_to_page(pfn);
10661049
orig_head = hpage = compound_head(p);
1050+
1051+
/* tmporary check code, to be updated in later patches */
1052+
if (PageHuge(p)) {
1053+
if (TestSetPageHWPoison(hpage)) {
1054+
pr_err("Memory failure: %#lx: already hardware poisoned\n", pfn);
1055+
return 0;
1056+
}
1057+
goto tmp;
1058+
}
10671059
if (TestSetPageHWPoison(p)) {
10681060
pr_err("Memory failure: %#lx: already hardware poisoned\n",
10691061
pfn);
10701062
return 0;
10711063
}
10721064

1073-
/*
1074-
* Currently errors on hugetlbfs pages are measured in hugepage units,
1075-
* so nr_pages should be 1 << compound_order. OTOH when errors are on
1076-
* transparent hugepages, they are supposed to be split and error
1077-
* measurement is done in normal page units. So nr_pages should be one
1078-
* in this case.
1079-
*/
1080-
if (PageHuge(p))
1081-
nr_pages = 1 << compound_order(hpage);
1082-
else /* normal page or thp */
1083-
nr_pages = 1;
1084-
num_poisoned_pages_add(nr_pages);
1065+
tmp:
1066+
num_poisoned_pages_inc();
10851067

10861068
/*
10871069
* We need/can do nothing about count=0 pages.
@@ -1109,12 +1091,11 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
11091091
if (PageHWPoison(hpage)) {
11101092
if ((hwpoison_filter(p) && TestClearPageHWPoison(p))
11111093
|| (p != hpage && TestSetPageHWPoison(hpage))) {
1112-
num_poisoned_pages_sub(nr_pages);
1094+
num_poisoned_pages_dec();
11131095
unlock_page(hpage);
11141096
return 0;
11151097
}
11161098
}
1117-
set_page_hwpoison_huge_page(hpage);
11181099
res = dequeue_hwpoisoned_huge_page(hpage);
11191100
action_result(pfn, MF_MSG_FREE_HUGE,
11201101
res ? MF_IGNORED : MF_DELAYED);
@@ -1137,7 +1118,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
11371118
pr_err("Memory failure: %#lx: thp split failed\n",
11381119
pfn);
11391120
if (TestClearPageHWPoison(p))
1140-
num_poisoned_pages_sub(nr_pages);
1121+
num_poisoned_pages_dec();
11411122
put_hwpoison_page(p);
11421123
return -EBUSY;
11431124
}
@@ -1193,14 +1174,14 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
11931174
*/
11941175
if (!PageHWPoison(p)) {
11951176
pr_err("Memory failure: %#lx: just unpoisoned\n", pfn);
1196-
num_poisoned_pages_sub(nr_pages);
1177+
num_poisoned_pages_dec();
11971178
unlock_page(hpage);
11981179
put_hwpoison_page(hpage);
11991180
return 0;
12001181
}
12011182
if (hwpoison_filter(p)) {
12021183
if (TestClearPageHWPoison(p))
1203-
num_poisoned_pages_sub(nr_pages);
1184+
num_poisoned_pages_dec();
12041185
unlock_page(hpage);
12051186
put_hwpoison_page(hpage);
12061187
return 0;
@@ -1219,14 +1200,6 @@ int memory_failure(unsigned long pfn, int trapno, int flags)
12191200
put_hwpoison_page(hpage);
12201201
return 0;
12211202
}
1222-
/*
1223-
* Set PG_hwpoison on all pages in an error hugepage,
1224-
* because containment is done in hugepage unit for now.
1225-
* Since we have done TestSetPageHWPoison() for the head page with
1226-
* page lock held, we can safely set PG_hwpoison bits on tail pages.
1227-
*/
1228-
if (PageHuge(p))
1229-
set_page_hwpoison_huge_page(hpage);
12301203

12311204
/*
12321205
* It's very difficult to mess with pages currently under IO
@@ -1397,7 +1370,6 @@ int unpoison_memory(unsigned long pfn)
13971370
struct page *page;
13981371
struct page *p;
13991372
int freeit = 0;
1400-
unsigned int nr_pages;
14011373
static DEFINE_RATELIMIT_STATE(unpoison_rs, DEFAULT_RATELIMIT_INTERVAL,
14021374
DEFAULT_RATELIMIT_BURST);
14031375

@@ -1442,8 +1414,6 @@ int unpoison_memory(unsigned long pfn)
14421414
return 0;
14431415
}
14441416

1445-
nr_pages = 1 << compound_order(page);
1446-
14471417
if (!get_hwpoison_page(p)) {
14481418
/*
14491419
* Since HWPoisoned hugepage should have non-zero refcount,
@@ -1473,10 +1443,8 @@ int unpoison_memory(unsigned long pfn)
14731443
if (TestClearPageHWPoison(page)) {
14741444
unpoison_pr_info("Unpoison: Software-unpoisoned page %#lx\n",
14751445
pfn, &unpoison_rs);
1476-
num_poisoned_pages_sub(nr_pages);
1446+
num_poisoned_pages_dec();
14771447
freeit = 1;
1478-
if (PageHuge(page))
1479-
clear_page_hwpoison_huge_page(page);
14801448
}
14811449
unlock_page(page);
14821450

@@ -1608,14 +1576,10 @@ static int soft_offline_huge_page(struct page *page, int flags)
16081576
ret = -EIO;
16091577
} else {
16101578
/* overcommit hugetlb page will be freed to buddy */
1611-
if (PageHuge(page)) {
1612-
set_page_hwpoison_huge_page(hpage);
1579+
SetPageHWPoison(page);
1580+
if (PageHuge(page))
16131581
dequeue_hwpoisoned_huge_page(hpage);
1614-
num_poisoned_pages_add(1 << compound_order(hpage));
1615-
} else {
1616-
SetPageHWPoison(page);
1617-
num_poisoned_pages_inc();
1618-
}
1582+
num_poisoned_pages_inc();
16191583
}
16201584
return ret;
16211585
}
@@ -1731,15 +1695,12 @@ static int soft_offline_in_use_page(struct page *page, int flags)
17311695

17321696
static void soft_offline_free_page(struct page *page)
17331697
{
1734-
if (PageHuge(page)) {
1735-
struct page *hpage = compound_head(page);
1698+
struct page *head = compound_head(page);
17361699

1737-
set_page_hwpoison_huge_page(hpage);
1738-
if (!dequeue_hwpoisoned_huge_page(hpage))
1739-
num_poisoned_pages_add(1 << compound_order(hpage));
1740-
} else {
1741-
if (!TestSetPageHWPoison(page))
1742-
num_poisoned_pages_inc();
1700+
if (!TestSetPageHWPoison(head)) {
1701+
num_poisoned_pages_inc();
1702+
if (PageHuge(head))
1703+
dequeue_hwpoisoned_huge_page(head);
17431704
}
17441705
}
17451706

0 commit comments

Comments
 (0)