Skip to content

Commit

Permalink
ext4: introduce ext4_kvmalloc(), ext4_kzalloc(), and ext4_kvfree()
Browse files Browse the repository at this point in the history
Introduce new helper functions which try kmalloc, and then fall back
to vmalloc if necessary, and use them for allocating and deallocating
s_flex_groups.

Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
  • Loading branch information
Theodore Ts'o committed Aug 1, 2011
1 parent 33853a0 commit 9933fc0
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 18 deletions.
3 changes: 3 additions & 0 deletions fs/ext4/ext4.h
Original file line number Diff line number Diff line change
Expand Up @@ -1874,6 +1874,9 @@ extern int ext4_group_extend(struct super_block *sb,
ext4_fsblk_t n_blocks_count);

/* super.c */
extern void *ext4_kvmalloc(size_t size, gfp_t flags);
extern void *ext4_kvzalloc(size_t size, gfp_t flags);
extern void ext4_kvfree(void *ptr);
extern void __ext4_error(struct super_block *, const char *, unsigned int,
const char *, ...)
__attribute__ ((format (printf, 4, 5)));
Expand Down
54 changes: 36 additions & 18 deletions fs/ext4/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,35 @@ static struct file_system_type ext3_fs_type = {
#define IS_EXT3_SB(sb) (0)
#endif

void *ext4_kvmalloc(size_t size, gfp_t flags)
{
void *ret;

ret = kmalloc(size, flags);
if (!ret)
ret = __vmalloc(size, flags, PAGE_KERNEL);
return ret;
}

void *ext4_kvzalloc(size_t size, gfp_t flags)
{
void *ret;

ret = kmalloc(size, flags);
if (!ret)
ret = __vmalloc(size, flags | __GFP_ZERO, PAGE_KERNEL);
return ret;
}

void ext4_kvfree(void *ptr)
{
if (is_vmalloc_addr(ptr))
vfree(ptr);
else
kfree(ptr);

}

ext4_fsblk_t ext4_block_bitmap(struct super_block *sb,
struct ext4_group_desc *bg)
{
Expand Down Expand Up @@ -791,10 +820,7 @@ static void ext4_put_super(struct super_block *sb)
for (i = 0; i < sbi->s_gdb_count; i++)
brelse(sbi->s_group_desc[i]);
kfree(sbi->s_group_desc);
if (is_vmalloc_addr(sbi->s_flex_groups))
vfree(sbi->s_flex_groups);
else
kfree(sbi->s_flex_groups);
ext4_kvfree(sbi->s_flex_groups);
percpu_counter_destroy(&sbi->s_freeblocks_counter);
percpu_counter_destroy(&sbi->s_freeinodes_counter);
percpu_counter_destroy(&sbi->s_dirs_counter);
Expand Down Expand Up @@ -1977,15 +2003,11 @@ static int ext4_fill_flex_info(struct super_block *sb)
((le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) + 1) <<
EXT4_DESC_PER_BLOCK_BITS(sb))) / groups_per_flex;
size = flex_group_count * sizeof(struct flex_groups);
sbi->s_flex_groups = kzalloc(size, GFP_KERNEL);
sbi->s_flex_groups = ext4_kvzalloc(size, GFP_KERNEL);
if (sbi->s_flex_groups == NULL) {
sbi->s_flex_groups = vzalloc(size);
if (sbi->s_flex_groups == NULL) {
ext4_msg(sb, KERN_ERR,
"not enough memory for %u flex groups",
flex_group_count);
goto failed;
}
ext4_msg(sb, KERN_ERR, "not enough memory for %u flex groups",
flex_group_count);
goto failed;
}

for (i = 0; i < sbi->s_groups_count; i++) {
Expand Down Expand Up @@ -3750,12 +3772,8 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
}
failed_mount3:
del_timer(&sbi->s_err_report);
if (sbi->s_flex_groups) {
if (is_vmalloc_addr(sbi->s_flex_groups))
vfree(sbi->s_flex_groups);
else
kfree(sbi->s_flex_groups);
}
if (sbi->s_flex_groups)
ext4_kvfree(sbi->s_flex_groups);
percpu_counter_destroy(&sbi->s_freeblocks_counter);
percpu_counter_destroy(&sbi->s_freeinodes_counter);
percpu_counter_destroy(&sbi->s_dirs_counter);
Expand Down

0 comments on commit 9933fc0

Please sign in to comment.