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