+Index: linux-2.6.16.46-0.14/fs/ext3/super.c
+===================================================================
+--- linux-2.6.16.46-0.14.orig/fs/ext3/super.c
++++ linux-2.6.16.46-0.14/fs/ext3/super.c
+@@ -2908,18 +2908,19 @@ restore_opts:
+ static int ext3_statfs (struct super_block * sb, struct kstatfs * buf)
+ {
+ struct ext3_super_block *es = EXT3_SB(sb)->s_es;
+- unsigned long overhead;
+- int i;
++ struct ext3_sb_info *sbi = EXT3_SB(sb);
+
+- if (test_opt (sb, MINIX_DF))
+- overhead = 0;
+- else {
+- unsigned long ngroups;
+- ngroups = EXT3_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;
++ unsigned long overhead = 0;
+ 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.
+ */
+
+ /*
+@@ -2941,18 +2942,23 @@ static int ext3_statfs (struct super_blo
+ * Every block group has an inode bitmap, a block
+ * bitmap, and an inode table.
+ */
+- overhead += (ngroups * (2 + EXT3_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 = EXT3_SUPER_MAGIC;
+ buf->f_bsize = sb->s_blocksize;
+- buf->f_blocks = le32_to_cpu(es->s_blocks_count) - overhead;
++ buf->f_blocks = le32_to_cpu(es->s_blocks_count) - sbi->s_overhead_last;
+ buf->f_bfree = ext3_count_free_blocks (sb);
++ es->s_free_blocks_count = cpu_to_le32(buf->f_bfree);
+ buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count);
+ if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count))
+ buf->f_bavail = 0;
+ buf->f_files = le32_to_cpu(es->s_inodes_count);
+ buf->f_ffree = ext3_count_free_inodes (sb);
++ es->s_free_inodes_count = cpu_to_le32(buf->f_ffree);
+ buf->f_namelen = EXT3_NAME_LEN;
+ return 0;
+ }
+Index: linux-2.6.16.46-0.14/include/linux/ext3_fs_sb.h
+===================================================================
+--- linux-2.6.16.46-0.14.orig/include/linux/ext3_fs_sb.h
++++ linux-2.6.16.46-0.14/include/linux/ext3_fs_sb.h
+@@ -45,6 +45,8 @@ struct ext3_sb_info {
+ unsigned long s_gdb_count; /* Number of group descriptor blocks */
+ unsigned long s_desc_per_block; /* Number of group descriptors per block */
+ unsigned long s_groups_count; /* Number of groups in the fs */
++ unsigned long s_overhead_last; /* Last calculated overhead */
++ unsigned long s_blocks_last; /* Last seen block count */
+ struct buffer_head * s_sbh; /* Buffer containing the super block */
+ struct ext3_super_block * s_es; /* Pointer to the super block in the buffer */
+ struct buffer_head ** s_group_desc;