Skip to content

Commit d883c6c

Browse files
JoonsooKimtorvalds
authored andcommitted
Revert "mm/cma: manage the memory of the CMA area by using the ZONE_MOVABLE"
This reverts the following commits that change CMA design in MM. 3d2054a ("ARM: CMA: avoid double mapping to the CMA area if CONFIG_HIGHMEM=y") 1d47a3e ("mm/cma: remove ALLOC_CMA") bad8c6c ("mm/cma: manage the memory of the CMA area by using the ZONE_MOVABLE") Ville reported a following error on i386. Inode-cache hash table entries: 65536 (order: 6, 262144 bytes) microcode: microcode updated early to revision 0x4, date = 2013-06-28 Initializing CPU#0 Initializing HighMem for node 0 (000377fe:00118000) Initializing Movable for node 0 (00000001:00118000) BUG: Bad page state in process swapper pfn:377fe page:f53effc0 count:0 mapcount:-127 mapping:00000000 index:0x0 flags: 0x80000000() raw: 80000000 00000000 00000000 ffffff80 00000000 00000100 00000200 00000001 page dumped because: nonzero mapcount Modules linked in: CPU: 0 PID: 0 Comm: swapper Not tainted 4.17.0-rc5-elk+ #145 Hardware name: Dell Inc. Latitude E5410/03VXMC, BIOS A15 07/11/2013 Call Trace: dump_stack+0x60/0x96 bad_page+0x9a/0x100 free_pages_check_bad+0x3f/0x60 free_pcppages_bulk+0x29d/0x5b0 free_unref_page_commit+0x84/0xb0 free_unref_page+0x3e/0x70 __free_pages+0x1d/0x20 free_highmem_page+0x19/0x40 add_highpages_with_active_regions+0xab/0xeb set_highmem_pages_init+0x66/0x73 mem_init+0x1b/0x1d7 start_kernel+0x17a/0x363 i386_start_kernel+0x95/0x99 startup_32_smp+0x164/0x168 The reason for this error is that the span of MOVABLE_ZONE is extended to whole node span for future CMA initialization, and, normal memory is wrongly freed here. I submitted the fix and it seems to work, but, another problem happened. It's so late time to fix the later problem so I decide to reverting the series. Reported-by: Ville Syrjälä <[email protected]> Acked-by: Laura Abbott <[email protected]> Acked-by: Michal Hocko <[email protected]> Cc: Andrew Morton <[email protected]> Signed-off-by: Joonsoo Kim <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 577e75e commit d883c6c

File tree

7 files changed

+49
-145
lines changed

7 files changed

+49
-145
lines changed

arch/arm/mm/dma-mapping.c

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -466,12 +466,6 @@ void __init dma_contiguous_early_fixup(phys_addr_t base, unsigned long size)
466466
void __init dma_contiguous_remap(void)
467467
{
468468
int i;
469-
470-
if (!dma_mmu_remap_num)
471-
return;
472-
473-
/* call flush_cache_all() since CMA area would be large enough */
474-
flush_cache_all();
475469
for (i = 0; i < dma_mmu_remap_num; i++) {
476470
phys_addr_t start = dma_mmu_remap[i].base;
477471
phys_addr_t end = start + dma_mmu_remap[i].size;
@@ -504,15 +498,7 @@ void __init dma_contiguous_remap(void)
504498
flush_tlb_kernel_range(__phys_to_virt(start),
505499
__phys_to_virt(end));
506500

507-
/*
508-
* All the memory in CMA region will be on ZONE_MOVABLE.
509-
* If that zone is considered as highmem, the memory in CMA
510-
* region is also considered as highmem even if it's
511-
* physical address belong to lowmem. In this case,
512-
* re-mapping isn't required.
513-
*/
514-
if (!is_highmem_idx(ZONE_MOVABLE))
515-
iotable_init(&map, 1);
501+
iotable_init(&map, 1);
516502
}
517503
}
518504

include/linux/memory_hotplug.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,9 @@ void put_online_mems(void);
216216
void mem_hotplug_begin(void);
217217
void mem_hotplug_done(void);
218218

219+
extern void set_zone_contiguous(struct zone *zone);
220+
extern void clear_zone_contiguous(struct zone *zone);
221+
219222
#else /* ! CONFIG_MEMORY_HOTPLUG */
220223
#define pfn_to_online_page(pfn) \
221224
({ \

include/linux/mm.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2109,7 +2109,6 @@ extern void setup_per_cpu_pageset(void);
21092109

21102110
extern void zone_pcp_update(struct zone *zone);
21112111
extern void zone_pcp_reset(struct zone *zone);
2112-
extern void setup_zone_pageset(struct zone *zone);
21132112

21142113
/* page_alloc.c */
21152114
extern int min_free_kbytes;

mm/cma.c

Lines changed: 11 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
#include <trace/events/cma.h>
4040

4141
#include "cma.h"
42-
#include "internal.h"
4342

4443
struct cma cma_areas[MAX_CMA_AREAS];
4544
unsigned cma_area_count;
@@ -110,25 +109,23 @@ static int __init cma_activate_area(struct cma *cma)
110109
if (!cma->bitmap)
111110
return -ENOMEM;
112111

112+
WARN_ON_ONCE(!pfn_valid(pfn));
113+
zone = page_zone(pfn_to_page(pfn));
114+
113115
do {
114116
unsigned j;
115117

116118
base_pfn = pfn;
117-
if (!pfn_valid(base_pfn))
118-
goto err;
119-
120-
zone = page_zone(pfn_to_page(base_pfn));
121119
for (j = pageblock_nr_pages; j; --j, pfn++) {
122-
if (!pfn_valid(pfn))
123-
goto err;
124-
120+
WARN_ON_ONCE(!pfn_valid(pfn));
125121
/*
126-
* In init_cma_reserved_pageblock(), present_pages
127-
* is adjusted with assumption that all pages in
128-
* the pageblock come from a single zone.
122+
* alloc_contig_range requires the pfn range
123+
* specified to be in the same zone. Make this
124+
* simple by forcing the entire CMA resv range
125+
* to be in the same zone.
129126
*/
130127
if (page_zone(pfn_to_page(pfn)) != zone)
131-
goto err;
128+
goto not_in_zone;
132129
}
133130
init_cma_reserved_pageblock(pfn_to_page(base_pfn));
134131
} while (--i);
@@ -142,7 +139,7 @@ static int __init cma_activate_area(struct cma *cma)
142139

143140
return 0;
144141

145-
err:
142+
not_in_zone:
146143
pr_err("CMA area %s could not be activated\n", cma->name);
147144
kfree(cma->bitmap);
148145
cma->count = 0;
@@ -152,41 +149,6 @@ static int __init cma_activate_area(struct cma *cma)
152149
static int __init cma_init_reserved_areas(void)
153150
{
154151
int i;
155-
struct zone *zone;
156-
pg_data_t *pgdat;
157-
158-
if (!cma_area_count)
159-
return 0;
160-
161-
for_each_online_pgdat(pgdat) {
162-
unsigned long start_pfn = UINT_MAX, end_pfn = 0;
163-
164-
zone = &pgdat->node_zones[ZONE_MOVABLE];
165-
166-
/*
167-
* In this case, we cannot adjust the zone range
168-
* since it is now maximum node span and we don't
169-
* know original zone range.
170-
*/
171-
if (populated_zone(zone))
172-
continue;
173-
174-
for (i = 0; i < cma_area_count; i++) {
175-
if (pfn_to_nid(cma_areas[i].base_pfn) !=
176-
pgdat->node_id)
177-
continue;
178-
179-
start_pfn = min(start_pfn, cma_areas[i].base_pfn);
180-
end_pfn = max(end_pfn, cma_areas[i].base_pfn +
181-
cma_areas[i].count);
182-
}
183-
184-
if (!end_pfn)
185-
continue;
186-
187-
zone->zone_start_pfn = start_pfn;
188-
zone->spanned_pages = end_pfn - start_pfn;
189-
}
190152

191153
for (i = 0; i < cma_area_count; i++) {
192154
int ret = cma_activate_area(&cma_areas[i]);
@@ -195,32 +157,9 @@ static int __init cma_init_reserved_areas(void)
195157
return ret;
196158
}
197159

198-
/*
199-
* Reserved pages for ZONE_MOVABLE are now activated and
200-
* this would change ZONE_MOVABLE's managed page counter and
201-
* the other zones' present counter. We need to re-calculate
202-
* various zone information that depends on this initialization.
203-
*/
204-
build_all_zonelists(NULL);
205-
for_each_populated_zone(zone) {
206-
if (zone_idx(zone) == ZONE_MOVABLE) {
207-
zone_pcp_reset(zone);
208-
setup_zone_pageset(zone);
209-
} else
210-
zone_pcp_update(zone);
211-
212-
set_zone_contiguous(zone);
213-
}
214-
215-
/*
216-
* We need to re-init per zone wmark by calling
217-
* init_per_zone_wmark_min() but doesn't call here because it is
218-
* registered on core_initcall and it will be called later than us.
219-
*/
220-
221160
return 0;
222161
}
223-
pure_initcall(cma_init_reserved_areas);
162+
core_initcall(cma_init_reserved_areas);
224163

225164
/**
226165
* cma_init_reserved_mem() - create custom contiguous area from reserved memory

mm/compaction.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1450,12 +1450,14 @@ static enum compact_result __compaction_suitable(struct zone *zone, int order,
14501450
* if compaction succeeds.
14511451
* For costly orders, we require low watermark instead of min for
14521452
* compaction to proceed to increase its chances.
1453+
* ALLOC_CMA is used, as pages in CMA pageblocks are considered
1454+
* suitable migration targets
14531455
*/
14541456
watermark = (order > PAGE_ALLOC_COSTLY_ORDER) ?
14551457
low_wmark_pages(zone) : min_wmark_pages(zone);
14561458
watermark += compact_gap(order);
14571459
if (!__zone_watermark_ok(zone, 0, watermark, classzone_idx,
1458-
0, wmark_target))
1460+
ALLOC_CMA, wmark_target))
14591461
return COMPACT_SKIPPED;
14601462

14611463
return COMPACT_CONTINUE;

mm/internal.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,9 +168,6 @@ extern void post_alloc_hook(struct page *page, unsigned int order,
168168
gfp_t gfp_flags);
169169
extern int user_min_free_kbytes;
170170

171-
extern void set_zone_contiguous(struct zone *zone);
172-
extern void clear_zone_contiguous(struct zone *zone);
173-
174171
#if defined CONFIG_COMPACTION || defined CONFIG_CMA
175172

176173
/*
@@ -498,6 +495,7 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone,
498495
#define ALLOC_HARDER 0x10 /* try to alloc harder */
499496
#define ALLOC_HIGH 0x20 /* __GFP_HIGH set */
500497
#define ALLOC_CPUSET 0x40 /* check for correct cpuset */
498+
#define ALLOC_CMA 0x80 /* allow allocations from CMA areas */
501499

502500
enum ttu_flags;
503501
struct tlbflush_unmap_batch;

mm/page_alloc.c

Lines changed: 30 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1743,38 +1743,16 @@ void __init page_alloc_init_late(void)
17431743
}
17441744

17451745
#ifdef CONFIG_CMA
1746-
static void __init adjust_present_page_count(struct page *page, long count)
1747-
{
1748-
struct zone *zone = page_zone(page);
1749-
1750-
/* We don't need to hold a lock since it is boot-up process */
1751-
zone->present_pages += count;
1752-
}
1753-
17541746
/* Free whole pageblock and set its migration type to MIGRATE_CMA. */
17551747
void __init init_cma_reserved_pageblock(struct page *page)
17561748
{
17571749
unsigned i = pageblock_nr_pages;
1758-
unsigned long pfn = page_to_pfn(page);
17591750
struct page *p = page;
1760-
int nid = page_to_nid(page);
1761-
1762-
/*
1763-
* ZONE_MOVABLE will steal present pages from other zones by
1764-
* changing page links so page_zone() is changed. Before that,
1765-
* we need to adjust previous zone's page count first.
1766-
*/
1767-
adjust_present_page_count(page, -pageblock_nr_pages);
17681751

17691752
do {
17701753
__ClearPageReserved(p);
17711754
set_page_count(p, 0);
1772-
1773-
/* Steal pages from other zones */
1774-
set_page_links(p, ZONE_MOVABLE, nid, pfn);
1775-
} while (++p, ++pfn, --i);
1776-
1777-
adjust_present_page_count(page, pageblock_nr_pages);
1755+
} while (++p, --i);
17781756

17791757
set_pageblock_migratetype(page, MIGRATE_CMA);
17801758

@@ -2889,7 +2867,7 @@ int __isolate_free_page(struct page *page, unsigned int order)
28892867
* exists.
28902868
*/
28912869
watermark = min_wmark_pages(zone) + (1UL << order);
2892-
if (!zone_watermark_ok(zone, 0, watermark, 0, 0))
2870+
if (!zone_watermark_ok(zone, 0, watermark, 0, ALLOC_CMA))
28932871
return 0;
28942872

28952873
__mod_zone_freepage_state(zone, -(1UL << order), mt);
@@ -3165,6 +3143,12 @@ bool __zone_watermark_ok(struct zone *z, unsigned int order, unsigned long mark,
31653143
}
31663144

31673145

3146+
#ifdef CONFIG_CMA
3147+
/* If allocation can't use CMA areas don't use free CMA pages */
3148+
if (!(alloc_flags & ALLOC_CMA))
3149+
free_pages -= zone_page_state(z, NR_FREE_CMA_PAGES);
3150+
#endif
3151+
31683152
/*
31693153
* Check watermarks for an order-0 allocation request. If these
31703154
* are not met, then a high-order request also cannot go ahead
@@ -3191,8 +3175,10 @@ bool __zone_watermark_ok(struct zone *z, unsigned int order, unsigned long mark,
31913175
}
31923176

31933177
#ifdef CONFIG_CMA
3194-
if (!list_empty(&area->free_list[MIGRATE_CMA]))
3178+
if ((alloc_flags & ALLOC_CMA) &&
3179+
!list_empty(&area->free_list[MIGRATE_CMA])) {
31953180
return true;
3181+
}
31963182
#endif
31973183
if (alloc_harder &&
31983184
!list_empty(&area->free_list[MIGRATE_HIGHATOMIC]))
@@ -3212,6 +3198,13 @@ static inline bool zone_watermark_fast(struct zone *z, unsigned int order,
32123198
unsigned long mark, int classzone_idx, unsigned int alloc_flags)
32133199
{
32143200
long free_pages = zone_page_state(z, NR_FREE_PAGES);
3201+
long cma_pages = 0;
3202+
3203+
#ifdef CONFIG_CMA
3204+
/* If allocation can't use CMA areas don't use free CMA pages */
3205+
if (!(alloc_flags & ALLOC_CMA))
3206+
cma_pages = zone_page_state(z, NR_FREE_CMA_PAGES);
3207+
#endif
32153208

32163209
/*
32173210
* Fast check for order-0 only. If this fails then the reserves
@@ -3220,7 +3213,7 @@ static inline bool zone_watermark_fast(struct zone *z, unsigned int order,
32203213
* the caller is !atomic then it'll uselessly search the free
32213214
* list. That corner case is then slower but it is harmless.
32223215
*/
3223-
if (!order && free_pages > mark + z->lowmem_reserve[classzone_idx])
3216+
if (!order && (free_pages - cma_pages) > mark + z->lowmem_reserve[classzone_idx])
32243217
return true;
32253218

32263219
return __zone_watermark_ok(z, order, mark, classzone_idx, alloc_flags,
@@ -3856,6 +3849,10 @@ gfp_to_alloc_flags(gfp_t gfp_mask)
38563849
} else if (unlikely(rt_task(current)) && !in_interrupt())
38573850
alloc_flags |= ALLOC_HARDER;
38583851

3852+
#ifdef CONFIG_CMA
3853+
if (gfpflags_to_migratetype(gfp_mask) == MIGRATE_MOVABLE)
3854+
alloc_flags |= ALLOC_CMA;
3855+
#endif
38593856
return alloc_flags;
38603857
}
38613858

@@ -4322,6 +4319,9 @@ static inline bool prepare_alloc_pages(gfp_t gfp_mask, unsigned int order,
43224319
if (should_fail_alloc_page(gfp_mask, order))
43234320
return false;
43244321

4322+
if (IS_ENABLED(CONFIG_CMA) && ac->migratetype == MIGRATE_MOVABLE)
4323+
*alloc_flags |= ALLOC_CMA;
4324+
43254325
return true;
43264326
}
43274327

@@ -6204,7 +6204,6 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat)
62046204
{
62056205
enum zone_type j;
62066206
int nid = pgdat->node_id;
6207-
unsigned long node_end_pfn = 0;
62086207

62096208
pgdat_resize_init(pgdat);
62106209
#ifdef CONFIG_NUMA_BALANCING
@@ -6232,13 +6231,9 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat)
62326231
struct zone *zone = pgdat->node_zones + j;
62336232
unsigned long size, realsize, freesize, memmap_pages;
62346233
unsigned long zone_start_pfn = zone->zone_start_pfn;
6235-
unsigned long movable_size = 0;
62366234

62376235
size = zone->spanned_pages;
62386236
realsize = freesize = zone->present_pages;
6239-
if (zone_end_pfn(zone) > node_end_pfn)
6240-
node_end_pfn = zone_end_pfn(zone);
6241-
62426237

62436238
/*
62446239
* Adjust freesize so that it accounts for how much memory
@@ -6287,30 +6282,12 @@ static void __paginginit free_area_init_core(struct pglist_data *pgdat)
62876282
zone_seqlock_init(zone);
62886283
zone_pcp_init(zone);
62896284

6290-
/*
6291-
* The size of the CMA area is unknown now so we need to
6292-
* prepare the memory for the usemap at maximum.
6293-
*/
6294-
if (IS_ENABLED(CONFIG_CMA) && j == ZONE_MOVABLE &&
6295-
pgdat->node_spanned_pages) {
6296-
movable_size = node_end_pfn - pgdat->node_start_pfn;
6297-
}
6298-
6299-
if (!size && !movable_size)
6285+
if (!size)
63006286
continue;
63016287

63026288
set_pageblock_order();
6303-
if (movable_size) {
6304-
zone->zone_start_pfn = pgdat->node_start_pfn;
6305-
zone->spanned_pages = movable_size;
6306-
setup_usemap(pgdat, zone,
6307-
pgdat->node_start_pfn, movable_size);
6308-
init_currently_empty_zone(zone,
6309-
pgdat->node_start_pfn, movable_size);
6310-
} else {
6311-
setup_usemap(pgdat, zone, zone_start_pfn, size);
6312-
init_currently_empty_zone(zone, zone_start_pfn, size);
6313-
}
6289+
setup_usemap(pgdat, zone, zone_start_pfn, size);
6290+
init_currently_empty_zone(zone, zone_start_pfn, size);
63146291
memmap_init(size, nid, j, zone_start_pfn);
63156292
}
63166293
}
@@ -7951,7 +7928,7 @@ void free_contig_range(unsigned long pfn, unsigned nr_pages)
79517928
}
79527929
#endif
79537930

7954-
#if defined CONFIG_MEMORY_HOTPLUG || defined CONFIG_CMA
7931+
#ifdef CONFIG_MEMORY_HOTPLUG
79557932
/*
79567933
* The zone indicated has a new number of managed_pages; batch sizes and percpu
79577934
* page high values need to be recalulated.

0 commit comments

Comments
 (0)