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.c49
1 files changed, 27 insertions, 22 deletions
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 254f1f9fc4e..38a11bf7932 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -4810,19 +4810,25 @@ static void ext4_trim_extent(struct super_block *sb, int start, int count,
4810 * the group buddy bitmap. This is done until whole group is scanned. 4810 * the group buddy bitmap. This is done until whole group is scanned.
4811 */ 4811 */
4812static ext4_grpblk_t 4812static ext4_grpblk_t
4813ext4_trim_all_free(struct super_block *sb, struct ext4_buddy *e4b, 4813ext4_trim_all_free(struct super_block *sb, ext4_group_t group,
4814 ext4_grpblk_t start, ext4_grpblk_t max, ext4_grpblk_t minblocks) 4814 ext4_grpblk_t start, ext4_grpblk_t max,
4815 ext4_grpblk_t minblocks)
4815{ 4816{
4816 void *bitmap; 4817 void *bitmap;
4817 ext4_grpblk_t next, count = 0; 4818 ext4_grpblk_t next, count = 0;
4818 ext4_group_t group; 4819 struct ext4_buddy e4b;
4820 int ret;
4819 4821
4820 BUG_ON(e4b == NULL); 4822 ret = ext4_mb_load_buddy(sb, group, &e4b);
4823 if (ret) {
4824 ext4_error(sb, "Error in loading buddy "
4825 "information for %u", group);
4826 return ret;
4827 }
4821 4828
4822 bitmap = e4b->bd_bitmap; 4829 bitmap = e4b.bd_bitmap;
4823 group = e4b->bd_group; 4830 start = (e4b.bd_info->bb_first_free > start) ?
4824 start = (e4b->bd_info->bb_first_free > start) ? 4831 e4b.bd_info->bb_first_free : start;
4825 e4b->bd_info->bb_first_free : start;
4826 ext4_lock_group(sb, group); 4832 ext4_lock_group(sb, group);
4827 4833
4828 while (start < max) { 4834 while (start < max) {
@@ -4833,7 +4839,7 @@ ext4_trim_all_free(struct super_block *sb, struct ext4_buddy *e4b,
4833 4839
4834 if ((next - start) >= minblocks) { 4840 if ((next - start) >= minblocks) {
4835 ext4_trim_extent(sb, start, 4841 ext4_trim_extent(sb, start,
4836 next - start, group, e4b); 4842 next - start, group, &e4b);
4837 count += next - start; 4843 count += next - start;
4838 } 4844 }
4839 start = next + 1; 4845 start = next + 1;
@@ -4849,10 +4855,11 @@ ext4_trim_all_free(struct super_block *sb, struct ext4_buddy *e4b,
4849 ext4_lock_group(sb, group); 4855 ext4_lock_group(sb, group);
4850 } 4856 }
4851 4857
4852 if ((e4b->bd_info->bb_free - count) < minblocks) 4858 if ((e4b.bd_info->bb_free - count) < minblocks)
4853 break; 4859 break;
4854 } 4860 }
4855 ext4_unlock_group(sb, group); 4861 ext4_unlock_group(sb, group);
4862 ext4_mb_unload_buddy(&e4b);
4856 4863
4857 ext4_debug("trimmed %d blocks in the group %d\n", 4864 ext4_debug("trimmed %d blocks in the group %d\n",
4858 count, group); 4865 count, group);
@@ -4874,11 +4881,11 @@ ext4_trim_all_free(struct super_block *sb, struct ext4_buddy *e4b,
4874 */ 4881 */
4875int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range) 4882int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
4876{ 4883{
4877 struct ext4_buddy e4b; 4884 struct ext4_group_info *grp;
4878 ext4_group_t first_group, last_group; 4885 ext4_group_t first_group, last_group;
4879 ext4_group_t group, ngroups = ext4_get_groups_count(sb); 4886 ext4_group_t group, ngroups = ext4_get_groups_count(sb);
4880 ext4_grpblk_t cnt = 0, first_block, last_block; 4887 ext4_grpblk_t cnt = 0, first_block, last_block;
4881 uint64_t start, len, minlen, trimmed; 4888 uint64_t start, len, minlen, trimmed = 0;
4882 ext4_fsblk_t first_data_blk = 4889 ext4_fsblk_t first_data_blk =
4883 le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block); 4890 le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block);
4884 int ret = 0; 4891 int ret = 0;
@@ -4886,7 +4893,6 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
4886 start = range->start >> sb->s_blocksize_bits; 4893 start = range->start >> sb->s_blocksize_bits;
4887 len = range->len >> sb->s_blocksize_bits; 4894 len = range->len >> sb->s_blocksize_bits;
4888 minlen = range->minlen >> sb->s_blocksize_bits; 4895 minlen = range->minlen >> sb->s_blocksize_bits;
4889 trimmed = 0;
4890 4896
4891 if (unlikely(minlen > EXT4_BLOCKS_PER_GROUP(sb))) 4897 if (unlikely(minlen > EXT4_BLOCKS_PER_GROUP(sb)))
4892 return -EINVAL; 4898 return -EINVAL;
@@ -4907,11 +4913,12 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
4907 return -EINVAL; 4913 return -EINVAL;
4908 4914
4909 for (group = first_group; group <= last_group; group++) { 4915 for (group = first_group; group <= last_group; group++) {
4910 ret = ext4_mb_load_buddy(sb, group, &e4b); 4916 grp = ext4_get_group_info(sb, group);
4911 if (ret) { 4917 /* We only do this if the grp has never been initialized */
4912 ext4_error(sb, "Error in loading buddy " 4918 if (unlikely(EXT4_MB_GRP_NEED_INIT(grp))) {
4913 "information for %u", group); 4919 ret = ext4_mb_init_group(sb, group);
4914 break; 4920 if (ret)
4921 break;
4915 } 4922 }
4916 4923
4917 /* 4924 /*
@@ -4924,16 +4931,14 @@ int ext4_trim_fs(struct super_block *sb, struct fstrim_range *range)
4924 last_block = first_block + len; 4931 last_block = first_block + len;
4925 len -= last_block - first_block; 4932 len -= last_block - first_block;
4926 4933
4927 if (e4b.bd_info->bb_free >= minlen) { 4934 if (grp->bb_free >= minlen) {
4928 cnt = ext4_trim_all_free(sb, &e4b, first_block, 4935 cnt = ext4_trim_all_free(sb, group, first_block,
4929 last_block, minlen); 4936 last_block, minlen);
4930 if (cnt < 0) { 4937 if (cnt < 0) {
4931 ret = cnt; 4938 ret = cnt;
4932 ext4_mb_unload_buddy(&e4b);
4933 break; 4939 break;
4934 } 4940 }
4935 } 4941 }
4936 ext4_mb_unload_buddy(&e4b);
4937 trimmed += cnt; 4942 trimmed += cnt;
4938 first_block = 0; 4943 first_block = 0;
4939 } 4944 }