diff options
author | Theodore Ts'o <tytso@mit.edu> | 2011-09-09 19:00:51 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2011-09-09 19:00:51 -0400 |
commit | f975d6bcc7a698a10cc755115e27d3612dcfe322 (patch) | |
tree | 859f688a1962209ef535ca79cf31433c7bc57135 /fs/ext4/super.c | |
parent | 24aaa8ef4e2b5764ada1fc69787e2fbd4f6276e5 (diff) |
ext4: teach ext4_statfs() to deal with clusters if bigalloc is enabled
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4/super.c')
-rw-r--r-- | fs/ext4/super.c | 37 |
1 files changed, 24 insertions, 13 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index d7e0e045b11b..6810957e0ac7 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -4580,16 +4580,34 @@ restore_opts: | |||
4580 | return err; | 4580 | return err; |
4581 | } | 4581 | } |
4582 | 4582 | ||
4583 | /* | ||
4584 | * Note: calculating the overhead so we can be compatible with | ||
4585 | * historical BSD practice is quite difficult in the face of | ||
4586 | * clusters/bigalloc. This is because multiple metadata blocks from | ||
4587 | * different block group can end up in the same allocation cluster. | ||
4588 | * Calculating the exact overhead in the face of clustered allocation | ||
4589 | * requires either O(all block bitmaps) in memory or O(number of block | ||
4590 | * groups**2) in time. We will still calculate the superblock for | ||
4591 | * older file systems --- and if we come across with a bigalloc file | ||
4592 | * system with zero in s_overhead_clusters the estimate will be close to | ||
4593 | * correct especially for very large cluster sizes --- but for newer | ||
4594 | * file systems, it's better to calculate this figure once at mkfs | ||
4595 | * time, and store it in the superblock. If the superblock value is | ||
4596 | * present (even for non-bigalloc file systems), we will use it. | ||
4597 | */ | ||
4583 | static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) | 4598 | static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) |
4584 | { | 4599 | { |
4585 | struct super_block *sb = dentry->d_sb; | 4600 | struct super_block *sb = dentry->d_sb; |
4586 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 4601 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
4587 | struct ext4_super_block *es = sbi->s_es; | 4602 | struct ext4_super_block *es = sbi->s_es; |
4603 | struct ext4_group_desc *gdp; | ||
4588 | u64 fsid; | 4604 | u64 fsid; |
4589 | s64 bfree; | 4605 | s64 bfree; |
4590 | 4606 | ||
4591 | if (test_opt(sb, MINIX_DF)) { | 4607 | if (test_opt(sb, MINIX_DF)) { |
4592 | sbi->s_overhead_last = 0; | 4608 | sbi->s_overhead_last = 0; |
4609 | } else if (es->s_overhead_clusters) { | ||
4610 | sbi->s_overhead_last = le32_to_cpu(es->s_overhead_clusters); | ||
4593 | } else if (sbi->s_blocks_last != ext4_blocks_count(es)) { | 4611 | } else if (sbi->s_blocks_last != ext4_blocks_count(es)) { |
4594 | ext4_group_t i, ngroups = ext4_get_groups_count(sb); | 4612 | ext4_group_t i, ngroups = ext4_get_groups_count(sb); |
4595 | ext4_fsblk_t overhead = 0; | 4613 | ext4_fsblk_t overhead = 0; |
@@ -4604,24 +4622,16 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
4604 | * All of the blocks before first_data_block are | 4622 | * All of the blocks before first_data_block are |
4605 | * overhead | 4623 | * overhead |
4606 | */ | 4624 | */ |
4607 | overhead = le32_to_cpu(es->s_first_data_block); | 4625 | overhead = EXT4_B2C(sbi, le32_to_cpu(es->s_first_data_block)); |
4608 | 4626 | ||
4609 | /* | 4627 | /* |
4610 | * Add the overhead attributed to the superblock and | 4628 | * Add the overhead found in each block group |
4611 | * block group descriptors. If the sparse superblocks | ||
4612 | * feature is turned on, then not all groups have this. | ||
4613 | */ | 4629 | */ |
4614 | for (i = 0; i < ngroups; i++) { | 4630 | for (i = 0; i < ngroups; i++) { |
4615 | overhead += ext4_bg_has_super(sb, i) + | 4631 | gdp = ext4_get_group_desc(sb, i, NULL); |
4616 | ext4_bg_num_gdb(sb, i); | 4632 | overhead += ext4_num_overhead_clusters(sb, i, gdp); |
4617 | cond_resched(); | 4633 | cond_resched(); |
4618 | } | 4634 | } |
4619 | |||
4620 | /* | ||
4621 | * Every block group has an inode bitmap, a block | ||
4622 | * bitmap, and an inode table. | ||
4623 | */ | ||
4624 | overhead += ngroups * (2 + sbi->s_itb_per_group); | ||
4625 | sbi->s_overhead_last = overhead; | 4635 | sbi->s_overhead_last = overhead; |
4626 | smp_wmb(); | 4636 | smp_wmb(); |
4627 | sbi->s_blocks_last = ext4_blocks_count(es); | 4637 | sbi->s_blocks_last = ext4_blocks_count(es); |
@@ -4629,7 +4639,8 @@ static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
4629 | 4639 | ||
4630 | buf->f_type = EXT4_SUPER_MAGIC; | 4640 | buf->f_type = EXT4_SUPER_MAGIC; |
4631 | buf->f_bsize = sb->s_blocksize; | 4641 | buf->f_bsize = sb->s_blocksize; |
4632 | buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last; | 4642 | buf->f_blocks = (ext4_blocks_count(es) - |
4643 | EXT4_C2B(sbi, sbi->s_overhead_last)); | ||
4633 | bfree = percpu_counter_sum_positive(&sbi->s_freeclusters_counter) - | 4644 | bfree = percpu_counter_sum_positive(&sbi->s_freeclusters_counter) - |
4634 | percpu_counter_sum_positive(&sbi->s_dirtyclusters_counter); | 4645 | percpu_counter_sum_positive(&sbi->s_dirtyclusters_counter); |
4635 | /* prevent underflow in case that few free space is available */ | 4646 | /* prevent underflow in case that few free space is available */ |