Message ID | 20190715081549.32577-2-osalvador@suse.de (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Fixes for sub-section hotplug | expand |
Oscar Salvador <osalvador@suse.de> writes: > deactivate_section checks whether a section is early or not > in order to either call free_map_bootmem() or depopulate_section_memmap(). > Being the former for sections added at boot time, and the latter for > sections hotplugged. > > The problem is that we zero section_mem_map, so the last early_section() > will always report false and the section will not be removed. > > Fix this checking whether a section is early or not at function > entry. > Reviewed-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com> > Fixes: mmotm ("mm/sparsemem: Support sub-section hotplug") > Signed-off-by: Oscar Salvador <osalvador@suse.de> > --- > mm/sparse.c | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > > diff --git a/mm/sparse.c b/mm/sparse.c > index 3267c4001c6d..1e224149aab6 100644 > --- a/mm/sparse.c > +++ b/mm/sparse.c > @@ -738,6 +738,7 @@ static void section_deactivate(unsigned long pfn, unsigned long nr_pages, > DECLARE_BITMAP(map, SUBSECTIONS_PER_SECTION) = { 0 }; > DECLARE_BITMAP(tmp, SUBSECTIONS_PER_SECTION) = { 0 }; > struct mem_section *ms = __pfn_to_section(pfn); > + bool section_is_early = early_section(ms); > struct page *memmap = NULL; > unsigned long *subsection_map = ms->usage > ? &ms->usage->subsection_map[0] : NULL; > @@ -772,7 +773,7 @@ static void section_deactivate(unsigned long pfn, unsigned long nr_pages, > if (bitmap_empty(subsection_map, SUBSECTIONS_PER_SECTION)) { > unsigned long section_nr = pfn_to_section_nr(pfn); > > - if (!early_section(ms)) { > + if (!section_is_early) { > kfree(ms->usage); > ms->usage = NULL; > } > @@ -780,7 +781,7 @@ static void section_deactivate(unsigned long pfn, unsigned long nr_pages, > ms->section_mem_map = sparse_encode_mem_map(NULL, section_nr); > } > > - if (early_section(ms) && memmap) > + if (section_is_early && memmap) > free_map_bootmem(memmap); > else > depopulate_section_memmap(pfn, nr_pages, altmap); > -- > 2.12.3
On Mon, Jul 15, 2019 at 1:16 AM Oscar Salvador <osalvador@suse.de> wrote: > > deactivate_section checks whether a section is early or not > in order to either call free_map_bootmem() or depopulate_section_memmap(). > Being the former for sections added at boot time, and the latter for > sections hotplugged. > > The problem is that we zero section_mem_map, so the last early_section() > will always report false and the section will not be removed. > > Fix this checking whether a section is early or not at function > entry. > > Fixes: mmotm ("mm/sparsemem: Support sub-section hotplug") > Signed-off-by: Oscar Salvador <osalvador@suse.de> > --- > mm/sparse.c | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > > diff --git a/mm/sparse.c b/mm/sparse.c > index 3267c4001c6d..1e224149aab6 100644 > --- a/mm/sparse.c > +++ b/mm/sparse.c > @@ -738,6 +738,7 @@ static void section_deactivate(unsigned long pfn, unsigned long nr_pages, > DECLARE_BITMAP(map, SUBSECTIONS_PER_SECTION) = { 0 }; > DECLARE_BITMAP(tmp, SUBSECTIONS_PER_SECTION) = { 0 }; > struct mem_section *ms = __pfn_to_section(pfn); > + bool section_is_early = early_section(ms); > struct page *memmap = NULL; > unsigned long *subsection_map = ms->usage > ? &ms->usage->subsection_map[0] : NULL; > @@ -772,7 +773,7 @@ static void section_deactivate(unsigned long pfn, unsigned long nr_pages, > if (bitmap_empty(subsection_map, SUBSECTIONS_PER_SECTION)) { > unsigned long section_nr = pfn_to_section_nr(pfn); > > - if (!early_section(ms)) { > + if (!section_is_early) { > kfree(ms->usage); > ms->usage = NULL; > } > @@ -780,7 +781,7 @@ static void section_deactivate(unsigned long pfn, unsigned long nr_pages, > ms->section_mem_map = sparse_encode_mem_map(NULL, section_nr); > } > > - if (early_section(ms) && memmap) > + if (section_is_early && memmap) > free_map_bootmem(memmap); > else > depopulate_section_memmap(pfn, nr_pages, altmap); Reviewed-by: Dan Williams <dan.j.wiliams@intel.com> In fact, this bug was re-introduced between v9 and v10 as I had seen this bug before, but did not write a reproducer for the unit test.
On 15.07.19 10:15, Oscar Salvador wrote: > deactivate_section checks whether a section is early or not > in order to either call free_map_bootmem() or depopulate_section_memmap(). > Being the former for sections added at boot time, and the latter for > sections hotplugged. > > The problem is that we zero section_mem_map, so the last early_section() > will always report false and the section will not be removed. > > Fix this checking whether a section is early or not at function > entry. > > Fixes: mmotm ("mm/sparsemem: Support sub-section hotplug") > Signed-off-by: Oscar Salvador <osalvador@suse.de> > --- > mm/sparse.c | 5 +++-- > 1 file changed, 3 insertions(+), 2 deletions(-) > > diff --git a/mm/sparse.c b/mm/sparse.c > index 3267c4001c6d..1e224149aab6 100644 > --- a/mm/sparse.c > +++ b/mm/sparse.c > @@ -738,6 +738,7 @@ static void section_deactivate(unsigned long pfn, unsigned long nr_pages, > DECLARE_BITMAP(map, SUBSECTIONS_PER_SECTION) = { 0 }; > DECLARE_BITMAP(tmp, SUBSECTIONS_PER_SECTION) = { 0 }; > struct mem_section *ms = __pfn_to_section(pfn); > + bool section_is_early = early_section(ms); > struct page *memmap = NULL; > unsigned long *subsection_map = ms->usage > ? &ms->usage->subsection_map[0] : NULL; > @@ -772,7 +773,7 @@ static void section_deactivate(unsigned long pfn, unsigned long nr_pages, > if (bitmap_empty(subsection_map, SUBSECTIONS_PER_SECTION)) { > unsigned long section_nr = pfn_to_section_nr(pfn); > > - if (!early_section(ms)) { > + if (!section_is_early) { > kfree(ms->usage); > ms->usage = NULL; > } > @@ -780,7 +781,7 @@ static void section_deactivate(unsigned long pfn, unsigned long nr_pages, > ms->section_mem_map = sparse_encode_mem_map(NULL, section_nr); > } > > - if (early_section(ms) && memmap) > + if (section_is_early && memmap) > free_map_bootmem(memmap); > else > depopulate_section_memmap(pfn, nr_pages, altmap); > Reviewed-by: David Hildenbrand <david@redhat.com>
diff --git a/mm/sparse.c b/mm/sparse.c index 3267c4001c6d..1e224149aab6 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -738,6 +738,7 @@ static void section_deactivate(unsigned long pfn, unsigned long nr_pages, DECLARE_BITMAP(map, SUBSECTIONS_PER_SECTION) = { 0 }; DECLARE_BITMAP(tmp, SUBSECTIONS_PER_SECTION) = { 0 }; struct mem_section *ms = __pfn_to_section(pfn); + bool section_is_early = early_section(ms); struct page *memmap = NULL; unsigned long *subsection_map = ms->usage ? &ms->usage->subsection_map[0] : NULL; @@ -772,7 +773,7 @@ static void section_deactivate(unsigned long pfn, unsigned long nr_pages, if (bitmap_empty(subsection_map, SUBSECTIONS_PER_SECTION)) { unsigned long section_nr = pfn_to_section_nr(pfn); - if (!early_section(ms)) { + if (!section_is_early) { kfree(ms->usage); ms->usage = NULL; } @@ -780,7 +781,7 @@ static void section_deactivate(unsigned long pfn, unsigned long nr_pages, ms->section_mem_map = sparse_encode_mem_map(NULL, section_nr); } - if (early_section(ms) && memmap) + if (section_is_early && memmap) free_map_bootmem(memmap); else depopulate_section_memmap(pfn, nr_pages, altmap);
deactivate_section checks whether a section is early or not in order to either call free_map_bootmem() or depopulate_section_memmap(). Being the former for sections added at boot time, and the latter for sections hotplugged. The problem is that we zero section_mem_map, so the last early_section() will always report false and the section will not be removed. Fix this checking whether a section is early or not at function entry. Fixes: mmotm ("mm/sparsemem: Support sub-section hotplug") Signed-off-by: Oscar Salvador <osalvador@suse.de> --- mm/sparse.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)