aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2012-07-09 16:27:05 -0400
committerTheodore Ts'o <tytso@mit.edu>2012-07-09 16:27:05 -0400
commit952fc18ef9ec707ebdc16c0786ec360295e5ff15 (patch)
treebd93a2c400c4a50b17b677c3b46d92c71651b2aa /fs/ext4
parentf6fb99cadcd44660c68e13f6eab28333653621e6 (diff)
ext4: fix overhead calculation used by ext4_statfs()
Commit f975d6bcc7a introduced bug which caused ext4_statfs() to miscalculate the number of file system overhead blocks. This causes the f_blocks field in the statfs structure to be larger than it should be. This would in turn cause the "df" output to show the number of data blocks in the file system and the number of data blocks used to be larger than they should be. Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> Cc: stable@kernel.org
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/bitmap.c4
-rw-r--r--fs/ext4/ext4.h4
-rw-r--r--fs/ext4/resize.c7
-rw-r--r--fs/ext4/super.c174
4 files changed, 132 insertions, 57 deletions
diff --git a/fs/ext4/bitmap.c b/fs/ext4/bitmap.c
index 7e86a6d28c64..a94b9c63ee5c 100644
--- a/fs/ext4/bitmap.c
+++ b/fs/ext4/bitmap.c
@@ -11,8 +11,6 @@
11#include <linux/jbd2.h> 11#include <linux/jbd2.h>
12#include "ext4.h" 12#include "ext4.h"
13 13
14#ifdef EXT4FS_DEBUG
15
16static const int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0}; 14static const int nibblemap[] = {4, 3, 3, 2, 3, 2, 2, 1, 3, 2, 2, 1, 2, 1, 1, 0};
17 15
18unsigned int ext4_count_free(char *bitmap, unsigned int numchars) 16unsigned int ext4_count_free(char *bitmap, unsigned int numchars)
@@ -25,8 +23,6 @@ unsigned int ext4_count_free(char *bitmap, unsigned int numchars)
25 return sum; 23 return sum;
26} 24}
27 25
28#endif /* EXT4FS_DEBUG */
29
30int ext4_inode_bitmap_csum_verify(struct super_block *sb, ext4_group_t group, 26int ext4_inode_bitmap_csum_verify(struct super_block *sb, ext4_group_t group,
31 struct ext4_group_desc *gdp, 27 struct ext4_group_desc *gdp,
32 struct buffer_head *bh, int sz) 28 struct buffer_head *bh, int sz)
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 293fa1ced21b..01434f25917d 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1161,8 +1161,7 @@ struct ext4_sb_info {
1161 unsigned long s_desc_per_block; /* Number of group descriptors per block */ 1161 unsigned long s_desc_per_block; /* Number of group descriptors per block */
1162 ext4_group_t s_groups_count; /* Number of groups in the fs */ 1162 ext4_group_t s_groups_count; /* Number of groups in the fs */
1163 ext4_group_t s_blockfile_groups;/* Groups acceptable for non-extent files */ 1163 ext4_group_t s_blockfile_groups;/* Groups acceptable for non-extent files */
1164 unsigned long s_overhead_last; /* Last calculated overhead */ 1164 unsigned long s_overhead; /* # of fs overhead clusters */
1165 unsigned long s_blocks_last; /* Last seen block count */
1166 unsigned int s_cluster_ratio; /* Number of blocks per cluster */ 1165 unsigned int s_cluster_ratio; /* Number of blocks per cluster */
1167 unsigned int s_cluster_bits; /* log2 of s_cluster_ratio */ 1166 unsigned int s_cluster_bits; /* log2 of s_cluster_ratio */
1168 loff_t s_bitmap_maxbytes; /* max bytes for bitmap files */ 1167 loff_t s_bitmap_maxbytes; /* max bytes for bitmap files */
@@ -2037,6 +2036,7 @@ extern int ext4_group_extend(struct super_block *sb,
2037extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count); 2036extern int ext4_resize_fs(struct super_block *sb, ext4_fsblk_t n_blocks_count);
2038 2037
2039/* super.c */ 2038/* super.c */
2039extern int ext4_calculate_overhead(struct super_block *sb);
2040extern int ext4_superblock_csum_verify(struct super_block *sb, 2040extern int ext4_superblock_csum_verify(struct super_block *sb,
2041 struct ext4_super_block *es); 2041 struct ext4_super_block *es);
2042extern void ext4_superblock_csum_set(struct super_block *sb, 2042extern void ext4_superblock_csum_set(struct super_block *sb,
diff --git a/fs/ext4/resize.c b/fs/ext4/resize.c
index 7ea6cbb44121..17d38de4068c 100644
--- a/fs/ext4/resize.c
+++ b/fs/ext4/resize.c
@@ -1197,7 +1197,7 @@ static void ext4_update_super(struct super_block *sb,
1197 struct ext4_new_group_data *group_data = flex_gd->groups; 1197 struct ext4_new_group_data *group_data = flex_gd->groups;
1198 struct ext4_sb_info *sbi = EXT4_SB(sb); 1198 struct ext4_sb_info *sbi = EXT4_SB(sb);
1199 struct ext4_super_block *es = sbi->s_es; 1199 struct ext4_super_block *es = sbi->s_es;
1200 int i; 1200 int i, ret;
1201 1201
1202 BUG_ON(flex_gd->count == 0 || group_data == NULL); 1202 BUG_ON(flex_gd->count == 0 || group_data == NULL);
1203 /* 1203 /*
@@ -1272,6 +1272,11 @@ static void ext4_update_super(struct super_block *sb,
1272 &sbi->s_flex_groups[flex_group].free_inodes); 1272 &sbi->s_flex_groups[flex_group].free_inodes);
1273 } 1273 }
1274 1274
1275 /*
1276 * Update the fs overhead information
1277 */
1278 ext4_calculate_overhead(sb);
1279
1275 if (test_opt(sb, DEBUG)) 1280 if (test_opt(sb, DEBUG))
1276 printk(KERN_DEBUG "EXT4-fs: added group %u:" 1281 printk(KERN_DEBUG "EXT4-fs: added group %u:"
1277 "%llu blocks(%llu free %llu reserved)\n", flex_gd->count, 1282 "%llu blocks(%llu free %llu reserved)\n", flex_gd->count,
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index eb7aa3e4ef05..78b7ede2efa0 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -3085,6 +3085,114 @@ static int set_journal_csum_feature_set(struct super_block *sb)
3085 return ret; 3085 return ret;
3086} 3086}
3087 3087
3088/*
3089 * Note: calculating the overhead so we can be compatible with
3090 * historical BSD practice is quite difficult in the face of
3091 * clusters/bigalloc. This is because multiple metadata blocks from
3092 * different block group can end up in the same allocation cluster.
3093 * Calculating the exact overhead in the face of clustered allocation
3094 * requires either O(all block bitmaps) in memory or O(number of block
3095 * groups**2) in time. We will still calculate the superblock for
3096 * older file systems --- and if we come across with a bigalloc file
3097 * system with zero in s_overhead_clusters the estimate will be close to
3098 * correct especially for very large cluster sizes --- but for newer
3099 * file systems, it's better to calculate this figure once at mkfs
3100 * time, and store it in the superblock. If the superblock value is
3101 * present (even for non-bigalloc file systems), we will use it.
3102 */
3103static int count_overhead(struct super_block *sb, ext4_group_t grp,
3104 char *buf)
3105{
3106 struct ext4_sb_info *sbi = EXT4_SB(sb);
3107 struct ext4_group_desc *gdp;
3108 ext4_fsblk_t first_block, last_block, b;
3109 ext4_group_t i, ngroups = ext4_get_groups_count(sb);
3110 int s, j, count = 0;
3111
3112 first_block = le32_to_cpu(sbi->s_es->s_first_data_block) +
3113 (grp * EXT4_BLOCKS_PER_GROUP(sb));
3114 last_block = first_block + EXT4_BLOCKS_PER_GROUP(sb) - 1;
3115 for (i = 0; i < ngroups; i++) {
3116 gdp = ext4_get_group_desc(sb, i, NULL);
3117 b = ext4_block_bitmap(sb, gdp);
3118 if (b >= first_block && b <= last_block) {
3119 ext4_set_bit(EXT4_B2C(sbi, b - first_block), buf);
3120 count++;
3121 }
3122 b = ext4_inode_bitmap(sb, gdp);
3123 if (b >= first_block && b <= last_block) {
3124 ext4_set_bit(EXT4_B2C(sbi, b - first_block), buf);
3125 count++;
3126 }
3127 b = ext4_inode_table(sb, gdp);
3128 if (b >= first_block && b + sbi->s_itb_per_group <= last_block)
3129 for (j = 0; j < sbi->s_itb_per_group; j++, b++) {
3130 int c = EXT4_B2C(sbi, b - first_block);
3131 ext4_set_bit(c, buf);
3132 count++;
3133 }
3134 if (i != grp)
3135 continue;
3136 s = 0;
3137 if (ext4_bg_has_super(sb, grp)) {
3138 ext4_set_bit(s++, buf);
3139 count++;
3140 }
3141 for (j = ext4_bg_num_gdb(sb, grp); j > 0; j--) {
3142 ext4_set_bit(EXT4_B2C(sbi, s++), buf);
3143 count++;
3144 }
3145 }
3146 if (!count)
3147 return 0;
3148 return EXT4_CLUSTERS_PER_GROUP(sb) -
3149 ext4_count_free(buf, EXT4_CLUSTERS_PER_GROUP(sb) / 8);
3150}
3151
3152/*
3153 * Compute the overhead and stash it in sbi->s_overhead
3154 */
3155int ext4_calculate_overhead(struct super_block *sb)
3156{
3157 struct ext4_sb_info *sbi = EXT4_SB(sb);
3158 struct ext4_super_block *es = sbi->s_es;
3159 ext4_group_t i, ngroups = ext4_get_groups_count(sb);
3160 ext4_fsblk_t overhead = 0;
3161 char *buf = (char *) get_zeroed_page(GFP_KERNEL);
3162
3163 memset(buf, 0, PAGE_SIZE);
3164 if (!buf)
3165 return -ENOMEM;
3166
3167 /*
3168 * Compute the overhead (FS structures). This is constant
3169 * for a given filesystem unless the number of block groups
3170 * changes so we cache the previous value until it does.
3171 */
3172
3173 /*
3174 * All of the blocks before first_data_block are overhead
3175 */
3176 overhead = EXT4_B2C(sbi, le32_to_cpu(es->s_first_data_block));
3177
3178 /*
3179 * Add the overhead found in each block group
3180 */
3181 for (i = 0; i < ngroups; i++) {
3182 int blks;
3183
3184 blks = count_overhead(sb, i, buf);
3185 overhead += blks;
3186 if (blks)
3187 memset(buf, 0, PAGE_SIZE);
3188 cond_resched();
3189 }
3190 sbi->s_overhead = overhead;
3191 smp_wmb();
3192 free_page((unsigned long) buf);
3193 return 0;
3194}
3195
3088static int ext4_fill_super(struct super_block *sb, void *data, int silent) 3196static int ext4_fill_super(struct super_block *sb, void *data, int silent)
3089{ 3197{
3090 char *orig_data = kstrdup(data, GFP_KERNEL); 3198 char *orig_data = kstrdup(data, GFP_KERNEL);
@@ -3735,6 +3843,18 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent)
3735 3843
3736no_journal: 3844no_journal:
3737 /* 3845 /*
3846 * Get the # of file system overhead blocks from the
3847 * superblock if present.
3848 */
3849 if (es->s_overhead_clusters)
3850 sbi->s_overhead = le32_to_cpu(es->s_overhead_clusters);
3851 else {
3852 ret = ext4_calculate_overhead(sb);
3853 if (ret)
3854 goto failed_mount_wq;
3855 }
3856
3857 /*
3738 * The maximum number of concurrent works can be high and 3858 * The maximum number of concurrent works can be high and
3739 * concurrency isn't really necessary. Limit it to 1. 3859 * concurrency isn't really necessary. Limit it to 1.
3740 */ 3860 */
@@ -4600,67 +4720,21 @@ restore_opts:
4600 return err; 4720 return err;
4601} 4721}
4602 4722
4603/*
4604 * Note: calculating the overhead so we can be compatible with
4605 * historical BSD practice is quite difficult in the face of
4606 * clusters/bigalloc. This is because multiple metadata blocks from
4607 * different block group can end up in the same allocation cluster.
4608 * Calculating the exact overhead in the face of clustered allocation
4609 * requires either O(all block bitmaps) in memory or O(number of block
4610 * groups**2) in time. We will still calculate the superblock for
4611 * older file systems --- and if we come across with a bigalloc file
4612 * system with zero in s_overhead_clusters the estimate will be close to
4613 * correct especially for very large cluster sizes --- but for newer
4614 * file systems, it's better to calculate this figure once at mkfs
4615 * time, and store it in the superblock. If the superblock value is
4616 * present (even for non-bigalloc file systems), we will use it.
4617 */
4618static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf) 4723static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf)
4619{ 4724{
4620 struct super_block *sb = dentry->d_sb; 4725 struct super_block *sb = dentry->d_sb;
4621 struct ext4_sb_info *sbi = EXT4_SB(sb); 4726 struct ext4_sb_info *sbi = EXT4_SB(sb);
4622 struct ext4_super_block *es = sbi->s_es; 4727 struct ext4_super_block *es = sbi->s_es;
4623 struct ext4_group_desc *gdp; 4728 ext4_fsblk_t overhead = 0;
4624 u64 fsid; 4729 u64 fsid;
4625 s64 bfree; 4730 s64 bfree;
4626 4731
4627 if (test_opt(sb, MINIX_DF)) { 4732 if (!test_opt(sb, MINIX_DF))
4628 sbi->s_overhead_last = 0; 4733 overhead = sbi->s_overhead;
4629 } else if (es->s_overhead_clusters) {
4630 sbi->s_overhead_last = le32_to_cpu(es->s_overhead_clusters);
4631 } else if (sbi->s_blocks_last != ext4_blocks_count(es)) {
4632 ext4_group_t i, ngroups = ext4_get_groups_count(sb);
4633 ext4_fsblk_t overhead = 0;
4634
4635 /*
4636 * Compute the overhead (FS structures). This is constant
4637 * for a given filesystem unless the number of block groups
4638 * changes so we cache the previous value until it does.
4639 */
4640
4641 /*
4642 * All of the blocks before first_data_block are
4643 * overhead
4644 */
4645 overhead = EXT4_B2C(sbi, le32_to_cpu(es->s_first_data_block));
4646
4647 /*
4648 * Add the overhead found in each block group
4649 */
4650 for (i = 0; i < ngroups; i++) {
4651 gdp = ext4_get_group_desc(sb, i, NULL);
4652 overhead += ext4_num_overhead_clusters(sb, i, gdp);
4653 cond_resched();
4654 }
4655 sbi->s_overhead_last = overhead;
4656 smp_wmb();
4657 sbi->s_blocks_last = ext4_blocks_count(es);
4658 }
4659 4734
4660 buf->f_type = EXT4_SUPER_MAGIC; 4735 buf->f_type = EXT4_SUPER_MAGIC;
4661 buf->f_bsize = sb->s_blocksize; 4736 buf->f_bsize = sb->s_blocksize;
4662 buf->f_blocks = (ext4_blocks_count(es) - 4737 buf->f_blocks = ext4_blocks_count(es) - EXT4_C2B(sbi, sbi->s_overhead);
4663 EXT4_C2B(sbi, sbi->s_overhead_last));
4664 bfree = percpu_counter_sum_positive(&sbi->s_freeclusters_counter) - 4738 bfree = percpu_counter_sum_positive(&sbi->s_freeclusters_counter) -
4665 percpu_counter_sum_positive(&sbi->s_dirtyclusters_counter); 4739 percpu_counter_sum_positive(&sbi->s_dirtyclusters_counter);
4666 /* prevent underflow in case that few free space is available */ 4740 /* prevent underflow in case that few free space is available */