ext4: allocate struct ext4_allocation_context from a kmem cache

struct ext4_allocation_context is rather large, and this bloats
the stack of many functions which use it. Allocating it from
a named slab cache will alleviate this.

For example, with this change (on top of the noinline patch sent earlier):

-ext4_mb_new_blocks 200
+ext4_mb_new_blocks 40

-ext4_mb_free_blocks 344
+ext4_mb_free_blocks 168

-ext4_mb_release_inode_pa 216
+ext4_mb_release_inode_pa 40

-ext4_mb_release_group_pa 192
+ext4_mb_release_group_pa 24

Most of these stack-allocated structs are actually used only for
mballoc history; and in those cases often a smaller struct would do.
So changing that may be another way around it, at least for those
functions, if preferred. For now, in those cases where the ac
is only for history, an allocation failure simply skips the history
recording, and does not cause any other failures.


Signed-off-by: Eric Sandeen <sandeen@redhat.com>
Signed-off-by: Mingming Cao <cmm@us.ibm.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>


authored by Eric Sandeen and committed by Theodore Ts'o 256bdb49 c4e35e07

+82 -45
+82 -45
fs/ext4/mballoc.c
··· 420 #define MB_DEFAULT_GROUP_PREALLOC 512 421 422 static struct kmem_cache *ext4_pspace_cachep; 423 424 #ifdef EXT4_BB_MAX_BLOCKS 425 #undef EXT4_BB_MAX_BLOCKS ··· 2960 if (ext4_pspace_cachep == NULL) 2961 return -ENOMEM; 2962 2963 #ifdef CONFIG_PROC_FS 2964 proc_root_ext4 = proc_mkdir(EXT4_ROOT, proc_root_fs); 2965 if (proc_root_ext4 == NULL) 2966 printk(KERN_ERR "EXT4-fs: Unable to create %s\n", EXT4_ROOT); 2967 #endif 2968 - 2969 return 0; 2970 } 2971 ··· 2980 { 2981 /* XXX: synchronize_rcu(); */ 2982 kmem_cache_destroy(ext4_pspace_cachep); 2983 #ifdef CONFIG_PROC_FS 2984 remove_proc_entry(EXT4_ROOT, proc_root_fs); 2985 #endif ··· 3708 struct buffer_head *bitmap_bh, 3709 struct ext4_prealloc_space *pa) 3710 { 3711 - struct ext4_allocation_context ac; 3712 struct super_block *sb = e4b->bd_sb; 3713 struct ext4_sb_info *sbi = EXT4_SB(sb); 3714 unsigned long end; ··· 3724 BUG_ON(group != e4b->bd_group && pa->pa_len != 0); 3725 end = bit + pa->pa_len; 3726 3727 - ac.ac_sb = sb; 3728 - ac.ac_inode = pa->pa_inode; 3729 - ac.ac_op = EXT4_MB_HISTORY_DISCARD; 3730 3731 while (bit < end) { 3732 bit = ext4_find_next_zero_bit(bitmap_bh->b_data, end, bit); ··· 3746 (unsigned) group); 3747 free += next - bit; 3748 3749 - ac.ac_b_ex.fe_group = group; 3750 - ac.ac_b_ex.fe_start = bit; 3751 - ac.ac_b_ex.fe_len = next - bit; 3752 - ac.ac_b_ex.fe_logical = 0; 3753 - ext4_mb_store_history(&ac); 3754 3755 mb_free_blocks(pa->pa_inode, e4b, bit, next - bit); 3756 bit = next + 1; ··· 3766 } 3767 BUG_ON(free != pa->pa_free); 3768 atomic_add(free, &sbi->s_mb_discarded); 3769 3770 return err; 3771 } ··· 3775 static int ext4_mb_release_group_pa(struct ext4_buddy *e4b, 3776 struct ext4_prealloc_space *pa) 3777 { 3778 - struct ext4_allocation_context ac; 3779 struct super_block *sb = e4b->bd_sb; 3780 ext4_group_t group; 3781 ext4_grpblk_t bit; 3782 3783 - ac.ac_op = EXT4_MB_HISTORY_DISCARD; 3784 3785 BUG_ON(pa->pa_deleted == 0); 3786 ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit); ··· 3791 mb_free_blocks(pa->pa_inode, e4b, bit, pa->pa_len); 3792 atomic_add(pa->pa_len, &EXT4_SB(sb)->s_mb_discarded); 3793 3794 - ac.ac_sb = sb; 3795 - ac.ac_inode = NULL; 3796 - ac.ac_b_ex.fe_group = group; 3797 - ac.ac_b_ex.fe_start = bit; 3798 - ac.ac_b_ex.fe_len = pa->pa_len; 3799 - ac.ac_b_ex.fe_logical = 0; 3800 - ext4_mb_store_history(&ac); 3801 3802 return 0; 3803 } ··· 4254 ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, 4255 struct ext4_allocation_request *ar, int *errp) 4256 { 4257 - struct ext4_allocation_context ac; 4258 struct ext4_sb_info *sbi; 4259 struct super_block *sb; 4260 ext4_fsblk_t block = 0; ··· 4280 } 4281 inquota = ar->len; 4282 4283 ext4_mb_poll_new_transaction(sb, handle); 4284 4285 - *errp = ext4_mb_initialize_context(&ac, ar); 4286 if (*errp) { 4287 ar->len = 0; 4288 goto out; 4289 } 4290 4291 - ac.ac_op = EXT4_MB_HISTORY_PREALLOC; 4292 - if (!ext4_mb_use_preallocated(&ac)) { 4293 4294 - ac.ac_op = EXT4_MB_HISTORY_ALLOC; 4295 - ext4_mb_normalize_request(&ac, ar); 4296 4297 repeat: 4298 /* allocate space in core */ 4299 - ext4_mb_regular_allocator(&ac); 4300 4301 /* as we've just preallocated more space than 4302 * user requested orinally, we store allocated 4303 * space in a special descriptor */ 4304 - if (ac.ac_status == AC_STATUS_FOUND && 4305 - ac.ac_o_ex.fe_len < ac.ac_b_ex.fe_len) 4306 - ext4_mb_new_preallocation(&ac); 4307 } 4308 4309 - if (likely(ac.ac_status == AC_STATUS_FOUND)) { 4310 - ext4_mb_mark_diskspace_used(&ac, handle); 4311 *errp = 0; 4312 - block = ext4_grp_offs_to_block(sb, &ac.ac_b_ex); 4313 - ar->len = ac.ac_b_ex.fe_len; 4314 } else { 4315 - freed = ext4_mb_discard_preallocations(sb, ac.ac_o_ex.fe_len); 4316 if (freed) 4317 goto repeat; 4318 *errp = -ENOSPC; 4319 - ac.ac_b_ex.fe_len = 0; 4320 ar->len = 0; 4321 - ext4_mb_show_ac(&ac); 4322 } 4323 4324 - ext4_mb_release_context(&ac); 4325 4326 out: 4327 if (ar->len < inquota) 4328 DQUOT_FREE_BLOCK(ar->inode, inquota - ar->len); 4329 4330 return block; 4331 } 4332 static void ext4_mb_poll_new_transaction(struct super_block *sb, ··· 4437 { 4438 struct buffer_head *bitmap_bh = 0; 4439 struct super_block *sb = inode->i_sb; 4440 - struct ext4_allocation_context ac; 4441 struct ext4_group_desc *gdp; 4442 struct ext4_super_block *es; 4443 unsigned long overflow; ··· 4466 4467 ext4_debug("freeing block %lu\n", block); 4468 4469 - ac.ac_op = EXT4_MB_HISTORY_FREE; 4470 - ac.ac_inode = inode; 4471 - ac.ac_sb = sb; 4472 4473 do_more: 4474 overflow = 0; ··· 4537 BUFFER_TRACE(bitmap_bh, "dirtied bitmap block"); 4538 err = ext4_journal_dirty_metadata(handle, bitmap_bh); 4539 4540 - ac.ac_b_ex.fe_group = block_group; 4541 - ac.ac_b_ex.fe_start = bit; 4542 - ac.ac_b_ex.fe_len = count; 4543 - ext4_mb_store_history(&ac); 4544 4545 if (metadata) { 4546 /* blocks being freed are metadata. these blocks shouldn't ··· 4583 error_return: 4584 brelse(bitmap_bh); 4585 ext4_std_error(sb, err); 4586 return; 4587 }
··· 420 #define MB_DEFAULT_GROUP_PREALLOC 512 421 422 static struct kmem_cache *ext4_pspace_cachep; 423 + static struct kmem_cache *ext4_ac_cachep; 424 425 #ifdef EXT4_BB_MAX_BLOCKS 426 #undef EXT4_BB_MAX_BLOCKS ··· 2959 if (ext4_pspace_cachep == NULL) 2960 return -ENOMEM; 2961 2962 + ext4_ac_cachep = 2963 + kmem_cache_create("ext4_alloc_context", 2964 + sizeof(struct ext4_allocation_context), 2965 + 0, SLAB_RECLAIM_ACCOUNT, NULL); 2966 + if (ext4_ac_cachep == NULL) { 2967 + kmem_cache_destroy(ext4_pspace_cachep); 2968 + return -ENOMEM; 2969 + } 2970 #ifdef CONFIG_PROC_FS 2971 proc_root_ext4 = proc_mkdir(EXT4_ROOT, proc_root_fs); 2972 if (proc_root_ext4 == NULL) 2973 printk(KERN_ERR "EXT4-fs: Unable to create %s\n", EXT4_ROOT); 2974 #endif 2975 return 0; 2976 } 2977 ··· 2972 { 2973 /* XXX: synchronize_rcu(); */ 2974 kmem_cache_destroy(ext4_pspace_cachep); 2975 + kmem_cache_destroy(ext4_ac_cachep); 2976 #ifdef CONFIG_PROC_FS 2977 remove_proc_entry(EXT4_ROOT, proc_root_fs); 2978 #endif ··· 3699 struct buffer_head *bitmap_bh, 3700 struct ext4_prealloc_space *pa) 3701 { 3702 + struct ext4_allocation_context *ac; 3703 struct super_block *sb = e4b->bd_sb; 3704 struct ext4_sb_info *sbi = EXT4_SB(sb); 3705 unsigned long end; ··· 3715 BUG_ON(group != e4b->bd_group && pa->pa_len != 0); 3716 end = bit + pa->pa_len; 3717 3718 + ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS); 3719 + 3720 + if (ac) { 3721 + ac->ac_sb = sb; 3722 + ac->ac_inode = pa->pa_inode; 3723 + ac->ac_op = EXT4_MB_HISTORY_DISCARD; 3724 + } 3725 3726 while (bit < end) { 3727 bit = ext4_find_next_zero_bit(bitmap_bh->b_data, end, bit); ··· 3733 (unsigned) group); 3734 free += next - bit; 3735 3736 + if (ac) { 3737 + ac->ac_b_ex.fe_group = group; 3738 + ac->ac_b_ex.fe_start = bit; 3739 + ac->ac_b_ex.fe_len = next - bit; 3740 + ac->ac_b_ex.fe_logical = 0; 3741 + ext4_mb_store_history(ac); 3742 + } 3743 3744 mb_free_blocks(pa->pa_inode, e4b, bit, next - bit); 3745 bit = next + 1; ··· 3751 } 3752 BUG_ON(free != pa->pa_free); 3753 atomic_add(free, &sbi->s_mb_discarded); 3754 + if (ac) 3755 + kmem_cache_free(ext4_ac_cachep, ac); 3756 3757 return err; 3758 } ··· 3758 static int ext4_mb_release_group_pa(struct ext4_buddy *e4b, 3759 struct ext4_prealloc_space *pa) 3760 { 3761 + struct ext4_allocation_context *ac; 3762 struct super_block *sb = e4b->bd_sb; 3763 ext4_group_t group; 3764 ext4_grpblk_t bit; 3765 3766 + ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS); 3767 + 3768 + if (ac) 3769 + ac->ac_op = EXT4_MB_HISTORY_DISCARD; 3770 3771 BUG_ON(pa->pa_deleted == 0); 3772 ext4_get_group_no_and_offset(sb, pa->pa_pstart, &group, &bit); ··· 3771 mb_free_blocks(pa->pa_inode, e4b, bit, pa->pa_len); 3772 atomic_add(pa->pa_len, &EXT4_SB(sb)->s_mb_discarded); 3773 3774 + if (ac) { 3775 + ac->ac_sb = sb; 3776 + ac->ac_inode = NULL; 3777 + ac->ac_b_ex.fe_group = group; 3778 + ac->ac_b_ex.fe_start = bit; 3779 + ac->ac_b_ex.fe_len = pa->pa_len; 3780 + ac->ac_b_ex.fe_logical = 0; 3781 + ext4_mb_store_history(ac); 3782 + kmem_cache_free(ext4_ac_cachep, ac); 3783 + } 3784 3785 return 0; 3786 } ··· 4231 ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, 4232 struct ext4_allocation_request *ar, int *errp) 4233 { 4234 + struct ext4_allocation_context *ac = NULL; 4235 struct ext4_sb_info *sbi; 4236 struct super_block *sb; 4237 ext4_fsblk_t block = 0; ··· 4257 } 4258 inquota = ar->len; 4259 4260 + ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS); 4261 + if (!ac) { 4262 + *errp = -ENOMEM; 4263 + return 0; 4264 + } 4265 + 4266 ext4_mb_poll_new_transaction(sb, handle); 4267 4268 + *errp = ext4_mb_initialize_context(ac, ar); 4269 if (*errp) { 4270 ar->len = 0; 4271 goto out; 4272 } 4273 4274 + ac->ac_op = EXT4_MB_HISTORY_PREALLOC; 4275 + if (!ext4_mb_use_preallocated(ac)) { 4276 4277 + ac->ac_op = EXT4_MB_HISTORY_ALLOC; 4278 + ext4_mb_normalize_request(ac, ar); 4279 4280 repeat: 4281 /* allocate space in core */ 4282 + ext4_mb_regular_allocator(ac); 4283 4284 /* as we've just preallocated more space than 4285 * user requested orinally, we store allocated 4286 * space in a special descriptor */ 4287 + if (ac->ac_status == AC_STATUS_FOUND && 4288 + ac->ac_o_ex.fe_len < ac->ac_b_ex.fe_len) 4289 + ext4_mb_new_preallocation(ac); 4290 } 4291 4292 + if (likely(ac->ac_status == AC_STATUS_FOUND)) { 4293 + ext4_mb_mark_diskspace_used(ac, handle); 4294 *errp = 0; 4295 + block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex); 4296 + ar->len = ac->ac_b_ex.fe_len; 4297 } else { 4298 + freed = ext4_mb_discard_preallocations(sb, ac->ac_o_ex.fe_len); 4299 if (freed) 4300 goto repeat; 4301 *errp = -ENOSPC; 4302 + ac->ac_b_ex.fe_len = 0; 4303 ar->len = 0; 4304 + ext4_mb_show_ac(ac); 4305 } 4306 4307 + ext4_mb_release_context(ac); 4308 4309 out: 4310 if (ar->len < inquota) 4311 DQUOT_FREE_BLOCK(ar->inode, inquota - ar->len); 4312 4313 + kmem_cache_free(ext4_ac_cachep, ac); 4314 return block; 4315 } 4316 static void ext4_mb_poll_new_transaction(struct super_block *sb, ··· 4407 { 4408 struct buffer_head *bitmap_bh = 0; 4409 struct super_block *sb = inode->i_sb; 4410 + struct ext4_allocation_context *ac = NULL; 4411 struct ext4_group_desc *gdp; 4412 struct ext4_super_block *es; 4413 unsigned long overflow; ··· 4436 4437 ext4_debug("freeing block %lu\n", block); 4438 4439 + ac = kmem_cache_alloc(ext4_ac_cachep, GFP_NOFS); 4440 + if (ac) { 4441 + ac->ac_op = EXT4_MB_HISTORY_FREE; 4442 + ac->ac_inode = inode; 4443 + ac->ac_sb = sb; 4444 + } 4445 4446 do_more: 4447 overflow = 0; ··· 4504 BUFFER_TRACE(bitmap_bh, "dirtied bitmap block"); 4505 err = ext4_journal_dirty_metadata(handle, bitmap_bh); 4506 4507 + if (ac) { 4508 + ac->ac_b_ex.fe_group = block_group; 4509 + ac->ac_b_ex.fe_start = bit; 4510 + ac->ac_b_ex.fe_len = count; 4511 + ext4_mb_store_history(ac); 4512 + } 4513 4514 if (metadata) { 4515 /* blocks being freed are metadata. these blocks shouldn't ··· 4548 error_return: 4549 brelse(bitmap_bh); 4550 ext4_std_error(sb, err); 4551 + if (ac) 4552 + kmem_cache_free(ext4_ac_cachep, ac); 4553 return; 4554 }