aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorLukas Czerner <lczerner@redhat.com>2011-05-24 18:16:27 -0400
committerTheodore Ts'o <tytso@mit.edu>2011-05-24 18:16:27 -0400
commit78944086663e6c1b03f3d60bf7610128149be5fc (patch)
treefac4b6257258ffc15b59c8d42b6c569948daaed2 /fs/ext4
parentc867516de5256e9cfba2ec5847fa27e0f0ddd2c5 (diff)
ext4: only load buddy bitmap in ext4_trim_fs() when it is needed
Currently we are loading buddy ext4_mb_load_buddy() for every block group we are going through in ext4_trim_fs() in many cases just to find out that there is not enough space to be bothered with. As Amir Goldstein suggested we can use bb_free information directly from ext4_group_info. This commit removes ext4_mb_load_buddy() from ext4_trim_fs() and rather get the ext4_group_info via ext4_get_group_info() and use the bb_free information directly from that. This avoids unnecessary call to load buddy in the case the group does not have enough free space to trim. Loading buddy is now moved to ext4_trim_all_free(). Tested by me with xfstests 251. Signed-off-by: Lukas Czerner <lczerner@redhat.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-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 }