diff options
| author | Theodore Ts'o <tytso@mit.edu> | 2011-08-01 08:45:02 -0400 | 
|---|---|---|
| committer | Theodore Ts'o <tytso@mit.edu> | 2011-08-01 08:45:02 -0400 | 
| commit | 9933fc0ac1ac14b795819cd63d05ea92112f690a (patch) | |
| tree | bff42e3494fd5401e6b171ddae8f52ecd1defd91 | |
| parent | 33853a0dde359ded0534204eb6857ad5166d515b (diff) | |
ext4: introduce ext4_kvmalloc(), ext4_kzalloc(), and ext4_kvfree()
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>
| -rw-r--r-- | fs/ext4/ext4.h | 3 | ||||
| -rw-r--r-- | fs/ext4/super.c | 54 | 
2 files changed, 39 insertions, 18 deletions
| diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index ba2009b49a55..db9feadf53a0 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -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))); diff --git a/fs/ext4/super.c b/fs/ext4/super.c index cfe9f39c4ba2..658f5864e9cf 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -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)  { @@ -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); @@ -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++) { @@ -3750,12 +3772,8 @@ failed_mount_wq:  	}  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); | 
