Revert "UPSTREAM: mm, page_alloc: spread allocations across zones before introducing fragmentation"
This reverts commit 8ad4b225e8
.
Reason for revert: revert customized code
Bug: 140544941
Test: boot
Signed-off-by: Minchan Kim <minchan@google.com>
Signed-off-by: Martin Liu <liumartin@google.com>
Signed-off-by: Mark Salyzyn <salyzyn@google.com>
Signed-off-by: Suren Baghdasaryan <surenb@google.com>
Change-Id: I340fb8af98b3f6e033fd5463b082fbca43abe941
This commit is contained in:
parent
5e86f20f4f
commit
82d4e597c4
2 changed files with 19 additions and 107 deletions
|
@ -490,15 +490,10 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone,
|
||||||
#define ALLOC_OOM ALLOC_NO_WATERMARKS
|
#define ALLOC_OOM ALLOC_NO_WATERMARKS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ALLOC_HARDER 0x10 /* try to alloc harder */
|
#define ALLOC_HARDER 0x10 /* try to alloc harder */
|
||||||
#define ALLOC_HIGH 0x20 /* __GFP_HIGH set */
|
#define ALLOC_HIGH 0x20 /* __GFP_HIGH set */
|
||||||
#define ALLOC_CPUSET 0x40 /* check for correct cpuset */
|
#define ALLOC_CPUSET 0x40 /* check for correct cpuset */
|
||||||
#define ALLOC_CMA 0x80 /* allow allocations from CMA areas */
|
#define ALLOC_CMA 0x80 /* allow allocations from CMA areas */
|
||||||
#ifdef CONFIG_ZONE_DMA32
|
|
||||||
#define ALLOC_NOFRAGMENT 0x100 /* avoid mixing pageblock types */
|
|
||||||
#else
|
|
||||||
#define ALLOC_NOFRAGMENT 0x0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum ttu_flags;
|
enum ttu_flags;
|
||||||
struct tlbflush_unmap_batch;
|
struct tlbflush_unmap_batch;
|
||||||
|
|
113
mm/page_alloc.c
113
mm/page_alloc.c
|
@ -2464,30 +2464,20 @@ static bool unreserve_highatomic_pageblock(const struct alloc_context *ac,
|
||||||
* condition simpler.
|
* condition simpler.
|
||||||
*/
|
*/
|
||||||
static __always_inline bool
|
static __always_inline bool
|
||||||
__rmqueue_fallback(struct zone *zone, int order, int start_migratetype,
|
__rmqueue_fallback(struct zone *zone, int order, int start_migratetype)
|
||||||
unsigned int alloc_flags)
|
|
||||||
{
|
{
|
||||||
struct free_area *area;
|
struct free_area *area;
|
||||||
int current_order;
|
int current_order;
|
||||||
int min_order = order;
|
|
||||||
struct page *page;
|
struct page *page;
|
||||||
int fallback_mt;
|
int fallback_mt;
|
||||||
bool can_steal;
|
bool can_steal;
|
||||||
|
|
||||||
/*
|
|
||||||
* Do not steal pages from freelists belonging to other pageblocks
|
|
||||||
* i.e. orders < pageblock_order. If there are no local zones free,
|
|
||||||
* the zonelists will be reiterated without ALLOC_NOFRAGMENT.
|
|
||||||
*/
|
|
||||||
if (alloc_flags & ALLOC_NOFRAGMENT)
|
|
||||||
min_order = pageblock_order;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Find the largest available free page in the other list. This roughly
|
* Find the largest available free page in the other list. This roughly
|
||||||
* approximates finding the pageblock with the most free pages, which
|
* approximates finding the pageblock with the most free pages, which
|
||||||
* would be too costly to do exactly.
|
* would be too costly to do exactly.
|
||||||
*/
|
*/
|
||||||
for (current_order = MAX_ORDER - 1; current_order >= min_order;
|
for (current_order = MAX_ORDER - 1; current_order >= order;
|
||||||
--current_order) {
|
--current_order) {
|
||||||
area = &(zone->free_area[current_order]);
|
area = &(zone->free_area[current_order]);
|
||||||
fallback_mt = find_suitable_fallback(area, current_order,
|
fallback_mt = find_suitable_fallback(area, current_order,
|
||||||
|
@ -2546,16 +2536,14 @@ __rmqueue_fallback(struct zone *zone, int order, int start_migratetype,
|
||||||
* Call me with the zone->lock already held.
|
* Call me with the zone->lock already held.
|
||||||
*/
|
*/
|
||||||
static __always_inline struct page *
|
static __always_inline struct page *
|
||||||
__rmqueue(struct zone *zone, unsigned int order, int migratetype,
|
__rmqueue(struct zone *zone, unsigned int order, int migratetype)
|
||||||
unsigned int alloc_flags)
|
|
||||||
{
|
{
|
||||||
struct page *page;
|
struct page *page;
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
page = __rmqueue_smallest(zone, order, migratetype);
|
page = __rmqueue_smallest(zone, order, migratetype);
|
||||||
|
|
||||||
if (unlikely(!page) && __rmqueue_fallback(zone, order, migratetype,
|
if (unlikely(!page) && __rmqueue_fallback(zone, order, migratetype))
|
||||||
alloc_flags))
|
|
||||||
goto retry;
|
goto retry;
|
||||||
|
|
||||||
trace_mm_page_alloc_zone_locked(page, order, migratetype);
|
trace_mm_page_alloc_zone_locked(page, order, migratetype);
|
||||||
|
@ -2587,7 +2575,7 @@ static inline struct page *__rmqueue_cma(struct zone *zone, unsigned int order)
|
||||||
*/
|
*/
|
||||||
static int rmqueue_bulk(struct zone *zone, unsigned int order,
|
static int rmqueue_bulk(struct zone *zone, unsigned int order,
|
||||||
unsigned long count, struct list_head *list,
|
unsigned long count, struct list_head *list,
|
||||||
int migratetype, unsigned int alloc_flags)
|
int migratetype)
|
||||||
{
|
{
|
||||||
int i, alloced = 0;
|
int i, alloced = 0;
|
||||||
|
|
||||||
|
@ -2603,7 +2591,7 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order,
|
||||||
if (is_migrate_cma(migratetype))
|
if (is_migrate_cma(migratetype))
|
||||||
page = __rmqueue_cma(zone, order);
|
page = __rmqueue_cma(zone, order);
|
||||||
else
|
else
|
||||||
page = __rmqueue(zone, order, migratetype, alloc_flags);
|
page = __rmqueue(zone, order, migratetype);
|
||||||
|
|
||||||
if (unlikely(page == NULL))
|
if (unlikely(page == NULL))
|
||||||
break;
|
break;
|
||||||
|
@ -2646,14 +2634,14 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order,
|
||||||
*/
|
*/
|
||||||
static struct list_head *get_populated_pcp_list(struct zone *zone,
|
static struct list_head *get_populated_pcp_list(struct zone *zone,
|
||||||
unsigned int order, struct per_cpu_pages *pcp,
|
unsigned int order, struct per_cpu_pages *pcp,
|
||||||
int migratetype, unsigned int alloc_flags)
|
int migratetype)
|
||||||
{
|
{
|
||||||
struct list_head *list = &pcp->lists[migratetype];
|
struct list_head *list = &pcp->lists[migratetype];
|
||||||
|
|
||||||
if (list_empty(list)) {
|
if (list_empty(list)) {
|
||||||
pcp->count += rmqueue_bulk(zone, order,
|
pcp->count += rmqueue_bulk(zone, order,
|
||||||
pcp->batch, list,
|
pcp->batch, list,
|
||||||
migratetype, alloc_flags);
|
migratetype);
|
||||||
|
|
||||||
if (list_empty(list))
|
if (list_empty(list))
|
||||||
list = NULL;
|
list = NULL;
|
||||||
|
@ -3082,7 +3070,6 @@ static inline void zone_statistics(struct zone *preferred_zone, struct zone *z)
|
||||||
|
|
||||||
/* Remove page from the per-cpu list, caller must protect the list */
|
/* Remove page from the per-cpu list, caller must protect the list */
|
||||||
static struct page *__rmqueue_pcplist(struct zone *zone, int migratetype,
|
static struct page *__rmqueue_pcplist(struct zone *zone, int migratetype,
|
||||||
unsigned int alloc_flags,
|
|
||||||
struct per_cpu_pages *pcp,
|
struct per_cpu_pages *pcp,
|
||||||
gfp_t gfp_flags)
|
gfp_t gfp_flags)
|
||||||
{
|
{
|
||||||
|
@ -3094,7 +3081,7 @@ static struct page *__rmqueue_pcplist(struct zone *zone, int migratetype,
|
||||||
if (migratetype == MIGRATE_MOVABLE &&
|
if (migratetype == MIGRATE_MOVABLE &&
|
||||||
gfp_flags & __GFP_CMA) {
|
gfp_flags & __GFP_CMA) {
|
||||||
list = get_populated_pcp_list(zone, 0, pcp,
|
list = get_populated_pcp_list(zone, 0, pcp,
|
||||||
get_cma_migrate_type(), alloc_flags);
|
get_cma_migrate_type());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list == NULL) {
|
if (list == NULL) {
|
||||||
|
@ -3103,7 +3090,7 @@ static struct page *__rmqueue_pcplist(struct zone *zone, int migratetype,
|
||||||
* free CMA pages.
|
* free CMA pages.
|
||||||
*/
|
*/
|
||||||
list = get_populated_pcp_list(zone, 0, pcp,
|
list = get_populated_pcp_list(zone, 0, pcp,
|
||||||
migratetype, alloc_flags);
|
migratetype);
|
||||||
if (unlikely(list == NULL) ||
|
if (unlikely(list == NULL) ||
|
||||||
unlikely(list_empty(list)))
|
unlikely(list_empty(list)))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -3120,8 +3107,7 @@ static struct page *__rmqueue_pcplist(struct zone *zone, int migratetype,
|
||||||
/* Lock and remove page from the per-cpu list */
|
/* Lock and remove page from the per-cpu list */
|
||||||
static struct page *rmqueue_pcplist(struct zone *preferred_zone,
|
static struct page *rmqueue_pcplist(struct zone *preferred_zone,
|
||||||
struct zone *zone, unsigned int order,
|
struct zone *zone, unsigned int order,
|
||||||
gfp_t gfp_flags, int migratetype,
|
gfp_t gfp_flags, int migratetype)
|
||||||
unsigned int alloc_flags)
|
|
||||||
{
|
{
|
||||||
struct per_cpu_pages *pcp;
|
struct per_cpu_pages *pcp;
|
||||||
struct page *page;
|
struct page *page;
|
||||||
|
@ -3129,7 +3115,7 @@ static struct page *rmqueue_pcplist(struct zone *preferred_zone,
|
||||||
|
|
||||||
local_irq_save(flags);
|
local_irq_save(flags);
|
||||||
pcp = &this_cpu_ptr(zone->pageset)->pcp;
|
pcp = &this_cpu_ptr(zone->pageset)->pcp;
|
||||||
page = __rmqueue_pcplist(zone, migratetype, alloc_flags, pcp,
|
page = __rmqueue_pcplist(zone, migratetype, pcp,
|
||||||
gfp_flags);
|
gfp_flags);
|
||||||
if (page) {
|
if (page) {
|
||||||
__count_zid_vm_events(PGALLOC, page_zonenum(page), 1 << order);
|
__count_zid_vm_events(PGALLOC, page_zonenum(page), 1 << order);
|
||||||
|
@ -3153,7 +3139,7 @@ struct page *rmqueue(struct zone *preferred_zone,
|
||||||
|
|
||||||
if (likely(order == 0)) {
|
if (likely(order == 0)) {
|
||||||
page = rmqueue_pcplist(preferred_zone, zone, order,
|
page = rmqueue_pcplist(preferred_zone, zone, order,
|
||||||
gfp_flags, migratetype, alloc_flags);
|
gfp_flags, migratetype);
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3178,7 +3164,7 @@ struct page *rmqueue(struct zone *preferred_zone,
|
||||||
page = __rmqueue_cma(zone, order);
|
page = __rmqueue_cma(zone, order);
|
||||||
|
|
||||||
if (!page)
|
if (!page)
|
||||||
page = __rmqueue(zone, order, migratetype, alloc_flags);
|
page = __rmqueue(zone, order, migratetype);
|
||||||
} while (page && check_new_pages(page, order));
|
} while (page && check_new_pages(page, order));
|
||||||
|
|
||||||
spin_unlock(&zone->lock);
|
spin_unlock(&zone->lock);
|
||||||
|
@ -3430,40 +3416,6 @@ static bool zone_allows_reclaim(struct zone *local_zone, struct zone *zone)
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_NUMA */
|
#endif /* CONFIG_NUMA */
|
||||||
|
|
||||||
#ifdef CONFIG_ZONE_DMA32
|
|
||||||
/*
|
|
||||||
* The restriction on ZONE_DMA32 as being a suitable zone to use to avoid
|
|
||||||
* fragmentation is subtle. If the preferred zone was HIGHMEM then
|
|
||||||
* premature use of a lower zone may cause lowmem pressure problems that
|
|
||||||
* are worse than fragmentation. If the next zone is ZONE_DMA then it is
|
|
||||||
* probably too small. It only makes sense to spread allocations to avoid
|
|
||||||
* fragmentation between the Normal and DMA32 zones.
|
|
||||||
*/
|
|
||||||
static inline unsigned int
|
|
||||||
alloc_flags_nofragment(struct zone *zone)
|
|
||||||
{
|
|
||||||
if (zone_idx(zone) != ZONE_NORMAL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If ZONE_DMA32 exists, assume it is the one after ZONE_NORMAL and
|
|
||||||
* the pointer is within zone->zone_pgdat->node_zones[]. Also assume
|
|
||||||
* on UMA that if Normal is populated then so is DMA32.
|
|
||||||
*/
|
|
||||||
BUILD_BUG_ON(ZONE_NORMAL - ZONE_DMA32 != 1);
|
|
||||||
if (nr_online_nodes > 1 && !populated_zone(--zone))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return ALLOC_NOFRAGMENT;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static inline unsigned int
|
|
||||||
alloc_flags_nofragment(struct zone *zone)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* get_page_from_freelist goes through the zonelist trying to allocate
|
* get_page_from_freelist goes through the zonelist trying to allocate
|
||||||
* a page.
|
* a page.
|
||||||
|
@ -3472,18 +3424,14 @@ static struct page *
|
||||||
get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags,
|
get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags,
|
||||||
const struct alloc_context *ac)
|
const struct alloc_context *ac)
|
||||||
{
|
{
|
||||||
struct zoneref *z;
|
struct zoneref *z = ac->preferred_zoneref;
|
||||||
struct zone *zone;
|
struct zone *zone;
|
||||||
struct pglist_data *last_pgdat_dirty_limit = NULL;
|
struct pglist_data *last_pgdat_dirty_limit = NULL;
|
||||||
bool no_fallback;
|
|
||||||
|
|
||||||
retry:
|
|
||||||
/*
|
/*
|
||||||
* Scan zonelist, looking for a zone with enough free.
|
* Scan zonelist, looking for a zone with enough free.
|
||||||
* See also __cpuset_node_allowed() comment in kernel/cpuset.c.
|
* See also __cpuset_node_allowed() comment in kernel/cpuset.c.
|
||||||
*/
|
*/
|
||||||
no_fallback = alloc_flags & ALLOC_NOFRAGMENT;
|
|
||||||
z = ac->preferred_zoneref;
|
|
||||||
for_next_zone_zonelist_nodemask(zone, z, ac->zonelist, ac->high_zoneidx,
|
for_next_zone_zonelist_nodemask(zone, z, ac->zonelist, ac->high_zoneidx,
|
||||||
ac->nodemask) {
|
ac->nodemask) {
|
||||||
struct page *page;
|
struct page *page;
|
||||||
|
@ -3522,22 +3470,6 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (no_fallback && nr_online_nodes > 1 &&
|
|
||||||
zone != ac->preferred_zoneref->zone) {
|
|
||||||
int local_nid;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If moving to a remote node, retry but allow
|
|
||||||
* fragmenting fallbacks. Locality is more important
|
|
||||||
* than fragmentation avoidance.
|
|
||||||
*/
|
|
||||||
local_nid = zone_to_nid(ac->preferred_zoneref->zone);
|
|
||||||
if (zone_to_nid(zone) != local_nid) {
|
|
||||||
alloc_flags &= ~ALLOC_NOFRAGMENT;
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mark = zone->watermark[alloc_flags & ALLOC_WMARK_MASK];
|
mark = zone->watermark[alloc_flags & ALLOC_WMARK_MASK];
|
||||||
if (!zone_watermark_fast(zone, order, mark,
|
if (!zone_watermark_fast(zone, order, mark,
|
||||||
ac_classzone_idx(ac), alloc_flags)) {
|
ac_classzone_idx(ac), alloc_flags)) {
|
||||||
|
@ -3605,15 +3537,6 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int alloc_flags,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* It's possible on a UMA machine to get through all zones that are
|
|
||||||
* fragmented. If avoiding fragmentation, reset and try again.
|
|
||||||
*/
|
|
||||||
if (no_fallback) {
|
|
||||||
alloc_flags &= ~ALLOC_NOFRAGMENT;
|
|
||||||
goto retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4623,12 +4546,6 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, int preferred_nid,
|
||||||
|
|
||||||
finalise_ac(gfp_mask, &ac);
|
finalise_ac(gfp_mask, &ac);
|
||||||
|
|
||||||
/*
|
|
||||||
* Forbid the first pass from falling back to types that fragment
|
|
||||||
* memory until all local zones are considered.
|
|
||||||
*/
|
|
||||||
alloc_flags |= alloc_flags_nofragment(ac.preferred_zoneref->zone);
|
|
||||||
|
|
||||||
/* First allocation attempt */
|
/* First allocation attempt */
|
||||||
page = get_page_from_freelist(alloc_mask, order, alloc_flags, &ac);
|
page = get_page_from_freelist(alloc_mask, order, alloc_flags, &ac);
|
||||||
if (likely(page))
|
if (likely(page))
|
||||||
|
|
Loading…
Reference in a new issue