aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/mballoc.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4/mballoc.c')
-rw-r--r--fs/ext4/mballoc.c60
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,
4310repeat: 4318repeat:
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
4360errout:
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 */
4854static void ext4_trim_extent(struct super_block *sb, int start, int count, 4873static 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 }
4955out: 4981out:
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/**