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 /fs/ext4 | |
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>
Diffstat (limited to 'fs/ext4')
-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, | |||
1874 | ext4_fsblk_t n_blocks_count); | 1874 | ext4_fsblk_t n_blocks_count); |
1875 | 1875 | ||
1876 | /* super.c */ | 1876 | /* super.c */ |
1877 | extern void *ext4_kvmalloc(size_t size, gfp_t flags); | ||
1878 | extern void *ext4_kvzalloc(size_t size, gfp_t flags); | ||
1879 | extern void ext4_kvfree(void *ptr); | ||
1877 | extern void __ext4_error(struct super_block *, const char *, unsigned int, | 1880 | extern void __ext4_error(struct super_block *, const char *, unsigned int, |
1878 | const char *, ...) | 1881 | const char *, ...) |
1879 | __attribute__ ((format (printf, 4, 5))); | 1882 | __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 = { | |||
110 | #define IS_EXT3_SB(sb) (0) | 110 | #define IS_EXT3_SB(sb) (0) |
111 | #endif | 111 | #endif |
112 | 112 | ||
113 | void *ext4_kvmalloc(size_t size, gfp_t flags) | ||
114 | { | ||
115 | void *ret; | ||
116 | |||
117 | ret = kmalloc(size, flags); | ||
118 | if (!ret) | ||
119 | ret = __vmalloc(size, flags, PAGE_KERNEL); | ||
120 | return ret; | ||
121 | } | ||
122 | |||
123 | void *ext4_kvzalloc(size_t size, gfp_t flags) | ||
124 | { | ||
125 | void *ret; | ||
126 | |||
127 | ret = kmalloc(size, flags); | ||
128 | if (!ret) | ||
129 | ret = __vmalloc(size, flags | __GFP_ZERO, PAGE_KERNEL); | ||
130 | return ret; | ||
131 | } | ||
132 | |||
133 | void ext4_kvfree(void *ptr) | ||
134 | { | ||
135 | if (is_vmalloc_addr(ptr)) | ||
136 | vfree(ptr); | ||
137 | else | ||
138 | kfree(ptr); | ||
139 | |||
140 | } | ||
141 | |||
113 | ext4_fsblk_t ext4_block_bitmap(struct super_block *sb, | 142 | ext4_fsblk_t ext4_block_bitmap(struct super_block *sb, |
114 | struct ext4_group_desc *bg) | 143 | struct ext4_group_desc *bg) |
115 | { | 144 | { |
@@ -791,10 +820,7 @@ static void ext4_put_super(struct super_block *sb) | |||
791 | for (i = 0; i < sbi->s_gdb_count; i++) | 820 | for (i = 0; i < sbi->s_gdb_count; i++) |
792 | brelse(sbi->s_group_desc[i]); | 821 | brelse(sbi->s_group_desc[i]); |
793 | kfree(sbi->s_group_desc); | 822 | kfree(sbi->s_group_desc); |
794 | if (is_vmalloc_addr(sbi->s_flex_groups)) | 823 | ext4_kvfree(sbi->s_flex_groups); |
795 | vfree(sbi->s_flex_groups); | ||
796 | else | ||
797 | kfree(sbi->s_flex_groups); | ||
798 | percpu_counter_destroy(&sbi->s_freeblocks_counter); | 824 | percpu_counter_destroy(&sbi->s_freeblocks_counter); |
799 | percpu_counter_destroy(&sbi->s_freeinodes_counter); | 825 | percpu_counter_destroy(&sbi->s_freeinodes_counter); |
800 | percpu_counter_destroy(&sbi->s_dirs_counter); | 826 | percpu_counter_destroy(&sbi->s_dirs_counter); |
@@ -1977,15 +2003,11 @@ static int ext4_fill_flex_info(struct super_block *sb) | |||
1977 | ((le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) + 1) << | 2003 | ((le16_to_cpu(sbi->s_es->s_reserved_gdt_blocks) + 1) << |
1978 | EXT4_DESC_PER_BLOCK_BITS(sb))) / groups_per_flex; | 2004 | EXT4_DESC_PER_BLOCK_BITS(sb))) / groups_per_flex; |
1979 | size = flex_group_count * sizeof(struct flex_groups); | 2005 | size = flex_group_count * sizeof(struct flex_groups); |
1980 | sbi->s_flex_groups = kzalloc(size, GFP_KERNEL); | 2006 | sbi->s_flex_groups = ext4_kvzalloc(size, GFP_KERNEL); |
1981 | if (sbi->s_flex_groups == NULL) { | 2007 | if (sbi->s_flex_groups == NULL) { |
1982 | sbi->s_flex_groups = vzalloc(size); | 2008 | ext4_msg(sb, KERN_ERR, "not enough memory for %u flex groups", |
1983 | if (sbi->s_flex_groups == NULL) { | 2009 | flex_group_count); |
1984 | ext4_msg(sb, KERN_ERR, | 2010 | goto failed; |
1985 | "not enough memory for %u flex groups", | ||
1986 | flex_group_count); | ||
1987 | goto failed; | ||
1988 | } | ||
1989 | } | 2011 | } |
1990 | 2012 | ||
1991 | for (i = 0; i < sbi->s_groups_count; i++) { | 2013 | for (i = 0; i < sbi->s_groups_count; i++) { |
@@ -3750,12 +3772,8 @@ failed_mount_wq: | |||
3750 | } | 3772 | } |
3751 | failed_mount3: | 3773 | failed_mount3: |
3752 | del_timer(&sbi->s_err_report); | 3774 | del_timer(&sbi->s_err_report); |
3753 | if (sbi->s_flex_groups) { | 3775 | if (sbi->s_flex_groups) |
3754 | if (is_vmalloc_addr(sbi->s_flex_groups)) | 3776 | ext4_kvfree(sbi->s_flex_groups); |
3755 | vfree(sbi->s_flex_groups); | ||
3756 | else | ||
3757 | kfree(sbi->s_flex_groups); | ||
3758 | } | ||
3759 | percpu_counter_destroy(&sbi->s_freeblocks_counter); | 3777 | percpu_counter_destroy(&sbi->s_freeblocks_counter); |
3760 | percpu_counter_destroy(&sbi->s_freeinodes_counter); | 3778 | percpu_counter_destroy(&sbi->s_freeinodes_counter); |
3761 | percpu_counter_destroy(&sbi->s_dirs_counter); | 3779 | percpu_counter_destroy(&sbi->s_dirs_counter); |