diff options
Diffstat (limited to 'fs/ext4/mballoc.c')
-rw-r--r-- | fs/ext4/mballoc.c | 55 |
1 files changed, 25 insertions, 30 deletions
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 5b4d4e3a4d58..851f49b2f9d2 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -2608,18 +2608,12 @@ int ext4_mb_release(struct super_block *sb) | |||
2608 | static inline int ext4_issue_discard(struct super_block *sb, | 2608 | static inline int ext4_issue_discard(struct super_block *sb, |
2609 | ext4_group_t block_group, ext4_grpblk_t block, int count) | 2609 | ext4_group_t block_group, ext4_grpblk_t block, int count) |
2610 | { | 2610 | { |
2611 | int ret; | ||
2612 | ext4_fsblk_t discard_block; | 2611 | ext4_fsblk_t discard_block; |
2613 | 2612 | ||
2614 | discard_block = block + ext4_group_first_block_no(sb, block_group); | 2613 | discard_block = block + ext4_group_first_block_no(sb, block_group); |
2615 | trace_ext4_discard_blocks(sb, | 2614 | trace_ext4_discard_blocks(sb, |
2616 | (unsigned long long) discard_block, count); | 2615 | (unsigned long long) discard_block, count); |
2617 | ret = sb_issue_discard(sb, discard_block, count, GFP_NOFS, 0); | 2616 | return sb_issue_discard(sb, discard_block, count, GFP_NOFS, 0); |
2618 | if (ret == -EOPNOTSUPP) { | ||
2619 | ext4_warning(sb, "discard not supported, disabling"); | ||
2620 | clear_opt(EXT4_SB(sb)->s_mount_opt, DISCARD); | ||
2621 | } | ||
2622 | return ret; | ||
2623 | } | 2617 | } |
2624 | 2618 | ||
2625 | /* | 2619 | /* |
@@ -2631,7 +2625,7 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn) | |||
2631 | struct super_block *sb = journal->j_private; | 2625 | struct super_block *sb = journal->j_private; |
2632 | struct ext4_buddy e4b; | 2626 | struct ext4_buddy e4b; |
2633 | struct ext4_group_info *db; | 2627 | struct ext4_group_info *db; |
2634 | int err, count = 0, count2 = 0; | 2628 | int err, ret, count = 0, count2 = 0; |
2635 | struct ext4_free_data *entry; | 2629 | struct ext4_free_data *entry; |
2636 | struct list_head *l, *ltmp; | 2630 | struct list_head *l, *ltmp; |
2637 | 2631 | ||
@@ -2641,9 +2635,15 @@ static void release_blocks_on_commit(journal_t *journal, transaction_t *txn) | |||
2641 | mb_debug(1, "gonna free %u blocks in group %u (0x%p):", | 2635 | mb_debug(1, "gonna free %u blocks in group %u (0x%p):", |
2642 | entry->count, entry->group, entry); | 2636 | entry->count, entry->group, entry); |
2643 | 2637 | ||
2644 | if (test_opt(sb, DISCARD)) | 2638 | if (test_opt(sb, DISCARD)) { |
2645 | ext4_issue_discard(sb, entry->group, | 2639 | ret = ext4_issue_discard(sb, entry->group, |
2646 | entry->start_blk, entry->count); | 2640 | entry->start_blk, entry->count); |
2641 | if (unlikely(ret == -EOPNOTSUPP)) { | ||
2642 | ext4_warning(sb, "discard not supported, " | ||
2643 | "disabling"); | ||
2644 | clear_opt(sb, DISCARD); | ||
2645 | } | ||
2646 | } | ||
2647 | 2647 | ||
2648 | err = ext4_mb_load_buddy(sb, entry->group, &e4b); | 2648 | err = ext4_mb_load_buddy(sb, entry->group, &e4b); |
2649 | /* we expect to find existing buddy because it's pinned */ | 2649 | /* we expect to find existing buddy because it's pinned */ |
@@ -3881,19 +3881,6 @@ repeat: | |||
3881 | } | 3881 | } |
3882 | } | 3882 | } |
3883 | 3883 | ||
3884 | /* | ||
3885 | * finds all preallocated spaces and return blocks being freed to them | ||
3886 | * if preallocated space becomes full (no block is used from the space) | ||
3887 | * then the function frees space in buddy | ||
3888 | * XXX: at the moment, truncate (which is the only way to free blocks) | ||
3889 | * discards all preallocations | ||
3890 | */ | ||
3891 | static void ext4_mb_return_to_preallocation(struct inode *inode, | ||
3892 | struct ext4_buddy *e4b, | ||
3893 | sector_t block, int count) | ||
3894 | { | ||
3895 | BUG_ON(!list_empty(&EXT4_I(inode)->i_prealloc_list)); | ||
3896 | } | ||
3897 | #ifdef CONFIG_EXT4_DEBUG | 3884 | #ifdef CONFIG_EXT4_DEBUG |
3898 | static void ext4_mb_show_ac(struct ext4_allocation_context *ac) | 3885 | static void ext4_mb_show_ac(struct ext4_allocation_context *ac) |
3899 | { | 3886 | { |
@@ -4283,7 +4270,7 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, | |||
4283 | * EDQUOT check, as blocks and quotas have been already | 4270 | * EDQUOT check, as blocks and quotas have been already |
4284 | * reserved when data being copied into pagecache. | 4271 | * reserved when data being copied into pagecache. |
4285 | */ | 4272 | */ |
4286 | if (EXT4_I(ar->inode)->i_delalloc_reserved_flag) | 4273 | if (ext4_test_inode_state(ar->inode, EXT4_STATE_DELALLOC_RESERVED)) |
4287 | ar->flags |= EXT4_MB_DELALLOC_RESERVED; | 4274 | ar->flags |= EXT4_MB_DELALLOC_RESERVED; |
4288 | else { | 4275 | else { |
4289 | /* Without delayed allocation we need to verify | 4276 | /* Without delayed allocation we need to verify |
@@ -4380,7 +4367,8 @@ out: | |||
4380 | if (inquota && ar->len < inquota) | 4367 | if (inquota && ar->len < inquota) |
4381 | dquot_free_block(ar->inode, inquota - ar->len); | 4368 | dquot_free_block(ar->inode, inquota - ar->len); |
4382 | if (!ar->len) { | 4369 | if (!ar->len) { |
4383 | if (!EXT4_I(ar->inode)->i_delalloc_reserved_flag) | 4370 | if (!ext4_test_inode_state(ar->inode, |
4371 | EXT4_STATE_DELALLOC_RESERVED)) | ||
4384 | /* release all the reserved blocks if non delalloc */ | 4372 | /* release all the reserved blocks if non delalloc */ |
4385 | percpu_counter_sub(&sbi->s_dirtyblocks_counter, | 4373 | percpu_counter_sub(&sbi->s_dirtyblocks_counter, |
4386 | reserv_blks); | 4374 | reserv_blks); |
@@ -4626,7 +4614,11 @@ do_more: | |||
4626 | * blocks being freed are metadata. these blocks shouldn't | 4614 | * blocks being freed are metadata. these blocks shouldn't |
4627 | * be used until this transaction is committed | 4615 | * be used until this transaction is committed |
4628 | */ | 4616 | */ |
4629 | new_entry = kmem_cache_alloc(ext4_free_ext_cachep, GFP_NOFS); | 4617 | new_entry = kmem_cache_alloc(ext4_free_ext_cachep, GFP_NOFS); |
4618 | if (!new_entry) { | ||
4619 | err = -ENOMEM; | ||
4620 | goto error_return; | ||
4621 | } | ||
4630 | new_entry->start_blk = bit; | 4622 | new_entry->start_blk = bit; |
4631 | new_entry->group = block_group; | 4623 | new_entry->group = block_group; |
4632 | new_entry->count = count; | 4624 | new_entry->count = count; |
@@ -4643,7 +4635,6 @@ do_more: | |||
4643 | ext4_lock_group(sb, block_group); | 4635 | ext4_lock_group(sb, block_group); |
4644 | mb_clear_bits(bitmap_bh->b_data, bit, count); | 4636 | mb_clear_bits(bitmap_bh->b_data, bit, count); |
4645 | mb_free_blocks(inode, &e4b, bit, count); | 4637 | mb_free_blocks(inode, &e4b, bit, count); |
4646 | ext4_mb_return_to_preallocation(inode, &e4b, block, count); | ||
4647 | } | 4638 | } |
4648 | 4639 | ||
4649 | ret = ext4_free_blks_count(sb, gdp) + count; | 4640 | ret = ext4_free_blks_count(sb, gdp) + count; |
@@ -4718,8 +4709,6 @@ static int ext4_trim_extent(struct super_block *sb, int start, int count, | |||
4718 | ext4_unlock_group(sb, group); | 4709 | ext4_unlock_group(sb, group); |
4719 | 4710 | ||
4720 | ret = ext4_issue_discard(sb, group, start, count); | 4711 | ret = ext4_issue_discard(sb, group, start, count); |
4721 | if (ret) | ||
4722 | ext4_std_error(sb, ret); | ||
4723 | 4712 | ||
4724 | ext4_lock_group(sb, group); | 4713 | ext4_lock_group(sb, group); |
4725 | mb_free_blocks(NULL, e4b, start, ex.fe_len); | 4714 | mb_free_blocks(NULL, e4b, start, ex.fe_len); |
@@ -4819,6 +4808,8 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) | |||
4819 | ext4_group_t group, ngroups = ext4_get_groups_count(sb); | 4808 | ext4_group_t group, ngroups = ext4_get_groups_count(sb); |
4820 | ext4_grpblk_t cnt = 0, first_block, last_block; | 4809 | ext4_grpblk_t cnt = 0, first_block, last_block; |
4821 | uint64_t start, len, minlen, trimmed; | 4810 | uint64_t start, len, minlen, trimmed; |
4811 | ext4_fsblk_t first_data_blk = | ||
4812 | le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block); | ||
4822 | int ret = 0; | 4813 | int ret = 0; |
4823 | 4814 | ||
4824 | start = range->start >> sb->s_blocksize_bits; | 4815 | start = range->start >> sb->s_blocksize_bits; |
@@ -4828,6 +4819,10 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) | |||
4828 | 4819 | ||
4829 | if (unlikely(minlen > EXT4_BLOCKS_PER_GROUP(sb))) | 4820 | if (unlikely(minlen > EXT4_BLOCKS_PER_GROUP(sb))) |
4830 | return -EINVAL; | 4821 | return -EINVAL; |
4822 | if (start < first_data_blk) { | ||
4823 | len -= first_data_blk - start; | ||
4824 | start = first_data_blk; | ||
4825 | } | ||
4831 | 4826 | ||
4832 | /* Determine first and last group to examine based on start and len */ | 4827 | /* Determine first and last group to examine based on start and len */ |
4833 | ext4_get_group_no_and_offset(sb, (ext4_fsblk_t) start, | 4828 | ext4_get_group_no_and_offset(sb, (ext4_fsblk_t) start, |
@@ -4851,7 +4846,7 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) | |||
4851 | if (len >= EXT4_BLOCKS_PER_GROUP(sb)) | 4846 | if (len >= EXT4_BLOCKS_PER_GROUP(sb)) |
4852 | len -= (EXT4_BLOCKS_PER_GROUP(sb) - first_block); | 4847 | len -= (EXT4_BLOCKS_PER_GROUP(sb) - first_block); |
4853 | else | 4848 | else |
4854 | last_block = len; | 4849 | last_block = first_block + len; |
4855 | 4850 | ||
4856 | if (e4b.bd_info->bb_free >= minlen) { | 4851 | if (e4b.bd_info->bb_free >= minlen) { |
4857 | cnt = ext4_trim_all_free(sb, &e4b, first_block, | 4852 | cnt = ext4_trim_all_free(sb, &e4b, first_block, |