summaryrefslogtreecommitdiffstats
path: root/fs/ext2/super.c
diff options
context:
space:
mode:
authorBadari Pulavarty <pbadari@us.ibm.com>2007-07-15 23:41:58 -0700
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-16 09:05:52 -0700
commit2235219b7721b8e74de6841e79240936561a2b63 (patch)
tree162dad89927c77f9e640d43fefa7ca20b0653262 /fs/ext2/super.c
parent8f14137e284d5733e7be05bd95656f59391b942e (diff)
ext2: 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>
Diffstat (limited to 'fs/ext2/super.c')
-rw-r--r--fs/ext2/super.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 5de5061eb33..b2efd9083b9 100644
--- a/fs/ext2/super.c
+++ b/fs/ext2/super.c
@@ -1099,15 +1099,18 @@ static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf)
struct super_block *sb = dentry->d_sb;
struct ext2_sb_info *sbi = EXT2_SB(sb);
struct ext2_super_block *es = sbi->s_es;
- unsigned long overhead;
- int i;
u64 fsid;
if (test_opt (sb, MINIX_DF))
- overhead = 0;
- else {
+ sbi->s_overhead_last = 0;
+ else if (sbi->s_blocks_last != le32_to_cpu(es->s_blocks_count)) {
+ unsigned long i, overhead = 0;
+ smp_rmb();
+
/*
- * Compute the overhead (FS structures)
+ * Compute the overhead (FS structures). This is constant
+ * for a given filesystem unless the number of block groups
+ * changes so we cache the previous value until it does.
*/
/*
@@ -1131,17 +1134,22 @@ static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf)
*/
overhead += (sbi->s_groups_count *
(2 + sbi->s_itb_per_group));
+ sbi->s_overhead_last = overhead;
+ smp_wmb();
+ sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count);
}
buf->f_type = EXT2_SUPER_MAGIC;
buf->f_bsize = sb->s_blocksize;
- buf->f_blocks = le32_to_cpu(es->s_blocks_count) - overhead;
+ buf->f_blocks = le32_to_cpu(es->s_blocks_count) - sbi->s_overhead_last;
buf->f_bfree = ext2_count_free_blocks(sb);
+ es->s_free_blocks_count = cpu_to_le32(buf->f_bfree);
buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count);
if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count))
buf->f_bavail = 0;
buf->f_files = le32_to_cpu(es->s_inodes_count);
buf->f_ffree = ext2_count_free_inodes(sb);
+ es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
buf->f_namelen = EXT2_NAME_LEN;
fsid = le64_to_cpup((void *)es->s_uuid) ^
le64_to_cpup((void *)es->s_uuid + sizeof(u64));