Skip to content

Commit a7c3e90

Browse files
Michal Hockotorvalds
authored andcommitted
mm: introduce kv[mz]alloc helpers
Patch series "kvmalloc", v5. There are many open coded kmalloc with vmalloc fallback instances in the tree. Most of them are not careful enough or simply do not care about the underlying semantic of the kmalloc/page allocator which means that a) some vmalloc fallbacks are basically unreachable because the kmalloc part will keep retrying until it succeeds b) the page allocator can invoke a really disruptive steps like the OOM killer to move forward which doesn't sound appropriate when we consider that the vmalloc fallback is available. As it can be seen implementing kvmalloc requires quite an intimate knowledge if the page allocator and the memory reclaim internals which strongly suggests that a helper should be implemented in the memory subsystem proper. Most callers, I could find, have been converted to use the helper instead. This is patch 6. There are some more relying on __GFP_REPEAT in the networking stack which I have converted as well and Eric Dumazet was not opposed [2] to convert them as well. [1] http://lkml.kernel.org/r/[email protected] [2] http://lkml.kernel.org/r/1485273626.16328.301.camel@edumazet-glaptop3.roam.corp.google.com This patch (of 9): Using kmalloc with the vmalloc fallback for larger allocations is a common pattern in the kernel code. Yet we do not have any common helper for that and so users have invented their own helpers. Some of them are really creative when doing so. Let's just add kv[mz]alloc and make sure it is implemented properly. This implementation makes sure to not make a large memory pressure for > PAGE_SZE requests (__GFP_NORETRY) and also to not warn about allocation failures. This also rules out the OOM killer as the vmalloc is a more approapriate fallback than a disruptive user visible action. This patch also changes some existing users and removes helpers which are specific for them. In some cases this is not possible (e.g. ext4_kvmalloc, libcfs_kvzalloc) because those seems to be broken and require GFP_NO{FS,IO} context which is not vmalloc compatible in general (note that the page table allocation is GFP_KERNEL). Those need to be fixed separately. While we are at it, document that __vmalloc{_node} about unsupported gfp mask because there seems to be a lot of confusion out there. kvmalloc_node will warn about GFP_KERNEL incompatible (which are not superset) flags to catch new abusers. Existing ones would have to die slowly. [[email protected]: f2fs fixup] Link: http://lkml.kernel.org/r/[email protected] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Michal Hocko <[email protected]> Signed-off-by: Stephen Rothwell <[email protected]> Reviewed-by: Andreas Dilger <[email protected]> [ext4 part] Acked-by: Vlastimil Babka <[email protected]> Cc: John Hubbard <[email protected]> Cc: David Miller <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 60f3e00 commit a7c3e90

File tree

24 files changed

+103
-130
lines changed

24 files changed

+103
-130
lines changed

arch/x86/kvm/lapic.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,8 @@ static void recalculate_apic_map(struct kvm *kvm)
177177
if (kvm_apic_present(vcpu))
178178
max_id = max(max_id, kvm_x2apic_id(vcpu->arch.apic));
179179

180-
new = kvm_kvzalloc(sizeof(struct kvm_apic_map) +
181-
sizeof(struct kvm_lapic *) * ((u64)max_id + 1));
180+
new = kvzalloc(sizeof(struct kvm_apic_map) +
181+
sizeof(struct kvm_lapic *) * ((u64)max_id + 1), GFP_KERNEL);
182182

183183
if (!new)
184184
goto out;

arch/x86/kvm/page_track.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ int kvm_page_track_create_memslot(struct kvm_memory_slot *slot,
4040
int i;
4141

4242
for (i = 0; i < KVM_PAGE_TRACK_MAX; i++) {
43-
slot->arch.gfn_track[i] = kvm_kvzalloc(npages *
44-
sizeof(*slot->arch.gfn_track[i]));
43+
slot->arch.gfn_track[i] = kvzalloc(npages *
44+
sizeof(*slot->arch.gfn_track[i]), GFP_KERNEL);
4545
if (!slot->arch.gfn_track[i])
4646
goto track_free;
4747
}

arch/x86/kvm/x86.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8199,13 +8199,13 @@ int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot,
81998199
slot->base_gfn, level) + 1;
82008200

82018201
slot->arch.rmap[i] =
8202-
kvm_kvzalloc(lpages * sizeof(*slot->arch.rmap[i]));
8202+
kvzalloc(lpages * sizeof(*slot->arch.rmap[i]), GFP_KERNEL);
82038203
if (!slot->arch.rmap[i])
82048204
goto out_free;
82058205
if (i == 0)
82068206
continue;
82078207

8208-
linfo = kvm_kvzalloc(lpages * sizeof(*linfo));
8208+
linfo = kvzalloc(lpages * sizeof(*linfo), GFP_KERNEL);
82098209
if (!linfo)
82108210
goto out_free;
82118211

drivers/md/dm-stats.c

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -146,12 +146,7 @@ static void *dm_kvzalloc(size_t alloc_size, int node)
146146
if (!claim_shared_memory(alloc_size))
147147
return NULL;
148148

149-
if (alloc_size <= KMALLOC_MAX_SIZE) {
150-
p = kzalloc_node(alloc_size, GFP_KERNEL | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN, node);
151-
if (p)
152-
return p;
153-
}
154-
p = vzalloc_node(alloc_size, node);
149+
p = kvzalloc_node(alloc_size, GFP_KERNEL | __GFP_NOMEMALLOC, node);
155150
if (p)
156151
return p;
157152

fs/ext4/mballoc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2393,7 +2393,7 @@ int ext4_mb_alloc_groupinfo(struct super_block *sb, ext4_group_t ngroups)
23932393
return 0;
23942394

23952395
size = roundup_pow_of_two(sizeof(*sbi->s_group_info) * size);
2396-
new_groupinfo = ext4_kvzalloc(size, GFP_KERNEL);
2396+
new_groupinfo = kvzalloc(size, GFP_KERNEL);
23972397
if (!new_groupinfo) {
23982398
ext4_msg(sb, KERN_ERR, "can't allocate buddy meta group");
23992399
return -ENOMEM;

fs/ext4/super.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2153,7 +2153,7 @@ int ext4_alloc_flex_bg_array(struct super_block *sb, ext4_group_t ngroup)
21532153
return 0;
21542154

21552155
size = roundup_pow_of_two(size * sizeof(struct flex_groups));
2156-
new_groups = ext4_kvzalloc(size, GFP_KERNEL);
2156+
new_groups = kvzalloc(size, GFP_KERNEL);
21572157
if (!new_groups) {
21582158
ext4_msg(sb, KERN_ERR, "not enough memory for %d flex groups",
21592159
size / (int) sizeof(struct flex_groups));
@@ -3887,7 +3887,7 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
38873887
goto failed_mount;
38883888
}
38893889
}
3890-
sbi->s_group_desc = ext4_kvmalloc(db_count *
3890+
sbi->s_group_desc = kvmalloc(db_count *
38913891
sizeof(struct buffer_head *),
38923892
GFP_KERNEL);
38933893
if (sbi->s_group_desc == NULL) {

fs/f2fs/f2fs.h

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2005,26 +2005,6 @@ static inline void *f2fs_kmalloc(struct f2fs_sb_info *sbi,
20052005
return kmalloc(size, flags);
20062006
}
20072007

2008-
static inline void *f2fs_kvmalloc(size_t size, gfp_t flags)
2009-
{
2010-
void *ret;
2011-
2012-
ret = kmalloc(size, flags | __GFP_NOWARN);
2013-
if (!ret)
2014-
ret = __vmalloc(size, flags, PAGE_KERNEL);
2015-
return ret;
2016-
}
2017-
2018-
static inline void *f2fs_kvzalloc(size_t size, gfp_t flags)
2019-
{
2020-
void *ret;
2021-
2022-
ret = kzalloc(size, flags | __GFP_NOWARN);
2023-
if (!ret)
2024-
ret = __vmalloc(size, flags | __GFP_ZERO, PAGE_KERNEL);
2025-
return ret;
2026-
}
2027-
20282008
#define get_inode_mode(i) \
20292009
((is_inode_flag_set(i, FI_ACL_MODE)) ? \
20302010
(F2FS_I(i)->i_acl_mode) : ((i)->i_mode))

fs/f2fs/file.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,11 +1012,11 @@ static int __exchange_data_block(struct inode *src_inode,
10121012
while (len) {
10131013
olen = min((pgoff_t)4 * ADDRS_PER_BLOCK, len);
10141014

1015-
src_blkaddr = f2fs_kvzalloc(sizeof(block_t) * olen, GFP_KERNEL);
1015+
src_blkaddr = kvzalloc(sizeof(block_t) * olen, GFP_KERNEL);
10161016
if (!src_blkaddr)
10171017
return -ENOMEM;
10181018

1019-
do_replace = f2fs_kvzalloc(sizeof(int) * olen, GFP_KERNEL);
1019+
do_replace = kvzalloc(sizeof(int) * olen, GFP_KERNEL);
10201020
if (!do_replace) {
10211021
kvfree(src_blkaddr);
10221022
return -ENOMEM;

fs/f2fs/node.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2621,17 +2621,17 @@ static int init_free_nid_cache(struct f2fs_sb_info *sbi)
26212621
{
26222622
struct f2fs_nm_info *nm_i = NM_I(sbi);
26232623

2624-
nm_i->free_nid_bitmap = f2fs_kvzalloc(nm_i->nat_blocks *
2624+
nm_i->free_nid_bitmap = kvzalloc(nm_i->nat_blocks *
26252625
NAT_ENTRY_BITMAP_SIZE, GFP_KERNEL);
26262626
if (!nm_i->free_nid_bitmap)
26272627
return -ENOMEM;
26282628

2629-
nm_i->nat_block_bitmap = f2fs_kvzalloc(nm_i->nat_blocks / 8,
2629+
nm_i->nat_block_bitmap = kvzalloc(nm_i->nat_blocks / 8,
26302630
GFP_KERNEL);
26312631
if (!nm_i->nat_block_bitmap)
26322632
return -ENOMEM;
26332633

2634-
nm_i->free_nid_count = f2fs_kvzalloc(nm_i->nat_blocks *
2634+
nm_i->free_nid_count = kvzalloc(nm_i->nat_blocks *
26352635
sizeof(unsigned short), GFP_KERNEL);
26362636
if (!nm_i->free_nid_count)
26372637
return -ENOMEM;

fs/f2fs/segment.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2501,13 +2501,13 @@ static int build_sit_info(struct f2fs_sb_info *sbi)
25012501

25022502
SM_I(sbi)->sit_info = sit_i;
25032503

2504-
sit_i->sentries = f2fs_kvzalloc(MAIN_SEGS(sbi) *
2504+
sit_i->sentries = kvzalloc(MAIN_SEGS(sbi) *
25052505
sizeof(struct seg_entry), GFP_KERNEL);
25062506
if (!sit_i->sentries)
25072507
return -ENOMEM;
25082508

25092509
bitmap_size = f2fs_bitmap_size(MAIN_SEGS(sbi));
2510-
sit_i->dirty_sentries_bitmap = f2fs_kvzalloc(bitmap_size, GFP_KERNEL);
2510+
sit_i->dirty_sentries_bitmap = kvzalloc(bitmap_size, GFP_KERNEL);
25112511
if (!sit_i->dirty_sentries_bitmap)
25122512
return -ENOMEM;
25132513

@@ -2540,7 +2540,7 @@ static int build_sit_info(struct f2fs_sb_info *sbi)
25402540
return -ENOMEM;
25412541

25422542
if (sbi->segs_per_sec > 1) {
2543-
sit_i->sec_entries = f2fs_kvzalloc(MAIN_SECS(sbi) *
2543+
sit_i->sec_entries = kvzalloc(MAIN_SECS(sbi) *
25442544
sizeof(struct sec_entry), GFP_KERNEL);
25452545
if (!sit_i->sec_entries)
25462546
return -ENOMEM;
@@ -2591,12 +2591,12 @@ static int build_free_segmap(struct f2fs_sb_info *sbi)
25912591
SM_I(sbi)->free_info = free_i;
25922592

25932593
bitmap_size = f2fs_bitmap_size(MAIN_SEGS(sbi));
2594-
free_i->free_segmap = f2fs_kvmalloc(bitmap_size, GFP_KERNEL);
2594+
free_i->free_segmap = kvmalloc(bitmap_size, GFP_KERNEL);
25952595
if (!free_i->free_segmap)
25962596
return -ENOMEM;
25972597

25982598
sec_bitmap_size = f2fs_bitmap_size(MAIN_SECS(sbi));
2599-
free_i->free_secmap = f2fs_kvmalloc(sec_bitmap_size, GFP_KERNEL);
2599+
free_i->free_secmap = kvmalloc(sec_bitmap_size, GFP_KERNEL);
26002600
if (!free_i->free_secmap)
26012601
return -ENOMEM;
26022602

@@ -2764,7 +2764,7 @@ static int init_victim_secmap(struct f2fs_sb_info *sbi)
27642764
struct dirty_seglist_info *dirty_i = DIRTY_I(sbi);
27652765
unsigned int bitmap_size = f2fs_bitmap_size(MAIN_SECS(sbi));
27662766

2767-
dirty_i->victim_secmap = f2fs_kvzalloc(bitmap_size, GFP_KERNEL);
2767+
dirty_i->victim_secmap = kvzalloc(bitmap_size, GFP_KERNEL);
27682768
if (!dirty_i->victim_secmap)
27692769
return -ENOMEM;
27702770
return 0;
@@ -2786,7 +2786,7 @@ static int build_dirty_segmap(struct f2fs_sb_info *sbi)
27862786
bitmap_size = f2fs_bitmap_size(MAIN_SEGS(sbi));
27872787

27882788
for (i = 0; i < NR_DIRTY_TYPE; i++) {
2789-
dirty_i->dirty_segmap[i] = f2fs_kvzalloc(bitmap_size, GFP_KERNEL);
2789+
dirty_i->dirty_segmap[i] = kvzalloc(bitmap_size, GFP_KERNEL);
27902790
if (!dirty_i->dirty_segmap[i])
27912791
return -ENOMEM;
27922792
}

0 commit comments

Comments
 (0)