aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBadari Pulavarty <pbadari@us.ibm.com>2007-07-16 02:41:58 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-16 12:05:52 -0400
commit2235219b7721b8e74de6841e79240936561a2b63 (patch)
tree162dad89927c77f9e640d43fefa7ca20b0653262
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>
-rw-r--r--fs/ext2/super.c20
-rw-r--r--include/linux/ext2_fs_sb.h2
2 files changed, 16 insertions, 6 deletions
diff --git a/fs/ext2/super.c b/fs/ext2/super.c
index 5de5061eb331..b2efd9083b9b 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)
1099 struct super_block *sb = dentry->d_sb; 1099 struct super_block *sb = dentry->d_sb;
1100 struct ext2_sb_info *sbi = EXT2_SB(sb); 1100 struct ext2_sb_info *sbi = EXT2_SB(sb);
1101 struct ext2_super_block *es = sbi->s_es; 1101 struct ext2_super_block *es = sbi->s_es;
1102 unsigned long overhead;
1103 int i;
1104 u64 fsid; 1102 u64 fsid;
1105 1103
1106 if (test_opt (sb, MINIX_DF)) 1104 if (test_opt (sb, MINIX_DF))
1107 overhead = 0; 1105 sbi->s_overhead_last = 0;
1108 else { 1106 else if (sbi->s_blocks_last != le32_to_cpu(es->s_blocks_count)) {
1107 unsigned long i, overhead = 0;
1108 smp_rmb();
1109
1109 /* 1110 /*
1110 * Compute the overhead (FS structures) 1111 * Compute the overhead (FS structures). This is constant
1112 * for a given filesystem unless the number of block groups
1113 * changes so we cache the previous value until it does.
1111 */ 1114 */
1112 1115
1113 /* 1116 /*
@@ -1131,17 +1134,22 @@ static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf)
1131 */ 1134 */
1132 overhead += (sbi->s_groups_count * 1135 overhead += (sbi->s_groups_count *
1133 (2 + sbi->s_itb_per_group)); 1136 (2 + sbi->s_itb_per_group));
1137 sbi->s_overhead_last = overhead;
1138 smp_wmb();
1139 sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count);
1134 } 1140 }
1135 1141
1136 buf->f_type = EXT2_SUPER_MAGIC; 1142 buf->f_type = EXT2_SUPER_MAGIC;
1137 buf->f_bsize = sb->s_blocksize; 1143 buf->f_bsize = sb->s_blocksize;
1138 buf->f_blocks = le32_to_cpu(es->s_blocks_count) - overhead; 1144 buf->f_blocks = le32_to_cpu(es->s_blocks_count) - sbi->s_overhead_last;
1139 buf->f_bfree = ext2_count_free_blocks(sb); 1145 buf->f_bfree = ext2_count_free_blocks(sb);
1146 es->s_free_blocks_count = cpu_to_le32(buf->f_bfree);
1140 buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count); 1147 buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count);
1141 if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count)) 1148 if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count))
1142 buf->f_bavail = 0; 1149 buf->f_bavail = 0;
1143 buf->f_files = le32_to_cpu(es->s_inodes_count); 1150 buf->f_files = le32_to_cpu(es->s_inodes_count);
1144 buf->f_ffree = ext2_count_free_inodes(sb); 1151 buf->f_ffree = ext2_count_free_inodes(sb);
1152 es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
1145 buf->f_namelen = EXT2_NAME_LEN; 1153 buf->f_namelen = EXT2_NAME_LEN;
1146 fsid = le64_to_cpup((void *)es->s_uuid) ^ 1154 fsid = le64_to_cpup((void *)es->s_uuid) ^
1147 le64_to_cpup((void *)es->s_uuid + sizeof(u64)); 1155 le64_to_cpup((void *)es->s_uuid + sizeof(u64));
diff --git a/include/linux/ext2_fs_sb.h b/include/linux/ext2_fs_sb.h
index 4eda0ed76a48..d149f2959e67 100644
--- a/include/linux/ext2_fs_sb.h
+++ b/include/linux/ext2_fs_sb.h
@@ -33,6 +33,8 @@ struct ext2_sb_info {
33 unsigned long s_gdb_count; /* Number of group descriptor blocks */ 33 unsigned long s_gdb_count; /* Number of group descriptor blocks */
34 unsigned long s_desc_per_block; /* Number of group descriptors per block */ 34 unsigned long s_desc_per_block; /* Number of group descriptors per block */
35 unsigned long s_groups_count; /* Number of groups in the fs */ 35 unsigned long s_groups_count; /* Number of groups in the fs */
36 unsigned long s_overhead_last; /* Last calculated overhead */
37 unsigned long s_blocks_last; /* Last seen block count */
36 struct buffer_head * s_sbh; /* Buffer containing the super block */ 38 struct buffer_head * s_sbh; /* Buffer containing the super block */
37 struct ext2_super_block * s_es; /* Pointer to the super block in the buffer */ 39 struct ext2_super_block * s_es; /* Pointer to the super block in the buffer */
38 struct buffer_head ** s_group_desc; 40 struct buffer_head ** s_group_desc;