aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBadari Pulavarty <pbadari@us.ibm.com>2007-07-16 02:42:00 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-16 12:05:52 -0400
commit5e70030d4cf91613530a23b40ad9919bb9ee114f (patch)
tree30a53102b73179840cac06ed325ece645585a566
parenta71ce8c6c9bf269b192f352ea555217815cf027e (diff)
ext4: statfs speed up
This is a patch that speeds up statfs. It is very simple - the "overhead" calculation, which takes a huge amount of time for large filesystems, never changes unless the size of the filesystem itself changes. That means we can store it in memory and only recalculate if the filesystem has been resized (almost never). It also fixes a minor problem that we never update the on-disk superblock free blocks/inodes counts until the filesystem is unmounted. While not fatal, we may as well update that on disk when we have the information, and it makes things like debugfs and dumpe2fs report a bit more accurate info. Signed-off-by: Badari Pulavarty <pbadari@us.ibm.com> Signed-off-by: Andreas Dilger <adilger@clusterfs.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/ext4/super.c25
-rw-r--r--include/linux/ext4_fs_sb.h2
2 files changed, 17 insertions, 10 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index adcbfadfcb4c..d0d8c76c7edb 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -2500,19 +2500,19 @@ static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf)
2500 struct super_block *sb = dentry->d_sb; 2500 struct super_block *sb = dentry->d_sb;
2501 struct ext4_sb_info *sbi = EXT4_SB(sb); 2501 struct ext4_sb_info *sbi = EXT4_SB(sb);
2502 struct ext4_super_block *es = sbi->s_es; 2502 struct ext4_super_block *es = sbi->s_es;
2503 ext4_fsblk_t overhead;
2504 int i;
2505 u64 fsid; 2503 u64 fsid;
2506 2504
2507 if (test_opt (sb, MINIX_DF)) 2505 if (test_opt(sb, MINIX_DF)) {
2508 overhead = 0; 2506 sbi->s_overhead_last = 0;
2509 else { 2507 } else if (sbi->s_blocks_last != le32_to_cpu(es->s_blocks_count)) {
2510 unsigned long ngroups; 2508 unsigned long ngroups = sbi->s_groups_count, i;
2511 ngroups = EXT4_SB(sb)->s_groups_count; 2509 ext4_fsblk_t overhead = 0;
2512 smp_rmb(); 2510 smp_rmb();
2513 2511
2514 /* 2512 /*
2515 * Compute the overhead (FS structures) 2513 * Compute the overhead (FS structures). This is constant
2514 * for a given filesystem unless the number of block groups
2515 * changes so we cache the previous value until it does.
2516 */ 2516 */
2517 2517
2518 /* 2518 /*
@@ -2536,18 +2536,23 @@ static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf)
2536 * Every block group has an inode bitmap, a block 2536 * Every block group has an inode bitmap, a block
2537 * bitmap, and an inode table. 2537 * bitmap, and an inode table.
2538 */ 2538 */
2539 overhead += (ngroups * (2 + EXT4_SB(sb)->s_itb_per_group)); 2539 overhead += ngroups * (2 + sbi->s_itb_per_group);
2540 sbi->s_overhead_last = overhead;
2541 smp_wmb();
2542 sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count);
2540 } 2543 }
2541 2544
2542 buf->f_type = EXT4_SUPER_MAGIC; 2545 buf->f_type = EXT4_SUPER_MAGIC;
2543 buf->f_bsize = sb->s_blocksize; 2546 buf->f_bsize = sb->s_blocksize;
2544 buf->f_blocks = ext4_blocks_count(es) - overhead; 2547 buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last;
2545 buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter); 2548 buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter);
2549 es->s_free_blocks_count = cpu_to_le32(buf->f_bfree);
2546 buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es); 2550 buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es);
2547 if (buf->f_bfree < ext4_r_blocks_count(es)) 2551 if (buf->f_bfree < ext4_r_blocks_count(es))
2548 buf->f_bavail = 0; 2552 buf->f_bavail = 0;
2549 buf->f_files = le32_to_cpu(es->s_inodes_count); 2553 buf->f_files = le32_to_cpu(es->s_inodes_count);
2550 buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter); 2554 buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter);
2555 es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
2551 buf->f_namelen = EXT4_NAME_LEN; 2556 buf->f_namelen = EXT4_NAME_LEN;
2552 fsid = le64_to_cpup((void *)es->s_uuid) ^ 2557 fsid = le64_to_cpup((void *)es->s_uuid) ^
2553 le64_to_cpup((void *)es->s_uuid + sizeof(u64)); 2558 le64_to_cpup((void *)es->s_uuid + sizeof(u64));
diff --git a/include/linux/ext4_fs_sb.h b/include/linux/ext4_fs_sb.h
index 691a713139ce..2347557a327a 100644
--- a/include/linux/ext4_fs_sb.h
+++ b/include/linux/ext4_fs_sb.h
@@ -39,6 +39,8 @@ struct ext4_sb_info {
39 unsigned long s_gdb_count; /* Number of group descriptor blocks */ 39 unsigned long s_gdb_count; /* Number of group descriptor blocks */
40 unsigned long s_desc_per_block; /* Number of group descriptors per block */ 40 unsigned long s_desc_per_block; /* Number of group descriptors per block */
41 unsigned long s_groups_count; /* Number of groups in the fs */ 41 unsigned long s_groups_count; /* Number of groups in the fs */
42 unsigned long s_overhead_last; /* Last calculated overhead */
43 unsigned long s_blocks_last; /* Last seen block count */
42 struct buffer_head * s_sbh; /* Buffer containing the super block */ 44 struct buffer_head * s_sbh; /* Buffer containing the super block */
43 struct ext4_super_block * s_es; /* Pointer to the super block in the buffer */ 45 struct ext4_super_block * s_es; /* Pointer to the super block in the buffer */
44 struct buffer_head ** s_group_desc; 46 struct buffer_head ** s_group_desc;