Skip to content

Commit 5ce9bfe

Browse files
tehcastertorvalds
authored andcommitted
mm, page_alloc: move cpuset seqcount checking to slowpath
This is a preparation for the following patch to make review simpler. While the primary motivation is a bug fix, this also simplifies the fast path, although the moved code is only enabled when cpusets are in use. Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Vlastimil Babka <[email protected]> Acked-by: Mel Gorman <[email protected]> Acked-by: Hillf Danton <[email protected]> Cc: Ganapatrao Kulkarni <[email protected]> Cc: Michal Hocko <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 16096c2 commit 5ce9bfe

File tree

1 file changed

+26
-21
lines changed

1 file changed

+26
-21
lines changed

mm/page_alloc.c

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3523,12 +3523,13 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
35233523
struct page *page = NULL;
35243524
unsigned int alloc_flags;
35253525
unsigned long did_some_progress;
3526-
enum compact_priority compact_priority = DEF_COMPACT_PRIORITY;
3526+
enum compact_priority compact_priority;
35273527
enum compact_result compact_result;
3528-
int compaction_retries = 0;
3529-
int no_progress_loops = 0;
3528+
int compaction_retries;
3529+
int no_progress_loops;
35303530
unsigned long alloc_start = jiffies;
35313531
unsigned int stall_timeout = 10 * HZ;
3532+
unsigned int cpuset_mems_cookie;
35323533

35333534
/*
35343535
* In the slowpath, we sanity check order to avoid ever trying to
@@ -3549,6 +3550,12 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
35493550
(__GFP_ATOMIC|__GFP_DIRECT_RECLAIM)))
35503551
gfp_mask &= ~__GFP_ATOMIC;
35513552

3553+
retry_cpuset:
3554+
compaction_retries = 0;
3555+
no_progress_loops = 0;
3556+
compact_priority = DEF_COMPACT_PRIORITY;
3557+
cpuset_mems_cookie = read_mems_allowed_begin();
3558+
35523559
/*
35533560
* The fast path uses conservative alloc_flags to succeed only until
35543561
* kswapd needs to be woken up, and to avoid the cost of setting up
@@ -3720,6 +3727,15 @@ __alloc_pages_slowpath(gfp_t gfp_mask, unsigned int order,
37203727
}
37213728

37223729
nopage:
3730+
/*
3731+
* When updating a task's mems_allowed, it is possible to race with
3732+
* parallel threads in such a way that an allocation can fail while
3733+
* the mask is being updated. If a page allocation is about to fail,
3734+
* check if the cpuset changed during allocation and if so, retry.
3735+
*/
3736+
if (read_mems_allowed_retry(cpuset_mems_cookie))
3737+
goto retry_cpuset;
3738+
37233739
warn_alloc(gfp_mask,
37243740
"page allocation failure: order:%u", order);
37253741
got_pg:
@@ -3734,7 +3750,6 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
37343750
struct zonelist *zonelist, nodemask_t *nodemask)
37353751
{
37363752
struct page *page;
3737-
unsigned int cpuset_mems_cookie;
37383753
unsigned int alloc_flags = ALLOC_WMARK_LOW;
37393754
gfp_t alloc_mask = gfp_mask; /* The gfp_t that was actually used for allocation */
37403755
struct alloc_context ac = {
@@ -3771,9 +3786,6 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
37713786
if (IS_ENABLED(CONFIG_CMA) && ac.migratetype == MIGRATE_MOVABLE)
37723787
alloc_flags |= ALLOC_CMA;
37733788

3774-
retry_cpuset:
3775-
cpuset_mems_cookie = read_mems_allowed_begin();
3776-
37773789
/* Dirty zone balancing only done in the fast path */
37783790
ac.spread_dirty_pages = (gfp_mask & __GFP_WRITE);
37793791

@@ -3786,6 +3798,11 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
37863798
ac.high_zoneidx, ac.nodemask);
37873799
if (!ac.preferred_zoneref->zone) {
37883800
page = NULL;
3801+
/*
3802+
* This might be due to race with cpuset_current_mems_allowed
3803+
* update, so make sure we retry with original nodemask in the
3804+
* slow path.
3805+
*/
37893806
goto no_zone;
37903807
}
37913808

@@ -3794,6 +3811,7 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
37943811
if (likely(page))
37953812
goto out;
37963813

3814+
no_zone:
37973815
/*
37983816
* Runtime PM, block IO and its error handling path can deadlock
37993817
* because I/O on the device might not complete.
@@ -3811,24 +3829,11 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
38113829
ac.nodemask = nodemask;
38123830
ac.preferred_zoneref = first_zones_zonelist(ac.zonelist,
38133831
ac.high_zoneidx, ac.nodemask);
3814-
if (!ac.preferred_zoneref->zone)
3815-
goto no_zone;
3832+
/* If we have NULL preferred zone, slowpath wll handle that */
38163833
}
38173834

38183835
page = __alloc_pages_slowpath(alloc_mask, order, &ac);
38193836

3820-
no_zone:
3821-
/*
3822-
* When updating a task's mems_allowed, it is possible to race with
3823-
* parallel threads in such a way that an allocation can fail while
3824-
* the mask is being updated. If a page allocation is about to fail,
3825-
* check if the cpuset changed during allocation and if so, retry.
3826-
*/
3827-
if (unlikely(!page && read_mems_allowed_retry(cpuset_mems_cookie))) {
3828-
alloc_mask = gfp_mask;
3829-
goto retry_cpuset;
3830-
}
3831-
38323837
out:
38333838
if (memcg_kmem_enabled() && (gfp_mask & __GFP_ACCOUNT) && page &&
38343839
unlikely(memcg_kmem_charge(page, gfp_mask, order) != 0)) {

0 commit comments

Comments
 (0)