aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/cpuset.h27
-rw-r--r--kernel/cpuset.c2
-rw-r--r--mm/filemap.c4
-rw-r--r--mm/hugetlb.c4
-rw-r--r--mm/mempolicy.c12
-rw-r--r--mm/page_alloc.c8
-rw-r--r--mm/slab.c4
-rw-r--r--mm/slub.c16
8 files changed, 38 insertions, 39 deletions
diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h
index 3fe661fe96d1..b19d3dc2e651 100644
--- a/include/linux/cpuset.h
+++ b/include/linux/cpuset.h
@@ -87,25 +87,26 @@ extern void rebuild_sched_domains(void);
87extern void cpuset_print_task_mems_allowed(struct task_struct *p); 87extern void cpuset_print_task_mems_allowed(struct task_struct *p);
88 88
89/* 89/*
90 * get_mems_allowed is required when making decisions involving mems_allowed 90 * read_mems_allowed_begin is required when making decisions involving
91 * such as during page allocation. mems_allowed can be updated in parallel 91 * mems_allowed such as during page allocation. mems_allowed can be updated in
92 * and depending on the new value an operation can fail potentially causing 92 * parallel and depending on the new value an operation can fail potentially
93 * process failure. A retry loop with get_mems_allowed and put_mems_allowed 93 * causing process failure. A retry loop with read_mems_allowed_begin and
94 * prevents these artificial failures. 94 * read_mems_allowed_retry prevents these artificial failures.
95 */ 95 */
96static inline unsigned int get_mems_allowed(void) 96static inline unsigned int read_mems_allowed_begin(void)
97{ 97{
98 return read_seqcount_begin(&current->mems_allowed_seq); 98 return read_seqcount_begin(&current->mems_allowed_seq);
99} 99}
100 100
101/* 101/*
102 * If this returns false, the operation that took place after get_mems_allowed 102 * If this returns true, the operation that took place after
103 * may have failed. It is up to the caller to retry the operation if 103 * read_mems_allowed_begin may have failed artificially due to a concurrent
104 * update of mems_allowed. It is up to the caller to retry the operation if
104 * appropriate. 105 * appropriate.
105 */ 106 */
106static inline bool put_mems_allowed(unsigned int seq) 107static inline bool read_mems_allowed_retry(unsigned int seq)
107{ 108{
108 return !read_seqcount_retry(&current->mems_allowed_seq, seq); 109 return read_seqcount_retry(&current->mems_allowed_seq, seq);
109} 110}
110 111
111static inline void set_mems_allowed(nodemask_t nodemask) 112static inline void set_mems_allowed(nodemask_t nodemask)
@@ -225,14 +226,14 @@ static inline void set_mems_allowed(nodemask_t nodemask)
225{ 226{
226} 227}
227 228
228static inline unsigned int get_mems_allowed(void) 229static inline unsigned int read_mems_allowed_begin(void)
229{ 230{
230 return 0; 231 return 0;
231} 232}
232 233
233static inline bool put_mems_allowed(unsigned int seq) 234static inline bool read_mems_allowed_retry(unsigned int seq)
234{ 235{
235 return true; 236 return false;
236} 237}
237 238
238#endif /* !CONFIG_CPUSETS */ 239#endif /* !CONFIG_CPUSETS */
diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index e6b1b66afe52..f6fc7475f1a1 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -1022,7 +1022,7 @@ static void cpuset_change_task_nodemask(struct task_struct *tsk,
1022 task_lock(tsk); 1022 task_lock(tsk);
1023 /* 1023 /*
1024 * Determine if a loop is necessary if another thread is doing 1024 * Determine if a loop is necessary if another thread is doing
1025 * get_mems_allowed(). If at least one node remains unchanged and 1025 * read_mems_allowed_begin(). If at least one node remains unchanged and
1026 * tsk does not have a mempolicy, then an empty nodemask will not be 1026 * tsk does not have a mempolicy, then an empty nodemask will not be
1027 * possible when mems_allowed is larger than a word. 1027 * possible when mems_allowed is larger than a word.
1028 */ 1028 */
diff --git a/mm/filemap.c b/mm/filemap.c
index 7a13f6ac5421..068cd2a63d32 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -520,10 +520,10 @@ struct page *__page_cache_alloc(gfp_t gfp)
520 if (cpuset_do_page_mem_spread()) { 520 if (cpuset_do_page_mem_spread()) {
521 unsigned int cpuset_mems_cookie; 521 unsigned int cpuset_mems_cookie;
522 do { 522 do {
523 cpuset_mems_cookie = get_mems_allowed(); 523 cpuset_mems_cookie = read_mems_allowed_begin();
524 n = cpuset_mem_spread_node(); 524 n = cpuset_mem_spread_node();
525 page = alloc_pages_exact_node(n, gfp, 0); 525 page = alloc_pages_exact_node(n, gfp, 0);
526 } while (!put_mems_allowed(cpuset_mems_cookie) && !page); 526 } while (!page && read_mems_allowed_retry(cpuset_mems_cookie));
527 527
528 return page; 528 return page;
529 } 529 }
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index c01cb9fedb18..139b7462203b 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -540,7 +540,7 @@ static struct page *dequeue_huge_page_vma(struct hstate *h,
540 goto err; 540 goto err;
541 541
542retry_cpuset: 542retry_cpuset:
543 cpuset_mems_cookie = get_mems_allowed(); 543 cpuset_mems_cookie = read_mems_allowed_begin();
544 zonelist = huge_zonelist(vma, address, 544 zonelist = huge_zonelist(vma, address,
545 htlb_alloc_mask(h), &mpol, &nodemask); 545 htlb_alloc_mask(h), &mpol, &nodemask);
546 546
@@ -562,7 +562,7 @@ retry_cpuset:
562 } 562 }
563 563
564 mpol_cond_put(mpol); 564 mpol_cond_put(mpol);
565 if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page)) 565 if (unlikely(!page && read_mems_allowed_retry(cpuset_mems_cookie)))
566 goto retry_cpuset; 566 goto retry_cpuset;
567 return page; 567 return page;
568 568
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 4755c8576942..e3ab02822799 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -1899,7 +1899,7 @@ int node_random(const nodemask_t *maskp)
1899 * If the effective policy is 'BIND, returns a pointer to the mempolicy's 1899 * If the effective policy is 'BIND, returns a pointer to the mempolicy's
1900 * @nodemask for filtering the zonelist. 1900 * @nodemask for filtering the zonelist.
1901 * 1901 *
1902 * Must be protected by get_mems_allowed() 1902 * Must be protected by read_mems_allowed_begin()
1903 */ 1903 */
1904struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr, 1904struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr,
1905 gfp_t gfp_flags, struct mempolicy **mpol, 1905 gfp_t gfp_flags, struct mempolicy **mpol,
@@ -2063,7 +2063,7 @@ alloc_pages_vma(gfp_t gfp, int order, struct vm_area_struct *vma,
2063 2063
2064retry_cpuset: 2064retry_cpuset:
2065 pol = get_vma_policy(current, vma, addr); 2065 pol = get_vma_policy(current, vma, addr);
2066 cpuset_mems_cookie = get_mems_allowed(); 2066 cpuset_mems_cookie = read_mems_allowed_begin();
2067 2067
2068 if (unlikely(pol->mode == MPOL_INTERLEAVE)) { 2068 if (unlikely(pol->mode == MPOL_INTERLEAVE)) {
2069 unsigned nid; 2069 unsigned nid;
@@ -2071,7 +2071,7 @@ retry_cpuset:
2071 nid = interleave_nid(pol, vma, addr, PAGE_SHIFT + order); 2071 nid = interleave_nid(pol, vma, addr, PAGE_SHIFT + order);
2072 mpol_cond_put(pol); 2072 mpol_cond_put(pol);
2073 page = alloc_page_interleave(gfp, order, nid); 2073 page = alloc_page_interleave(gfp, order, nid);
2074 if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page)) 2074 if (unlikely(!page && read_mems_allowed_retry(cpuset_mems_cookie)))
2075 goto retry_cpuset; 2075 goto retry_cpuset;
2076 2076
2077 return page; 2077 return page;
@@ -2081,7 +2081,7 @@ retry_cpuset:
2081 policy_nodemask(gfp, pol)); 2081 policy_nodemask(gfp, pol));
2082 if (unlikely(mpol_needs_cond_ref(pol))) 2082 if (unlikely(mpol_needs_cond_ref(pol)))
2083 __mpol_put(pol); 2083 __mpol_put(pol);
2084 if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page)) 2084 if (unlikely(!page && read_mems_allowed_retry(cpuset_mems_cookie)))
2085 goto retry_cpuset; 2085 goto retry_cpuset;
2086 return page; 2086 return page;
2087} 2087}
@@ -2115,7 +2115,7 @@ struct page *alloc_pages_current(gfp_t gfp, unsigned order)
2115 pol = &default_policy; 2115 pol = &default_policy;
2116 2116
2117retry_cpuset: 2117retry_cpuset:
2118 cpuset_mems_cookie = get_mems_allowed(); 2118 cpuset_mems_cookie = read_mems_allowed_begin();
2119 2119
2120 /* 2120 /*
2121 * No reference counting needed for current->mempolicy 2121 * No reference counting needed for current->mempolicy
@@ -2128,7 +2128,7 @@ retry_cpuset:
2128 policy_zonelist(gfp, pol, numa_node_id()), 2128 policy_zonelist(gfp, pol, numa_node_id()),
2129 policy_nodemask(gfp, pol)); 2129 policy_nodemask(gfp, pol));
2130 2130
2131 if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page)) 2131 if (unlikely(!page && read_mems_allowed_retry(cpuset_mems_cookie)))
2132 goto retry_cpuset; 2132 goto retry_cpuset;
2133 2133
2134 return page; 2134 return page;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 3bac76ae4b30..979378deccbf 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -2739,7 +2739,7 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order,
2739 return NULL; 2739 return NULL;
2740 2740
2741retry_cpuset: 2741retry_cpuset:
2742 cpuset_mems_cookie = get_mems_allowed(); 2742 cpuset_mems_cookie = read_mems_allowed_begin();
2743 2743
2744 /* The preferred zone is used for statistics later */ 2744 /* The preferred zone is used for statistics later */
2745 first_zones_zonelist(zonelist, high_zoneidx, 2745 first_zones_zonelist(zonelist, high_zoneidx,
@@ -2777,7 +2777,7 @@ out:
2777 * the mask is being updated. If a page allocation is about to fail, 2777 * the mask is being updated. If a page allocation is about to fail,
2778 * check if the cpuset changed during allocation and if so, retry. 2778 * check if the cpuset changed during allocation and if so, retry.
2779 */ 2779 */
2780 if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !page)) 2780 if (unlikely(!page && read_mems_allowed_retry(cpuset_mems_cookie)))
2781 goto retry_cpuset; 2781 goto retry_cpuset;
2782 2782
2783 memcg_kmem_commit_charge(page, memcg, order); 2783 memcg_kmem_commit_charge(page, memcg, order);
@@ -3045,9 +3045,9 @@ bool skip_free_areas_node(unsigned int flags, int nid)
3045 goto out; 3045 goto out;
3046 3046
3047 do { 3047 do {
3048 cpuset_mems_cookie = get_mems_allowed(); 3048 cpuset_mems_cookie = read_mems_allowed_begin();
3049 ret = !node_isset(nid, cpuset_current_mems_allowed); 3049 ret = !node_isset(nid, cpuset_current_mems_allowed);
3050 } while (!put_mems_allowed(cpuset_mems_cookie)); 3050 } while (read_mems_allowed_retry(cpuset_mems_cookie));
3051out: 3051out:
3052 return ret; 3052 return ret;
3053} 3053}
diff --git a/mm/slab.c b/mm/slab.c
index b264214c77ea..9153c802e2fe 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -3073,7 +3073,7 @@ static void *fallback_alloc(struct kmem_cache *cache, gfp_t flags)
3073 local_flags = flags & (GFP_CONSTRAINT_MASK|GFP_RECLAIM_MASK); 3073 local_flags = flags & (GFP_CONSTRAINT_MASK|GFP_RECLAIM_MASK);
3074 3074
3075retry_cpuset: 3075retry_cpuset:
3076 cpuset_mems_cookie = get_mems_allowed(); 3076 cpuset_mems_cookie = read_mems_allowed_begin();
3077 zonelist = node_zonelist(slab_node(), flags); 3077 zonelist = node_zonelist(slab_node(), flags);
3078 3078
3079retry: 3079retry:
@@ -3131,7 +3131,7 @@ retry:
3131 } 3131 }
3132 } 3132 }
3133 3133
3134 if (unlikely(!put_mems_allowed(cpuset_mems_cookie) && !obj)) 3134 if (unlikely(!obj && read_mems_allowed_retry(cpuset_mems_cookie)))
3135 goto retry_cpuset; 3135 goto retry_cpuset;
3136 return obj; 3136 return obj;
3137} 3137}
diff --git a/mm/slub.c b/mm/slub.c
index 25f14ad8f817..7611f148ee81 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1684,7 +1684,7 @@ static void *get_any_partial(struct kmem_cache *s, gfp_t flags,
1684 return NULL; 1684 return NULL;
1685 1685
1686 do { 1686 do {
1687 cpuset_mems_cookie = get_mems_allowed(); 1687 cpuset_mems_cookie = read_mems_allowed_begin();
1688 zonelist = node_zonelist(slab_node(), flags); 1688 zonelist = node_zonelist(slab_node(), flags);
1689 for_each_zone_zonelist(zone, z, zonelist, high_zoneidx) { 1689 for_each_zone_zonelist(zone, z, zonelist, high_zoneidx) {
1690 struct kmem_cache_node *n; 1690 struct kmem_cache_node *n;
@@ -1696,19 +1696,17 @@ static void *get_any_partial(struct kmem_cache *s, gfp_t flags,
1696 object = get_partial_node(s, n, c, flags); 1696 object = get_partial_node(s, n, c, flags);
1697 if (object) { 1697 if (object) {
1698 /* 1698 /*
1699 * Return the object even if 1699 * Don't check read_mems_allowed_retry()
1700 * put_mems_allowed indicated that 1700 * here - if mems_allowed was updated in
1701 * the cpuset mems_allowed was 1701 * parallel, that was a harmless race
1702 * updated in parallel. It's a 1702 * between allocation and the cpuset
1703 * harmless race between the alloc 1703 * update
1704 * and the cpuset update.
1705 */ 1704 */
1706 put_mems_allowed(cpuset_mems_cookie);
1707 return object; 1705 return object;
1708 } 1706 }
1709 } 1707 }
1710 } 1708 }
1711 } while (!put_mems_allowed(cpuset_mems_cookie)); 1709 } while (read_mems_allowed_retry(cpuset_mems_cookie));
1712#endif 1710#endif
1713 return NULL; 1711 return NULL;
1714} 1712}