diff options
-rw-r--r-- | fs/ext4/mballoc.c | 127 |
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 | ||
422 | static struct kmem_cache *ext4_pspace_cachep; | 422 | static struct kmem_cache *ext4_pspace_cachep; |
423 | static 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, | |||
3758 | static int ext4_mb_release_group_pa(struct ext4_buddy *e4b, | 3775 | static 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) | |||
4231 | ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, | 4254 | ext4_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 | ||
4274 | repeat: | 4303 | repeat: |
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 | ||
4303 | out: | 4332 | out: |
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 | } |
4309 | static void ext4_mb_poll_new_transaction(struct super_block *sb, | 4339 | static 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 | ||
4443 | do_more: | 4476 | do_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: | |||
4548 | error_return: | 4583 | error_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 | } |