|
@@ -2500,19 +2500,19 @@ static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf)
|
|
struct super_block *sb = dentry->d_sb;
|
|
struct super_block *sb = dentry->d_sb;
|
|
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
|
struct ext4_sb_info *sbi = EXT4_SB(sb);
|
|
struct ext4_super_block *es = sbi->s_es;
|
|
struct ext4_super_block *es = sbi->s_es;
|
|
- ext4_fsblk_t overhead;
|
|
|
|
- int i;
|
|
|
|
u64 fsid;
|
|
u64 fsid;
|
|
|
|
|
|
- if (test_opt (sb, MINIX_DF))
|
|
|
|
- overhead = 0;
|
|
|
|
- else {
|
|
|
|
- unsigned long ngroups;
|
|
|
|
- ngroups = EXT4_SB(sb)->s_groups_count;
|
|
|
|
|
|
+ if (test_opt(sb, MINIX_DF)) {
|
|
|
|
+ sbi->s_overhead_last = 0;
|
|
|
|
+ } else if (sbi->s_blocks_last != le32_to_cpu(es->s_blocks_count)) {
|
|
|
|
+ unsigned long ngroups = sbi->s_groups_count, i;
|
|
|
|
+ ext4_fsblk_t overhead = 0;
|
|
smp_rmb();
|
|
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.
|
|
*/
|
|
*/
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -2536,18 +2536,23 @@ static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf)
|
|
* Every block group has an inode bitmap, a block
|
|
* Every block group has an inode bitmap, a block
|
|
* bitmap, and an inode table.
|
|
* bitmap, and an inode table.
|
|
*/
|
|
*/
|
|
- overhead += (ngroups * (2 + EXT4_SB(sb)->s_itb_per_group));
|
|
|
|
|
|
+ overhead += ngroups * (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 = EXT4_SUPER_MAGIC;
|
|
buf->f_type = EXT4_SUPER_MAGIC;
|
|
buf->f_bsize = sb->s_blocksize;
|
|
buf->f_bsize = sb->s_blocksize;
|
|
- buf->f_blocks = ext4_blocks_count(es) - overhead;
|
|
|
|
|
|
+ buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last;
|
|
buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter);
|
|
buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter);
|
|
|
|
+ es->s_free_blocks_count = cpu_to_le32(buf->f_bfree);
|
|
buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es);
|
|
buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es);
|
|
if (buf->f_bfree < ext4_r_blocks_count(es))
|
|
if (buf->f_bfree < ext4_r_blocks_count(es))
|
|
buf->f_bavail = 0;
|
|
buf->f_bavail = 0;
|
|
buf->f_files = le32_to_cpu(es->s_inodes_count);
|
|
buf->f_files = le32_to_cpu(es->s_inodes_count);
|
|
buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter);
|
|
buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter);
|
|
|
|
+ es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
|
|
buf->f_namelen = EXT4_NAME_LEN;
|
|
buf->f_namelen = EXT4_NAME_LEN;
|
|
fsid = le64_to_cpup((void *)es->s_uuid) ^
|
|
fsid = le64_to_cpup((void *)es->s_uuid) ^
|
|
le64_to_cpup((void *)es->s_uuid + sizeof(u64));
|
|
le64_to_cpup((void *)es->s_uuid + sizeof(u64));
|