aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBadari Pulavarty <pbadari@us.ibm.com>2007-07-16 02:41:59 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-16 12:05:52 -0400
commita71ce8c6c9bf269b192f352ea555217815cf027e (patch)
tree32d1c37b890120e0eb12c2f4fe821af5507aad91
parent2235219b7721b8e74de6841e79240936561a2b63 (diff)
ext3: 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/ext3/super.c25
-rw-r--r--include/linux/ext3_fs_sb.h2
2 files changed, 17 insertions, 10 deletions
diff --git a/fs/ext3/super.c b/fs/ext3/super.c
index 8b75f73ba3b4..51d1c456cdab 100644
--- a/fs/ext3/super.c
+++ b/fs/ext3/super.c
@@ -2426,19 +2426,19 @@ static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf)
2426 struct super_block *sb = dentry->d_sb; 2426 struct super_block *sb = dentry->d_sb;
2427 struct ext3_sb_info *sbi = EXT3_SB(sb); 2427 struct ext3_sb_info *sbi = EXT3_SB(sb);
2428 struct ext3_super_block *es = sbi->s_es; 2428 struct ext3_super_block *es = sbi->s_es;
2429 ext3_fsblk_t overhead;
2430 int i;
2431 u64 fsid; 2429 u64 fsid;
2432 2430
2433 if (test_opt (sb, MINIX_DF)) 2431 if (test_opt(sb, MINIX_DF)) {
2434 overhead = 0; 2432 sbi->s_overhead_last = 0;
2435 else { 2433 } else if (sbi->s_blocks_last != le32_to_cpu(es->s_blocks_count)) {
2436 unsigned long ngroups; 2434 unsigned long ngroups = sbi->s_groups_count, i;
2437 ngroups = EXT3_SB(sb)->s_groups_count; 2435 ext3_fsblk_t overhead = 0;
2438 smp_rmb(); 2436 smp_rmb();
2439 2437
2440 /* 2438 /*
2441 * Compute the overhead (FS structures) 2439 * Compute the overhead (FS structures). This is constant
2440 * for a given filesystem unless the number of block groups
2441 * changes so we cache the previous value until it does.
2442 */ 2442 */
2443 2443
2444 /* 2444 /*
@@ -2462,18 +2462,23 @@ static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf)
2462 * Every block group has an inode bitmap, a block 2462 * Every block group has an inode bitmap, a block
2463 * bitmap, and an inode table. 2463 * bitmap, and an inode table.
2464 */ 2464 */
2465 overhead += (ngroups * (2 + EXT3_SB(sb)->s_itb_per_group)); 2465 overhead += ngroups * (2 + sbi->s_itb_per_group);
2466 sbi->s_overhead_last = overhead;
2467 smp_wmb();
2468 sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count);
2466 } 2469 }
2467 2470
2468 buf->f_type = EXT3_SUPER_MAGIC; 2471 buf->f_type = EXT3_SUPER_MAGIC;
2469 buf->f_bsize = sb->s_blocksize; 2472 buf->f_bsize = sb->s_blocksize;
2470 buf->f_blocks = le32_to_cpu(es->s_blocks_count) - overhead; 2473 buf->f_blocks = le32_to_cpu(es->s_blocks_count) - sbi->s_overhead_last;
2471 buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter); 2474 buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter);
2475 es->s_free_blocks_count = cpu_to_le32(buf->f_bfree);
2472 buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count); 2476 buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count);
2473 if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count)) 2477 if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count))
2474 buf->f_bavail = 0; 2478 buf->f_bavail = 0;
2475 buf->f_files = le32_to_cpu(es->s_inodes_count); 2479 buf->f_files = le32_to_cpu(es->s_inodes_count);
2476 buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter); 2480 buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter);
2481 es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
2477 buf->f_namelen = EXT3_NAME_LEN; 2482 buf->f_namelen = EXT3_NAME_LEN;
2478 fsid = le64_to_cpup((void *)es->s_uuid) ^ 2483 fsid = le64_to_cpup((void *)es->s_uuid) ^
2479 le64_to_cpup((void *)es->s_uuid + sizeof(u64)); 2484 le64_to_cpup((void *)es->s_uuid + sizeof(u64));
diff --git a/include/linux/ext3_fs_sb.h b/include/linux/ext3_fs_sb.h
index f61309c81cc4..d3c08353edf6 100644
--- a/include/linux/ext3_fs_sb.h
+++ b/include/linux/ext3_fs_sb.h
@@ -38,6 +38,8 @@ struct ext3_sb_info {
38 unsigned long s_gdb_count; /* Number of group descriptor blocks */ 38 unsigned long s_gdb_count; /* Number of group descriptor blocks */
39 unsigned long s_desc_per_block; /* Number of group descriptors per block */ 39 unsigned long s_desc_per_block; /* Number of group descriptors per block */
40 unsigned long s_groups_count; /* Number of groups in the fs */ 40 unsigned long s_groups_count; /* Number of groups in the fs */
41 unsigned long s_overhead_last; /* Last calculated overhead */
42 unsigned long s_blocks_last; /* Last seen block count */
41 struct buffer_head * s_sbh; /* Buffer containing the super block */ 43 struct buffer_head * s_sbh; /* Buffer containing the super block */
42 struct ext3_super_block * s_es; /* Pointer to the super block in the buffer */ 44 struct ext3_super_block * s_es; /* Pointer to the super block in the buffer */
43 struct buffer_head ** s_group_desc; 45 struct buffer_head ** s_group_desc;