Skip to content

Commit 9cd7555

Browse files
gormanmtorvalds
authored andcommitted
mm, page_alloc: split alloc_pages_nodemask()
alloc_pages_nodemask does a number of preperation steps that determine what zones can be used for the allocation depending on a variety of factors. This is fine but a hypothetical caller that wanted multiple order-0 pages has to do the preparation steps multiple times. This patch structures __alloc_pages_nodemask such that it's relatively easy to build a bulk order-0 page allocator. There is no functional change. Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Mel Gorman <[email protected]> Acked-by: Hillf Danton <[email protected]> Acked-by: Vlastimil Babka <[email protected]> Cc: Jesper Dangaard Brouer <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 066b239 commit 9cd7555

File tree

1 file changed

+46
-29
lines changed

1 file changed

+46
-29
lines changed

mm/page_alloc.c

Lines changed: 46 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3855,60 +3855,77 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
38553855
return page;
38563856
}
38573857

3858-
/*
3859-
* This is the 'heart' of the zoned buddy allocator.
3860-
*/
3861-
struct page *
3862-
__alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
3863-
struct zonelist *zonelist, nodemask_t *nodemask)
3858+
static inline bool prepare_alloc_pages(gfp_t gfp_mask, unsigned int order,
3859+
struct zonelist *zonelist, nodemask_t *nodemask,
3860+
struct alloc_context *ac, gfp_t *alloc_mask,
3861+
unsigned int *alloc_flags)
38643862
{
3865-
struct page *page;
3866-
unsigned int alloc_flags = ALLOC_WMARK_LOW;
3867-
gfp_t alloc_mask = gfp_mask; /* The gfp_t that was actually used for allocation */
3868-
struct alloc_context ac = {
3869-
.high_zoneidx = gfp_zone(gfp_mask),
3870-
.zonelist = zonelist,
3871-
.nodemask = nodemask,
3872-
.migratetype = gfpflags_to_migratetype(gfp_mask),
3873-
};
3863+
ac->high_zoneidx = gfp_zone(gfp_mask);
3864+
ac->zonelist = zonelist;
3865+
ac->nodemask = nodemask;
3866+
ac->migratetype = gfpflags_to_migratetype(gfp_mask);
38743867

38753868
if (cpusets_enabled()) {
3876-
alloc_mask |= __GFP_HARDWALL;
3877-
alloc_flags |= ALLOC_CPUSET;
3878-
if (!ac.nodemask)
3879-
ac.nodemask = &cpuset_current_mems_allowed;
3869+
*alloc_mask |= __GFP_HARDWALL;
3870+
*alloc_flags |= ALLOC_CPUSET;
3871+
if (!ac->nodemask)
3872+
ac->nodemask = &cpuset_current_mems_allowed;
38803873
}
38813874

3882-
gfp_mask &= gfp_allowed_mask;
3883-
38843875
lockdep_trace_alloc(gfp_mask);
38853876

38863877
might_sleep_if(gfp_mask & __GFP_DIRECT_RECLAIM);
38873878

38883879
if (should_fail_alloc_page(gfp_mask, order))
3889-
return NULL;
3880+
return false;
38903881

38913882
/*
38923883
* Check the zones suitable for the gfp_mask contain at least one
38933884
* valid zone. It's possible to have an empty zonelist as a result
38943885
* of __GFP_THISNODE and a memoryless node
38953886
*/
3896-
if (unlikely(!zonelist->_zonerefs->zone))
3897-
return NULL;
3887+
if (unlikely(!ac->zonelist->_zonerefs->zone))
3888+
return false;
38983889

3899-
if (IS_ENABLED(CONFIG_CMA) && ac.migratetype == MIGRATE_MOVABLE)
3900-
alloc_flags |= ALLOC_CMA;
3890+
if (IS_ENABLED(CONFIG_CMA) && ac->migratetype == MIGRATE_MOVABLE)
3891+
*alloc_flags |= ALLOC_CMA;
3892+
3893+
return true;
3894+
}
39013895

3896+
/* Determine whether to spread dirty pages and what the first usable zone */
3897+
static inline void finalise_ac(gfp_t gfp_mask,
3898+
unsigned int order, struct alloc_context *ac)
3899+
{
39023900
/* Dirty zone balancing only done in the fast path */
3903-
ac.spread_dirty_pages = (gfp_mask & __GFP_WRITE);
3901+
ac->spread_dirty_pages = (gfp_mask & __GFP_WRITE);
39043902

39053903
/*
39063904
* The preferred zone is used for statistics but crucially it is
39073905
* also used as the starting point for the zonelist iterator. It
39083906
* may get reset for allocations that ignore memory policies.
39093907
*/
3910-
ac.preferred_zoneref = first_zones_zonelist(ac.zonelist,
3911-
ac.high_zoneidx, ac.nodemask);
3908+
ac->preferred_zoneref = first_zones_zonelist(ac->zonelist,
3909+
ac->high_zoneidx, ac->nodemask);
3910+
}
3911+
3912+
/*
3913+
* This is the 'heart' of the zoned buddy allocator.
3914+
*/
3915+
struct page *
3916+
__alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
3917+
struct zonelist *zonelist, nodemask_t *nodemask)
3918+
{
3919+
struct page *page;
3920+
unsigned int alloc_flags = ALLOC_WMARK_LOW;
3921+
gfp_t alloc_mask = gfp_mask; /* The gfp_t that was actually used for allocation */
3922+
struct alloc_context ac = { };
3923+
3924+
gfp_mask &= gfp_allowed_mask;
3925+
if (!prepare_alloc_pages(gfp_mask, order, zonelist, nodemask, &ac, &alloc_mask, &alloc_flags))
3926+
return NULL;
3927+
3928+
finalise_ac(gfp_mask, order, &ac);
39123929
if (!ac.preferred_zoneref->zone) {
39133930
page = NULL;
39143931
/*

0 commit comments

Comments
 (0)