diff options
author | Badari Pulavarty <pbadari@us.ibm.com> | 2007-07-16 02:41:59 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-16 12:05:52 -0400 |
commit | a71ce8c6c9bf269b192f352ea555217815cf027e (patch) | |
tree | 32d1c37b890120e0eb12c2f4fe821af5507aad91 /fs/ext3 | |
parent | 2235219b7721b8e74de6841e79240936561a2b63 (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>
Diffstat (limited to 'fs/ext3')
-rw-r--r-- | fs/ext3/super.c | 25 |
1 files changed, 15 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)); |