Skip to content

Commit 54f180d

Browse files
yhuang-inteltorvalds
authored andcommitted
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>
1 parent bc4e54f commit 54f180d

File tree

3 files changed

+18
-13
lines changed

3 files changed

+18
-13
lines changed

mm/swap_slots.c

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <linux/cpumask.h>
3232
#include <linux/vmalloc.h>
3333
#include <linux/mutex.h>
34+
#include <linux/mm.h>
3435

3536
#ifdef CONFIG_SWAP
3637

@@ -119,16 +120,18 @@ static int alloc_swap_slot_cache(unsigned int cpu)
119120

120121
/*
121122
* 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,
123124
* which can lock swap_slots_cache_mutex.
124125
*/
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);
126128
if (!slots)
127129
return -ENOMEM;
128130

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);
130133
if (!slots_ret) {
131-
vfree(slots);
134+
kvfree(slots);
132135
return -ENOMEM;
133136
}
134137

@@ -152,9 +155,9 @@ static int alloc_swap_slot_cache(unsigned int cpu)
152155
out:
153156
mutex_unlock(&swap_slots_cache_mutex);
154157
if (slots)
155-
vfree(slots);
158+
kvfree(slots);
156159
if (slots_ret)
157-
vfree(slots_ret);
160+
kvfree(slots_ret);
158161
return 0;
159162
}
160163

@@ -171,7 +174,7 @@ static void drain_slots_cache_cpu(unsigned int cpu, unsigned int type,
171174
cache->cur = 0;
172175
cache->nr = 0;
173176
if (free_slots && cache->slots) {
174-
vfree(cache->slots);
177+
kvfree(cache->slots);
175178
cache->slots = NULL;
176179
}
177180
mutex_unlock(&cache->alloc_lock);
@@ -186,7 +189,7 @@ static void drain_slots_cache_cpu(unsigned int cpu, unsigned int type,
186189
}
187190
spin_unlock_irq(&cache->free_lock);
188191
if (slots)
189-
vfree(slots);
192+
kvfree(slots);
190193
}
191194
}
192195

mm/swap_state.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ int init_swap_address_space(unsigned int type, unsigned long nr_pages)
523523
unsigned int i, nr;
524524

525525
nr = DIV_ROUND_UP(nr_pages, SWAP_ADDRESS_SPACE_PAGES);
526-
spaces = vzalloc(sizeof(struct address_space) * nr);
526+
spaces = kvzalloc(sizeof(struct address_space) * nr, GFP_KERNEL);
527527
if (!spaces)
528528
return -ENOMEM;
529529
for (i = 0; i < nr; i++) {

mm/swapfile.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2270,8 +2270,8 @@ SYSCALL_DEFINE1(swapoff, const char __user *, specialfile)
22702270
free_percpu(p->percpu_cluster);
22712271
p->percpu_cluster = NULL;
22722272
vfree(swap_map);
2273-
vfree(cluster_info);
2274-
vfree(frontswap_map);
2273+
kvfree(cluster_info);
2274+
kvfree(frontswap_map);
22752275
/* Destroy swap account information */
22762276
swap_cgroup_swapoff(p->type);
22772277
exit_swap_address_space(p->type);
@@ -2794,7 +2794,8 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
27942794
p->cluster_next = 1 + (prandom_u32() % p->highest_bit);
27952795
nr_cluster = DIV_ROUND_UP(maxpages, SWAPFILE_CLUSTER);
27962796

2797-
cluster_info = vzalloc(nr_cluster * sizeof(*cluster_info));
2797+
cluster_info = kvzalloc(nr_cluster * sizeof(*cluster_info),
2798+
GFP_KERNEL);
27982799
if (!cluster_info) {
27992800
error = -ENOMEM;
28002801
goto bad_swap;
@@ -2827,7 +2828,8 @@ SYSCALL_DEFINE2(swapon, const char __user *, specialfile, int, swap_flags)
28272828
}
28282829
/* frontswap enabled? set up bit-per-page map for frontswap */
28292830
if (IS_ENABLED(CONFIG_FRONTSWAP))
2830-
frontswap_map = vzalloc(BITS_TO_LONGS(maxpages) * sizeof(long));
2831+
frontswap_map = kvzalloc(BITS_TO_LONGS(maxpages) * sizeof(long),
2832+
GFP_KERNEL);
28312833

28322834
if (p->bdev &&(swap_flags & SWAP_FLAG_DISCARD) && swap_discardable(p)) {
28332835
/*

0 commit comments

Comments
 (0)