aboutsummaryrefslogtreecommitdiffstats
path: root/mm/swap_slots.c
diff options
context:
space:
mode:
authorHuang Ying <ying.huang@intel.com>2017-05-08 18:57:40 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-05-08 20:15:13 -0400
commit54f180d3c181277457fb003dd9524c2aa1ef8160 (patch)
treefc763d5c91a4b0c0dfe5f4a6d594dd768866074f /mm/swap_slots.c
parentbc4e54f6e966e9ca35064cd60f91b1478c07a1b2 (diff)
mm, swap: use kvzalloc to allocate some swap data structures
Now vzalloc() is used in swap code to allocate various data structures, such as swap cache, swap slots cache, cluster info, etc. Because the size may be too large on some system, so that normal kzalloc() may fail. But using kzalloc() has some advantages, for example, less memory fragmentation, less TLB pressure, etc. So change the data structure allocation in swap code to use kvzalloc() which will try kzalloc() firstly, and fallback to vzalloc() if kzalloc() failed. In general, although kmalloc() will reduce the number of high-order pages in short term, vmalloc() will cause more pain for memory fragmentation in the long term. And the swap data structure allocation that is changed in this patch is expected to be long term allocation. From Dave Hansen: "for example, we have a two-page data structure. vmalloc() takes two effectively random order-0 pages, probably from two different 2M pages and pins them. That "kills" two 2M pages. kmalloc(), allocating two *contiguous* pages, will not cross a 2M boundary. That means it will only "kill" the possibility of a single 2M page. More 2M pages == less fragmentation. The allocation in this patch occurs during swap on time, which is usually done during system boot, so usually we have high opportunity to allocate the contiguous pages successfully. The allocation for swap_map[] in struct swap_info_struct is not changed, because that is usually quite large and vmalloc_to_page() is used for it. That makes it a little harder to change. Link: http://lkml.kernel.org/r/20170407064911.25447-1-ying.huang@intel.com Signed-off-by: Huang Ying <ying.huang@intel.com> Acked-by: Tim Chen <tim.c.chen@intel.com> Acked-by: Michal Hocko <mhocko@suse.com> Acked-by: Rik van Riel <riel@redhat.com> Cc: Dave Hansen <dave.hansen@intel.com> Cc: Hugh Dickins <hughd@google.com> Cc: Shaohua Li <shli@kernel.org> Cc: Minchan Kim <minchan@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/swap_slots.c')
-rw-r--r--mm/swap_slots.c19
1 files changed, 11 insertions, 8 deletions
diff --git a/mm/swap_slots.c b/mm/swap_slots.c
index aa1c415f4abd..58f6c78f1dad 100644
--- a/mm/swap_slots.c
+++ b/mm/swap_slots.c
@@ -31,6 +31,7 @@
31#include <linux/cpumask.h> 31#include <linux/cpumask.h>
32#include <linux/vmalloc.h> 32#include <linux/vmalloc.h>
33#include <linux/mutex.h> 33#include <linux/mutex.h>
34#include <linux/mm.h>
34 35
35#ifdef CONFIG_SWAP 36#ifdef CONFIG_SWAP
36 37
@@ -119,16 +120,18 @@ static int alloc_swap_slot_cache(unsigned int cpu)
119 120
120 /* 121 /*
121 * Do allocation outside swap_slots_cache_mutex 122 * Do allocation outside swap_slots_cache_mutex
122 * as vzalloc could trigger reclaim and get_swap_page, 123 * as kvzalloc could trigger reclaim and get_swap_page,
123 * which can lock swap_slots_cache_mutex. 124 * which can lock swap_slots_cache_mutex.
124 */ 125 */
125 slots = vzalloc(sizeof(swp_entry_t) * SWAP_SLOTS_CACHE_SIZE); 126 slots = kvzalloc(sizeof(swp_entry_t) * SWAP_SLOTS_CACHE_SIZE,
127 GFP_KERNEL);
126 if (!slots) 128 if (!slots)
127 return -ENOMEM; 129 return -ENOMEM;
128 130
129 slots_ret = vzalloc(sizeof(swp_entry_t) * SWAP_SLOTS_CACHE_SIZE); 131 slots_ret = kvzalloc(sizeof(swp_entry_t) * SWAP_SLOTS_CACHE_SIZE,
132 GFP_KERNEL);
130 if (!slots_ret) { 133 if (!slots_ret) {
131 vfree(slots); 134 kvfree(slots);
132 return -ENOMEM; 135 return -ENOMEM;
133 } 136 }
134 137
@@ -152,9 +155,9 @@ static int alloc_swap_slot_cache(unsigned int cpu)
152out: 155out:
153 mutex_unlock(&swap_slots_cache_mutex); 156 mutex_unlock(&swap_slots_cache_mutex);
154 if (slots) 157 if (slots)
155 vfree(slots); 158 kvfree(slots);
156 if (slots_ret) 159 if (slots_ret)
157 vfree(slots_ret); 160 kvfree(slots_ret);
158 return 0; 161 return 0;
159} 162}
160 163
@@ -171,7 +174,7 @@ static void drain_slots_cache_cpu(unsigned int cpu, unsigned int type,
171 cache->cur = 0; 174 cache->cur = 0;
172 cache->nr = 0; 175 cache->nr = 0;
173 if (free_slots && cache->slots) { 176 if (free_slots && cache->slots) {
174 vfree(cache->slots); 177 kvfree(cache->slots);
175 cache->slots = NULL; 178 cache->slots = NULL;
176 } 179 }
177 mutex_unlock(&cache->alloc_lock); 180 mutex_unlock(&cache->alloc_lock);
@@ -186,7 +189,7 @@ static void drain_slots_cache_cpu(unsigned int cpu, unsigned int type,
186 } 189 }
187 spin_unlock_irq(&cache->free_lock); 190 spin_unlock_irq(&cache->free_lock);
188 if (slots) 191 if (slots)
189 vfree(slots); 192 kvfree(slots);
190 } 193 }
191} 194}
192 195