summaryrefslogtreecommitdiff
path: root/fs/ext4/super.c
diff options
context:
space:
mode:
authorLukas Czerner <lczerner@redhat.com>2013-04-04 06:12:52 +0400
committerTheodore Ts'o <tytso@mit.edu>2013-04-04 06:12:52 +0400
commit689110098c7df10fab8800d3bf8e727c21f426fb (patch)
tree4115e575da8b49716e358ebd2459095863ad00e1 /fs/ext4/super.c
parenta75ae78f087f933ab3432e98bb4dbbf2196cf6d5 (diff)
downloadlinux-689110098c7df10fab8800d3bf8e727c21f426fb.tar.xz
ext4: make ext4_block_in_group() much more efficient
Currently in when getting the block group number for a particular block in ext4_block_in_group() we're using ext4_get_group_no_and_offset() which uses do_div() to get the block group and the remainer which is offset within the group. We don't need all of that in ext4_block_in_group() as we only need to figure out the group number. This commit changes ext4_block_in_group() to calculate group number directly. This shows as a big improvement with regards to cpu utilization. Measuring fallocate -l 15T on fresh file system with perf showed that 23% of cpu time was spend in the ext4_get_group_no_and_offset(). With this change it completely disappears from the list only bumping the occurrence of ext4_init_block_bitmap() which is the biggest user of ext4_block_in_group() by 4%. As the result of this change on my system the fallocate call was approx. 10% faster. However since there is '-g' option in mkfs which allow us setting different groups size (mostly for developers) I've introduced new per file system flag whether we have a standard block group size or not. The flag is used to determine whether we can use the bit shift optimization or not. Signed-off-by: Lukas Czerner <lczerner@redhat.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r--fs/ext4/super.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index febbe0e18024..525beb6e3e1e 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -3529,6 +3529,10 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
sbi->s_addr_per_block_bits = ilog2(EXT4_ADDR_PER_BLOCK(sb));
sbi->s_desc_per_block_bits = ilog2(EXT4_DESC_PER_BLOCK(sb));
+ /* Do we have standard group size of blocksize * 8 blocks ? */
+ if (sbi->s_blocks_per_group == blocksize << 3)
+ set_opt2(sb, STD_GROUP_SIZE);
+
for (i = 0; i < 4; i++)
sbi->s_hash_seed[i] = le32_to_cpu(es->s_hash_seed[i]);
sbi->s_def_hash_version = es->s_def_hash_version;