diff options
| author | Lukas Czerner <lczerner@redhat.com> | 2013-04-03 22:12:52 -0400 | 
|---|---|---|
| committer | Theodore Ts'o <tytso@mit.edu> | 2013-04-03 22:12:52 -0400 | 
| commit | 689110098c7df10fab8800d3bf8e727c21f426fb (patch) | |
| tree | 4115e575da8b49716e358ebd2459095863ad00e1 | |
| parent | a75ae78f087f933ab3432e98bb4dbbf2196cf6d5 (diff) | |
| download | olio-linux-3.10-689110098c7df10fab8800d3bf8e727c21f426fb.tar.xz olio-linux-3.10-689110098c7df10fab8800d3bf8e727c21f426fb.zip  | |
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>
| -rw-r--r-- | fs/ext4/balloc.c | 22 | ||||
| -rw-r--r-- | fs/ext4/ext4.h | 10 | ||||
| -rw-r--r-- | fs/ext4/super.c | 4 | 
3 files changed, 29 insertions, 7 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 92e68b33fff..d6babf94907 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c @@ -49,14 +49,24 @@ void ext4_get_group_no_and_offset(struct super_block *sb, ext4_fsblk_t blocknr,  } -static int ext4_block_in_group(struct super_block *sb, ext4_fsblk_t block, -			ext4_group_t block_group) +/* + * Check whether the 'block' lives within the 'block_group'. Returns 1 if so + * and 0 otherwise. + */ +static inline int ext4_block_in_group(struct super_block *sb, +				      ext4_fsblk_t block, +				      ext4_group_t block_group)  {  	ext4_group_t actual_group; -	ext4_get_group_no_and_offset(sb, block, &actual_group, NULL); -	if (actual_group == block_group) -		return 1; -	return 0; + +	if (test_opt2(sb, STD_GROUP_SIZE)) +		actual_group = +			(le32_to_cpu(EXT4_SB(sb)->s_es->s_first_data_block) + +			block) >> +			(EXT4_BLOCK_SIZE_BITS(sb) + EXT4_CLUSTER_BITS(sb) + 3); +	else +		ext4_get_group_no_and_offset(sb, block, &actual_group, NULL); +	return (actual_group == block_group) ? 1 : 0;  }  /* Return the number of clusters used for file system metadata; this diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 73f3e60f707..cc58aa8e986 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -949,7 +949,7 @@ struct ext4_inode_info {  #define EXT2_FLAGS_TEST_FILESYS		0x0004	/* to test development code */  /* - * Mount flags + * Mount flags set via mount options or defaults   */  #define EXT4_MOUNT_GRPID		0x00004	/* Create files with directory's group */  #define EXT4_MOUNT_DEBUG		0x00008	/* Some debugging messages */ @@ -981,8 +981,16 @@ struct ext4_inode_info {  #define EXT4_MOUNT_DISCARD		0x40000000 /* Issue DISCARD requests */  #define EXT4_MOUNT_INIT_INODE_TABLE	0x80000000 /* Initialize uninitialized itables */ +/* + * Mount flags set either automatically (could not be set by mount option) + * based on per file system feature or property or in special cases such as + * distinguishing between explicit mount option definition and default. + */  #define EXT4_MOUNT2_EXPLICIT_DELALLOC	0x00000001 /* User explicitly  						      specified delalloc */ +#define EXT4_MOUNT2_STD_GROUP_SIZE	0x00000002 /* We have standard group +						      size of blocksize * 8 +						      blocks */  #define clear_opt(sb, opt)		EXT4_SB(sb)->s_mount_opt &= \  						~EXT4_MOUNT_##opt diff --git a/fs/ext4/super.c b/fs/ext4/super.c index febbe0e1802..525beb6e3e1 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;  |