diff options
-rw-r--r-- | include/linux/cpuset.h | 27 | ||||
-rw-r--r-- | kernel/cpuset.c | 2 | ||||
-rw-r--r-- | mm/filemap.c | 4 | ||||
-rw-r--r-- | mm/hugetlb.c | 4 | ||||
-rw-r--r-- | mm/mempolicy.c | 12 | ||||
-rw-r--r-- | mm/page_alloc.c | 8 | ||||
-rw-r--r-- | mm/slab.c | 4 | ||||
-rw-r--r-- | mm/slub.c | 16 |
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); | |||
87 | extern void cpuset_print_task_mems_allowed(struct task_struct *p); | 87 | extern 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 | */ |
96 | static inline unsigned int get_mems_allowed(void) | 96 | static inline unsigned int read_mems_allowed_begin(void) |
97 | { | 97 | { |
98 | return read_seqcount_begin(¤t->mems_allowed_seq); | 98 | return read_seqcount_begin(¤t->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 | */ |
106 | static inline bool put_mems_allowed(unsigned int seq) | 107 | static inline bool read_mems_allowed_retry(unsigned int seq) |
107 | { | 108 | { |
108 | return !read_seqcount_retry(¤t->mems_allowed_seq, seq); | 109 | return read_seqcount_retry(¤t->mems_allowed_seq, seq); |
109 | } | 110 | } |
110 | 111 | ||
111 | static inline void set_mems_allowed(nodemask_t nodemask) | 112 | static 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 | ||
228 | static inline unsigned int get_mems_allowed(void) | 229 | static inline unsigned int read_mems_allowed_begin(void) |
229 | { | 230 | { |
230 | return 0; | 231 | return 0; |
231 | } | 232 | } |
232 | 233 | ||
233 | static inline bool put_mems_allowed(unsigned int seq) | 234 | static 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 | ||
542 | retry_cpuset: | 542 | retry_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 | */ |
1904 | struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr, | 1904 | struct 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 | ||
2064 | retry_cpuset: | 2064 | retry_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 | ||
2117 | retry_cpuset: | 2117 | retry_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 | ||
2741 | retry_cpuset: | 2741 | retry_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)); |
3051 | out: | 3051 | out: |
3052 | return ret; | 3052 | return ret; |
3053 | } | 3053 | } |
@@ -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 | ||
3075 | retry_cpuset: | 3075 | retry_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 | ||
3079 | retry: | 3079 | retry: |
@@ -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 | } |
@@ -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 | } |