aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2012-06-07 18:56:06 -0400
committerTheodore Ts'o <tytso@mit.edu>2012-06-07 18:56:06 -0400
commitb0dd6b70f0fda17ae9762fbb72d98e40a4f66556 (patch)
tree64b75161542ef9d74bb397b82e9cea5b60c9304b /fs
parentf8f5701bdaf9134b1f90e5044a82c66324d2073f (diff)
ext4: fix the free blocks calculation for ext3 file systems w/ uninit_bg
Ext3 filesystems that are converted to use as many ext4 file system features as possible will enable uninit_bg to speed up e2fsck times. These file systems will have a native ext3 layout of inode tables and block allocation bitmaps (as opposed to ext4's flex_bg layout). Unfortunately, in these cases, when first allocating a block in an uninitialized block group, ext4 would incorrectly calculate the number of free blocks in that block group, and then errorneously report that the file system was corrupt: EXT4-fs error (device vdd): ext4_mb_generate_buddy:741: group 30, 32254 clusters in bitmap, 32258 in gd This problem can be reproduced via: mke2fs -q -t ext4 -O ^flex_bg /dev/vdd 5g mount -t ext4 /dev/vdd /mnt fallocate -l 4600m /mnt/test The problem was caused by a bone headed mistake in the check to see if a particular metadata block was part of the block group. Many thanks to Kees Cook for finding and bisecting the buggy commit which introduced this bug (commit fd034a84e1, present since v3.2). Reported-by: Sander Eikelenboom <linux@eikelenboom.it> Reported-by: Kees Cook <keescook@chromium.org> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> Tested-by: Kees Cook <keescook@chromium.org> Cc: stable@kernel.org
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/balloc.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 99b6324290db..cee7812cc3cf 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -90,8 +90,8 @@ unsigned ext4_num_overhead_clusters(struct super_block *sb,
90 * unusual file system layouts. 90 * unusual file system layouts.
91 */ 91 */
92 if (ext4_block_in_group(sb, ext4_block_bitmap(sb, gdp), block_group)) { 92 if (ext4_block_in_group(sb, ext4_block_bitmap(sb, gdp), block_group)) {
93 block_cluster = EXT4_B2C(sbi, (start - 93 block_cluster = EXT4_B2C(sbi,
94 ext4_block_bitmap(sb, gdp))); 94 ext4_block_bitmap(sb, gdp) - start);
95 if (block_cluster < num_clusters) 95 if (block_cluster < num_clusters)
96 block_cluster = -1; 96 block_cluster = -1;
97 else if (block_cluster == num_clusters) { 97 else if (block_cluster == num_clusters) {
@@ -102,7 +102,7 @@ unsigned ext4_num_overhead_clusters(struct super_block *sb,
102 102
103 if (ext4_block_in_group(sb, ext4_inode_bitmap(sb, gdp), block_group)) { 103 if (ext4_block_in_group(sb, ext4_inode_bitmap(sb, gdp), block_group)) {
104 inode_cluster = EXT4_B2C(sbi, 104 inode_cluster = EXT4_B2C(sbi,
105 start - ext4_inode_bitmap(sb, gdp)); 105 ext4_inode_bitmap(sb, gdp) - start);
106 if (inode_cluster < num_clusters) 106 if (inode_cluster < num_clusters)
107 inode_cluster = -1; 107 inode_cluster = -1;
108 else if (inode_cluster == num_clusters) { 108 else if (inode_cluster == num_clusters) {
@@ -114,7 +114,7 @@ unsigned ext4_num_overhead_clusters(struct super_block *sb,
114 itbl_blk = ext4_inode_table(sb, gdp); 114 itbl_blk = ext4_inode_table(sb, gdp);
115 for (i = 0; i < sbi->s_itb_per_group; i++) { 115 for (i = 0; i < sbi->s_itb_per_group; i++) {
116 if (ext4_block_in_group(sb, itbl_blk + i, block_group)) { 116 if (ext4_block_in_group(sb, itbl_blk + i, block_group)) {
117 c = EXT4_B2C(sbi, start - itbl_blk + i); 117 c = EXT4_B2C(sbi, itbl_blk + i - start);
118 if ((c < num_clusters) || (c == inode_cluster) || 118 if ((c < num_clusters) || (c == inode_cluster) ||
119 (c == block_cluster) || (c == itbl_cluster)) 119 (c == block_cluster) || (c == itbl_cluster))
120 continue; 120 continue;