* [PATCH] drivers: memory: check for missing sections in test_pages_in_a_zone
@ 2015-12-11 22:21 Andrew Banman
2015-12-11 22:52 ` andrew banman
0 siblings, 1 reply; 3+ messages in thread
From: Andrew Banman @ 2015-12-11 22:21 UTC (permalink / raw)
To: Andrew Morton
Cc: Andrew Banman, Russ Anderson, Alex Thorlton, Yinghai Lu, Greg KH,
Seth Jennings, linux-kernel
test_pages_in_a_zone does not account for the possibility of missing
sections in the given pfn range. pfn_valid_within always returns 1 when
CONFIG_HOLES_IN_ZONE is not set, allowing invalid pfns from missing
sections to pass the test, leading to a kernel oops.
Wrap an additional pfn loop with PAGES_PER_SECTION granularity to check
for missing sections before proceeding into the zone-check code.
This also prevents a crash from offlining memory devices with missing
sections. Despite this, it may be a good idea to keep the related patch
'[PATCH 3/3] drivers: memory: prohibit offlining of memory blocks
with missing sections' because missing sections in a memory block may lead
to other problems not covered by the scope of this fix.
---
mm/memory_hotplug.c | 32 ++++++++++++++++++++------------
1 file changed, 20 insertions(+), 12 deletions(-)
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 67d488a..0c5f876 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1375,23 +1375,30 @@ int is_mem_section_removable(unsigned long start_pfn, unsigned long nr_pages)
*/
int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn)
{
- unsigned long pfn;
+ unsigned long pfn, sec_end_pfn;
struct zone *zone = NULL;
struct page *page;
int i;
- for (pfn = start_pfn;
+ for (pfn = start_pfn, sec_end_pfn = SECTION_ALIGN_UP(start_pfn);
pfn < end_pfn;
- pfn += MAX_ORDER_NR_PAGES) {
- i = 0;
- /* This is just a CONFIG_HOLES_IN_ZONE check.*/
- while ((i < MAX_ORDER_NR_PAGES) && !pfn_valid_within(pfn + i))
- i++;
- if (i == MAX_ORDER_NR_PAGES)
+ pfn = sec_end_pfn + 1, sec_end_pfn += PAGES_PER_SECTION) {
+ /* Make sure the memory section is present first */
+ if (!present_section_nr(pfn_to_section_nr(pfn)))
continue;
- page = pfn_to_page(pfn + i);
- if (zone && page_zone(page) != zone)
- return 0;
- zone = page_zone(page);
+ for (; pfn < sec_end_pfn && pfn < end_pfn;
+ pfn += MAX_ORDER_NR_PAGES) {
+ i = 0;
+ /* This is just a CONFIG_HOLES_IN_ZONE check.*/
+ while ((i < MAX_ORDER_NR_PAGES) &&
+ !pfn_valid_within(pfn + i))
+ i++;
+ if (i == MAX_ORDER_NR_PAGES)
+ continue;
+ page = pfn_to_page(pfn + i);
+ if (zone && page_zone(page) != zone)
+ return 0;
+ zone = page_zone(page);
+ }
}
return 1;
}
--
1.7.12.4
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] drivers: memory: check for missing sections in test_pages_in_a_zone
2015-12-11 22:21 [PATCH] drivers: memory: check for missing sections in test_pages_in_a_zone Andrew Banman
@ 2015-12-11 22:52 ` andrew banman
0 siblings, 0 replies; 3+ messages in thread
From: andrew banman @ 2015-12-11 22:52 UTC (permalink / raw)
To: Andrew Banman
Cc: Andrew Morton, Russ Anderson, Alex Thorlton, Yinghai Lu, Greg KH,
Seth Jennings, linux-kernel
On Fri, Dec 11, 2015 at 04:21:03PM -0600, Andrew Banman wrote:
> test_pages_in_a_zone does not account for the possibility of missing
> sections in the given pfn range. pfn_valid_within always returns 1 when
> CONFIG_HOLES_IN_ZONE is not set, allowing invalid pfns from missing
> sections to pass the test, leading to a kernel oops.
>
> Wrap an additional pfn loop with PAGES_PER_SECTION granularity to check
> for missing sections before proceeding into the zone-check code.
>
> This also prevents a crash from offlining memory devices with missing
> sections. Despite this, it may be a good idea to keep the related patch
> '[PATCH 3/3] drivers: memory: prohibit offlining of memory blocks
> with missing sections' because missing sections in a memory block may lead
> to other problems not covered by the scope of this fix.
>
> ---
Oops, the signed-off-by got absorbed the email headers. I'll resend. The patch
applies cleanly to the current mainline and to the 4.3.2 and 4.2.7 stable
branches. I'll edit the patch description to reflect that as well.
- Andrew
^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH] drivers: memory: check for missing sections in test_pages_in_a_zone
@ 2015-12-12 1:15 Andrew Banman
0 siblings, 0 replies; 3+ messages in thread
From: Andrew Banman @ 2015-12-12 1:15 UTC (permalink / raw)
To: Andrew Morton
Cc: Andrew Banman, Russ Anderson, Alex Thorlton, Yinghai Lu, Greg KH,
Seth Jennings, linux-kernel
test_pages_in_a_zone does not account for the possibility of missing
sections in the given pfn range. pfn_valid_within always returns 1 when
CONFIG_HOLES_IN_ZONE is not set, allowing invalid pfns from missing
sections to pass the test, leading to a kernel oops.
Wrap an additional pfn loop with PAGES_PER_SECTION granularity to check
for missing sections before proceeding into the zone-check code.
This also prevents a crash from offlining memory devices with missing
sections. Despite this, it may be a good idea to keep the related patch
'[PATCH 3/3] drivers: memory: prohibit offlining of memory blocks
with missing sections' because missing sections in a memory block may lead
to other problems not covered by the scope of this fix.
Patch applies cleanly to current mainline (b9d85451ddd) and the stable
branches back to 3.18.y.
Signed-off-by: Andrew Banman <abanman@sgi.com>
Acked-by: Alex Thorlton <athorlton@sgi.com>
Cc: Russ Anderson <rja@sgi.com>
Cc: Alex Thorlton <athorlton@sgi.com>
Cc: Yinghai Lu <yinghai@kernel.org>
Cc: Greg KH <greg@kroah.com>
Cc: Seth Jennings <sjennings@variantweb.net>
Cc: <linux-kernel@vger.kernel.org>
---
mm/memory_hotplug.c | 32 ++++++++++++++++++++------------
1 file changed, 20 insertions(+), 12 deletions(-)
diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
index 67d488a..0c5f876 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
@@ -1375,23 +1375,30 @@ int is_mem_section_removable(unsigned long start_pfn, unsigned long nr_pages)
*/
int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn)
{
- unsigned long pfn;
+ unsigned long pfn, sec_end_pfn;
struct zone *zone = NULL;
struct page *page;
int i;
- for (pfn = start_pfn;
+ for (pfn = start_pfn, sec_end_pfn = SECTION_ALIGN_UP(start_pfn);
pfn < end_pfn;
- pfn += MAX_ORDER_NR_PAGES) {
- i = 0;
- /* This is just a CONFIG_HOLES_IN_ZONE check.*/
- while ((i < MAX_ORDER_NR_PAGES) && !pfn_valid_within(pfn + i))
- i++;
- if (i == MAX_ORDER_NR_PAGES)
+ pfn = sec_end_pfn + 1, sec_end_pfn += PAGES_PER_SECTION) {
+ /* Make sure the memory section is present first */
+ if (!present_section_nr(pfn_to_section_nr(pfn)))
continue;
- page = pfn_to_page(pfn + i);
- if (zone && page_zone(page) != zone)
- return 0;
- zone = page_zone(page);
+ for (; pfn < sec_end_pfn && pfn < end_pfn;
+ pfn += MAX_ORDER_NR_PAGES) {
+ i = 0;
+ /* This is just a CONFIG_HOLES_IN_ZONE check.*/
+ while ((i < MAX_ORDER_NR_PAGES) &&
+ !pfn_valid_within(pfn + i))
+ i++;
+ if (i == MAX_ORDER_NR_PAGES)
+ continue;
+ page = pfn_to_page(pfn + i);
+ if (zone && page_zone(page) != zone)
+ return 0;
+ zone = page_zone(page);
+ }
}
return 1;
}
--
1.7.12.4
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2015-12-12 1:15 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-12-11 22:21 [PATCH] drivers: memory: check for missing sections in test_pages_in_a_zone Andrew Banman
2015-12-11 22:52 ` andrew banman
2015-12-12 1:15 Andrew Banman
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®