diff options
Diffstat (limited to 'fs/ext4/mballoc.c')
-rw-r--r-- | fs/ext4/mballoc.c | 60 |
1 files changed, 43 insertions, 17 deletions
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 526e55358606..1bf6fe785c4f 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c | |||
@@ -1373,7 +1373,7 @@ static int mb_find_extent(struct ext4_buddy *e4b, int block, | |||
1373 | ex->fe_start += next; | 1373 | ex->fe_start += next; |
1374 | 1374 | ||
1375 | while (needed > ex->fe_len && | 1375 | while (needed > ex->fe_len && |
1376 | (buddy = mb_find_buddy(e4b, order, &max))) { | 1376 | mb_find_buddy(e4b, order, &max)) { |
1377 | 1377 | ||
1378 | if (block + 1 >= max) | 1378 | if (block + 1 >= max) |
1379 | break; | 1379 | break; |
@@ -2607,9 +2607,17 @@ static void ext4_free_data_callback(struct super_block *sb, | |||
2607 | mb_debug(1, "gonna free %u blocks in group %u (0x%p):", | 2607 | mb_debug(1, "gonna free %u blocks in group %u (0x%p):", |
2608 | entry->efd_count, entry->efd_group, entry); | 2608 | entry->efd_count, entry->efd_group, entry); |
2609 | 2609 | ||
2610 | if (test_opt(sb, DISCARD)) | 2610 | if (test_opt(sb, DISCARD)) { |
2611 | ext4_issue_discard(sb, entry->efd_group, | 2611 | err = ext4_issue_discard(sb, entry->efd_group, |
2612 | entry->efd_start_cluster, entry->efd_count); | 2612 | entry->efd_start_cluster, |
2613 | entry->efd_count); | ||
2614 | if (err && err != -EOPNOTSUPP) | ||
2615 | ext4_msg(sb, KERN_WARNING, "discard request in" | ||
2616 | " group:%d block:%d count:%d failed" | ||
2617 | " with %d", entry->efd_group, | ||
2618 | entry->efd_start_cluster, | ||
2619 | entry->efd_count, err); | ||
2620 | } | ||
2613 | 2621 | ||
2614 | err = ext4_mb_load_buddy(sb, entry->efd_group, &e4b); | 2622 | err = ext4_mb_load_buddy(sb, entry->efd_group, &e4b); |
2615 | /* we expect to find existing buddy because it's pinned */ | 2623 | /* we expect to find existing buddy because it's pinned */ |
@@ -4310,8 +4318,10 @@ ext4_fsblk_t ext4_mb_new_blocks(handle_t *handle, | |||
4310 | repeat: | 4318 | repeat: |
4311 | /* allocate space in core */ | 4319 | /* allocate space in core */ |
4312 | *errp = ext4_mb_regular_allocator(ac); | 4320 | *errp = ext4_mb_regular_allocator(ac); |
4313 | if (*errp) | 4321 | if (*errp) { |
4322 | ext4_discard_allocated_blocks(ac); | ||
4314 | goto errout; | 4323 | goto errout; |
4324 | } | ||
4315 | 4325 | ||
4316 | /* as we've just preallocated more space than | 4326 | /* as we've just preallocated more space than |
4317 | * user requested orinally, we store allocated | 4327 | * user requested orinally, we store allocated |
@@ -4333,10 +4343,10 @@ repeat: | |||
4333 | ac->ac_b_ex.fe_len = 0; | 4343 | ac->ac_b_ex.fe_len = 0; |
4334 | ac->ac_status = AC_STATUS_CONTINUE; | 4344 | ac->ac_status = AC_STATUS_CONTINUE; |
4335 | goto repeat; | 4345 | goto repeat; |
4336 | } else if (*errp) | 4346 | } else if (*errp) { |
4337 | errout: | ||
4338 | ext4_discard_allocated_blocks(ac); | 4347 | ext4_discard_allocated_blocks(ac); |
4339 | else { | 4348 | goto errout; |
4349 | } else { | ||
4340 | block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex); | 4350 | block = ext4_grp_offs_to_block(sb, &ac->ac_b_ex); |
4341 | ar->len = ac->ac_b_ex.fe_len; | 4351 | ar->len = ac->ac_b_ex.fe_len; |
4342 | } | 4352 | } |
@@ -4347,6 +4357,7 @@ repeat: | |||
4347 | *errp = -ENOSPC; | 4357 | *errp = -ENOSPC; |
4348 | } | 4358 | } |
4349 | 4359 | ||
4360 | errout: | ||
4350 | if (*errp) { | 4361 | if (*errp) { |
4351 | ac->ac_b_ex.fe_len = 0; | 4362 | ac->ac_b_ex.fe_len = 0; |
4352 | ar->len = 0; | 4363 | ar->len = 0; |
@@ -4656,8 +4667,16 @@ do_more: | |||
4656 | * with group lock held. generate_buddy look at | 4667 | * with group lock held. generate_buddy look at |
4657 | * them with group lock_held | 4668 | * them with group lock_held |
4658 | */ | 4669 | */ |
4659 | if (test_opt(sb, DISCARD)) | 4670 | if (test_opt(sb, DISCARD)) { |
4660 | ext4_issue_discard(sb, block_group, bit, count); | 4671 | err = ext4_issue_discard(sb, block_group, bit, count); |
4672 | if (err && err != -EOPNOTSUPP) | ||
4673 | ext4_msg(sb, KERN_WARNING, "discard request in" | ||
4674 | " group:%d block:%d count:%lu failed" | ||
4675 | " with %d", block_group, bit, count, | ||
4676 | err); | ||
4677 | } | ||
4678 | |||
4679 | |||
4661 | ext4_lock_group(sb, block_group); | 4680 | ext4_lock_group(sb, block_group); |
4662 | mb_clear_bits(bitmap_bh->b_data, bit, count_clusters); | 4681 | mb_clear_bits(bitmap_bh->b_data, bit, count_clusters); |
4663 | mb_free_blocks(inode, &e4b, bit, count_clusters); | 4682 | mb_free_blocks(inode, &e4b, bit, count_clusters); |
@@ -4851,10 +4870,11 @@ error_return: | |||
4851 | * one will allocate those blocks, mark it as used in buddy bitmap. This must | 4870 | * one will allocate those blocks, mark it as used in buddy bitmap. This must |
4852 | * be called with under the group lock. | 4871 | * be called with under the group lock. |
4853 | */ | 4872 | */ |
4854 | static void ext4_trim_extent(struct super_block *sb, int start, int count, | 4873 | static int ext4_trim_extent(struct super_block *sb, int start, int count, |
4855 | ext4_group_t group, struct ext4_buddy *e4b) | 4874 | ext4_group_t group, struct ext4_buddy *e4b) |
4856 | { | 4875 | { |
4857 | struct ext4_free_extent ex; | 4876 | struct ext4_free_extent ex; |
4877 | int ret = 0; | ||
4858 | 4878 | ||
4859 | trace_ext4_trim_extent(sb, group, start, count); | 4879 | trace_ext4_trim_extent(sb, group, start, count); |
4860 | 4880 | ||
@@ -4870,9 +4890,10 @@ static void ext4_trim_extent(struct super_block *sb, int start, int count, | |||
4870 | */ | 4890 | */ |
4871 | mb_mark_used(e4b, &ex); | 4891 | mb_mark_used(e4b, &ex); |
4872 | ext4_unlock_group(sb, group); | 4892 | ext4_unlock_group(sb, group); |
4873 | ext4_issue_discard(sb, group, start, count); | 4893 | ret = ext4_issue_discard(sb, group, start, count); |
4874 | ext4_lock_group(sb, group); | 4894 | ext4_lock_group(sb, group); |
4875 | mb_free_blocks(NULL, e4b, start, ex.fe_len); | 4895 | mb_free_blocks(NULL, e4b, start, ex.fe_len); |
4896 | return ret; | ||
4876 | } | 4897 | } |
4877 | 4898 | ||
4878 | /** | 4899 | /** |
@@ -4901,7 +4922,7 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group, | |||
4901 | void *bitmap; | 4922 | void *bitmap; |
4902 | ext4_grpblk_t next, count = 0, free_count = 0; | 4923 | ext4_grpblk_t next, count = 0, free_count = 0; |
4903 | struct ext4_buddy e4b; | 4924 | struct ext4_buddy e4b; |
4904 | int ret; | 4925 | int ret = 0; |
4905 | 4926 | ||
4906 | trace_ext4_trim_all_free(sb, group, start, max); | 4927 | trace_ext4_trim_all_free(sb, group, start, max); |
4907 | 4928 | ||
@@ -4928,8 +4949,11 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group, | |||
4928 | next = mb_find_next_bit(bitmap, max + 1, start); | 4949 | next = mb_find_next_bit(bitmap, max + 1, start); |
4929 | 4950 | ||
4930 | if ((next - start) >= minblocks) { | 4951 | if ((next - start) >= minblocks) { |
4931 | ext4_trim_extent(sb, start, | 4952 | ret = ext4_trim_extent(sb, start, |
4932 | next - start, group, &e4b); | 4953 | next - start, group, &e4b); |
4954 | if (ret && ret != -EOPNOTSUPP) | ||
4955 | break; | ||
4956 | ret = 0; | ||
4933 | count += next - start; | 4957 | count += next - start; |
4934 | } | 4958 | } |
4935 | free_count += next - start; | 4959 | free_count += next - start; |
@@ -4950,8 +4974,10 @@ ext4_trim_all_free(struct super_block *sb, ext4_group_t group, | |||
4950 | break; | 4974 | break; |
4951 | } | 4975 | } |
4952 | 4976 | ||
4953 | if (!ret) | 4977 | if (!ret) { |
4978 | ret = count; | ||
4954 | EXT4_MB_GRP_SET_TRIMMED(e4b.bd_info); | 4979 | EXT4_MB_GRP_SET_TRIMMED(e4b.bd_info); |
4980 | } | ||
4955 | out: | 4981 | out: |
4956 | ext4_unlock_group(sb, group); | 4982 | ext4_unlock_group(sb, group); |
4957 | ext4_mb_unload_buddy(&e4b); | 4983 | ext4_mb_unload_buddy(&e4b); |
@@ -4959,7 +4985,7 @@ out: | |||
4959 | ext4_debug("trimmed %d blocks in the group %d\n", | 4985 | ext4_debug("trimmed %d blocks in the group %d\n", |
4960 | count, group); | 4986 | count, group); |
4961 | 4987 | ||
4962 | return count; | 4988 | return ret; |
4963 | } | 4989 | } |
4964 | 4990 | ||
4965 | /** | 4991 | /** |