aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-06-29 22:20:43 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-29 22:20:43 -0400
commit16874b2cb867d3eb63ed838f2847143e11556708 (patch)
tree3052bd2c5fe3a661ef42dea767d6a782d71c821b /fs
parent4c834452aad01531db949414f94f817a86348d59 (diff)
parenta93cd4cf86466caa49cfe64607bea7f0bde3f916 (diff)
Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull ext4 bugfixes from Ted Ts'o: "Fix a regression when trying to compile ext4 on older versions gcc. Fix a number of miscellaneous bugs for punch hole as well as a long-standing potential double buffer head release when failing a block allocation for an indirect-mapped file" * tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4: ext4: Fix hole punching for files with indirect blocks ext4: Fix block zeroing when punching holes in indirect block files ext4: decrement free clusters/inodes counters when block group declared bad fs/mbcache: replace __builtin_log2() with ilog2() ext4: Fix buffer double free in ext4_alloc_branch()
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/balloc.c16
-rw-r--r--fs/ext4/ialloc.c23
-rw-r--r--fs/ext4/indirect.c24
-rw-r--r--fs/ext4/mballoc.c8
-rw-r--r--fs/mbcache.c3
5 files changed, 68 insertions, 6 deletions
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c
index 0762d143e252..fca382037ddd 100644
--- a/fs/ext4/balloc.c
+++ b/fs/ext4/balloc.c
@@ -194,7 +194,16 @@ static void ext4_init_block_bitmap(struct super_block *sb,
194 if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) { 194 if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) {
195 ext4_error(sb, "Checksum bad for group %u", block_group); 195 ext4_error(sb, "Checksum bad for group %u", block_group);
196 grp = ext4_get_group_info(sb, block_group); 196 grp = ext4_get_group_info(sb, block_group);
197 if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
198 percpu_counter_sub(&sbi->s_freeclusters_counter,
199 grp->bb_free);
197 set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state); 200 set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state);
201 if (!EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) {
202 int count;
203 count = ext4_free_inodes_count(sb, gdp);
204 percpu_counter_sub(&sbi->s_freeinodes_counter,
205 count);
206 }
198 set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state); 207 set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state);
199 return; 208 return;
200 } 209 }
@@ -359,6 +368,7 @@ static void ext4_validate_block_bitmap(struct super_block *sb,
359{ 368{
360 ext4_fsblk_t blk; 369 ext4_fsblk_t blk;
361 struct ext4_group_info *grp = ext4_get_group_info(sb, block_group); 370 struct ext4_group_info *grp = ext4_get_group_info(sb, block_group);
371 struct ext4_sb_info *sbi = EXT4_SB(sb);
362 372
363 if (buffer_verified(bh)) 373 if (buffer_verified(bh))
364 return; 374 return;
@@ -369,6 +379,9 @@ static void ext4_validate_block_bitmap(struct super_block *sb,
369 ext4_unlock_group(sb, block_group); 379 ext4_unlock_group(sb, block_group);
370 ext4_error(sb, "bg %u: block %llu: invalid block bitmap", 380 ext4_error(sb, "bg %u: block %llu: invalid block bitmap",
371 block_group, blk); 381 block_group, blk);
382 if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
383 percpu_counter_sub(&sbi->s_freeclusters_counter,
384 grp->bb_free);
372 set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state); 385 set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state);
373 return; 386 return;
374 } 387 }
@@ -376,6 +389,9 @@ static void ext4_validate_block_bitmap(struct super_block *sb,
376 desc, bh))) { 389 desc, bh))) {
377 ext4_unlock_group(sb, block_group); 390 ext4_unlock_group(sb, block_group);
378 ext4_error(sb, "bg %u: bad block bitmap checksum", block_group); 391 ext4_error(sb, "bg %u: bad block bitmap checksum", block_group);
392 if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
393 percpu_counter_sub(&sbi->s_freeclusters_counter,
394 grp->bb_free);
379 set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state); 395 set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state);
380 return; 396 return;
381 } 397 }
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c
index 0ee59a6644e2..a87455df38bc 100644
--- a/fs/ext4/ialloc.c
+++ b/fs/ext4/ialloc.c
@@ -71,6 +71,7 @@ static unsigned ext4_init_inode_bitmap(struct super_block *sb,
71 struct ext4_group_desc *gdp) 71 struct ext4_group_desc *gdp)
72{ 72{
73 struct ext4_group_info *grp; 73 struct ext4_group_info *grp;
74 struct ext4_sb_info *sbi = EXT4_SB(sb);
74 J_ASSERT_BH(bh, buffer_locked(bh)); 75 J_ASSERT_BH(bh, buffer_locked(bh));
75 76
76 /* If checksum is bad mark all blocks and inodes use to prevent 77 /* If checksum is bad mark all blocks and inodes use to prevent
@@ -78,7 +79,16 @@ static unsigned ext4_init_inode_bitmap(struct super_block *sb,
78 if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) { 79 if (!ext4_group_desc_csum_verify(sb, block_group, gdp)) {
79 ext4_error(sb, "Checksum bad for group %u", block_group); 80 ext4_error(sb, "Checksum bad for group %u", block_group);
80 grp = ext4_get_group_info(sb, block_group); 81 grp = ext4_get_group_info(sb, block_group);
82 if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
83 percpu_counter_sub(&sbi->s_freeclusters_counter,
84 grp->bb_free);
81 set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state); 85 set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state);
86 if (!EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) {
87 int count;
88 count = ext4_free_inodes_count(sb, gdp);
89 percpu_counter_sub(&sbi->s_freeinodes_counter,
90 count);
91 }
82 set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state); 92 set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state);
83 return 0; 93 return 0;
84 } 94 }
@@ -116,6 +126,7 @@ ext4_read_inode_bitmap(struct super_block *sb, ext4_group_t block_group)
116 struct buffer_head *bh = NULL; 126 struct buffer_head *bh = NULL;
117 ext4_fsblk_t bitmap_blk; 127 ext4_fsblk_t bitmap_blk;
118 struct ext4_group_info *grp; 128 struct ext4_group_info *grp;
129 struct ext4_sb_info *sbi = EXT4_SB(sb);
119 130
120 desc = ext4_get_group_desc(sb, block_group, NULL); 131 desc = ext4_get_group_desc(sb, block_group, NULL);
121 if (!desc) 132 if (!desc)
@@ -185,6 +196,12 @@ verify:
185 ext4_error(sb, "Corrupt inode bitmap - block_group = %u, " 196 ext4_error(sb, "Corrupt inode bitmap - block_group = %u, "
186 "inode_bitmap = %llu", block_group, bitmap_blk); 197 "inode_bitmap = %llu", block_group, bitmap_blk);
187 grp = ext4_get_group_info(sb, block_group); 198 grp = ext4_get_group_info(sb, block_group);
199 if (!EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) {
200 int count;
201 count = ext4_free_inodes_count(sb, desc);
202 percpu_counter_sub(&sbi->s_freeinodes_counter,
203 count);
204 }
188 set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state); 205 set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state);
189 return NULL; 206 return NULL;
190 } 207 }
@@ -321,6 +338,12 @@ out:
321 fatal = err; 338 fatal = err;
322 } else { 339 } else {
323 ext4_error(sb, "bit already cleared for inode %lu", ino); 340 ext4_error(sb, "bit already cleared for inode %lu", ino);
341 if (!EXT4_MB_GRP_IBITMAP_CORRUPT(grp)) {
342 int count;
343 count = ext4_free_inodes_count(sb, gdp);
344 percpu_counter_sub(&sbi->s_freeinodes_counter,
345 count);
346 }
324 set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state); 347 set_bit(EXT4_GROUP_INFO_IBITMAP_CORRUPT_BIT, &grp->bb_state);
325 } 348 }
326 349
diff --git a/fs/ext4/indirect.c b/fs/ext4/indirect.c
index 8a57e9fcd1b9..fd69da194826 100644
--- a/fs/ext4/indirect.c
+++ b/fs/ext4/indirect.c
@@ -389,7 +389,13 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
389 return 0; 389 return 0;
390failed: 390failed:
391 for (; i >= 0; i--) { 391 for (; i >= 0; i--) {
392 if (i != indirect_blks && branch[i].bh) 392 /*
393 * We want to ext4_forget() only freshly allocated indirect
394 * blocks. Buffer for new_blocks[i-1] is at branch[i].bh and
395 * buffer at branch[0].bh is indirect block / inode already
396 * existing before ext4_alloc_branch() was called.
397 */
398 if (i > 0 && i != indirect_blks && branch[i].bh)
393 ext4_forget(handle, 1, inode, branch[i].bh, 399 ext4_forget(handle, 1, inode, branch[i].bh,
394 branch[i].bh->b_blocknr); 400 branch[i].bh->b_blocknr);
395 ext4_free_blocks(handle, inode, NULL, new_blocks[i], 401 ext4_free_blocks(handle, inode, NULL, new_blocks[i],
@@ -1310,16 +1316,24 @@ static int free_hole_blocks(handle_t *handle, struct inode *inode,
1310 blk = *i_data; 1316 blk = *i_data;
1311 if (level > 0) { 1317 if (level > 0) {
1312 ext4_lblk_t first2; 1318 ext4_lblk_t first2;
1319 ext4_lblk_t count2;
1320
1313 bh = sb_bread(inode->i_sb, le32_to_cpu(blk)); 1321 bh = sb_bread(inode->i_sb, le32_to_cpu(blk));
1314 if (!bh) { 1322 if (!bh) {
1315 EXT4_ERROR_INODE_BLOCK(inode, le32_to_cpu(blk), 1323 EXT4_ERROR_INODE_BLOCK(inode, le32_to_cpu(blk),
1316 "Read failure"); 1324 "Read failure");
1317 return -EIO; 1325 return -EIO;
1318 } 1326 }
1319 first2 = (first > offset) ? first - offset : 0; 1327 if (first > offset) {
1328 first2 = first - offset;
1329 count2 = count;
1330 } else {
1331 first2 = 0;
1332 count2 = count - (offset - first);
1333 }
1320 ret = free_hole_blocks(handle, inode, bh, 1334 ret = free_hole_blocks(handle, inode, bh,
1321 (__le32 *)bh->b_data, level - 1, 1335 (__le32 *)bh->b_data, level - 1,
1322 first2, count - offset, 1336 first2, count2,
1323 inode->i_sb->s_blocksize >> 2); 1337 inode->i_sb->s_blocksize >> 2);
1324 if (ret) { 1338 if (ret) {
1325 brelse(bh); 1339 brelse(bh);
@@ -1329,8 +1343,8 @@ static int free_hole_blocks(handle_t *handle, struct inode *inode,
1329 if (level == 0 || 1343 if (level == 0 ||
1330 (bh && all_zeroes((__le32 *)bh->b_data, 1344 (bh && all_zeroes((__le32 *)bh->b_data,
1331 (__le32 *)bh->b_data + addr_per_block))) { 1345 (__le32 *)bh->b_data + addr_per_block))) {
1332 ext4_free_data(handle, inode, parent_bh, &blk, &blk+1); 1346 ext4_free_data(handle, inode, parent_bh,
1333 *i_data = 0; 1347 i_data, i_data + 1);
1334 } 1348 }
1335 brelse(bh); 1349 brelse(bh);
1336 bh = NULL; 1350 bh = NULL;
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 59e31622cc6e..7f72f50a8fa7 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -722,6 +722,7 @@ void ext4_mb_generate_buddy(struct super_block *sb,
722 void *buddy, void *bitmap, ext4_group_t group) 722 void *buddy, void *bitmap, ext4_group_t group)
723{ 723{
724 struct ext4_group_info *grp = ext4_get_group_info(sb, group); 724 struct ext4_group_info *grp = ext4_get_group_info(sb, group);
725 struct ext4_sb_info *sbi = EXT4_SB(sb);
725 ext4_grpblk_t max = EXT4_CLUSTERS_PER_GROUP(sb); 726 ext4_grpblk_t max = EXT4_CLUSTERS_PER_GROUP(sb);
726 ext4_grpblk_t i = 0; 727 ext4_grpblk_t i = 0;
727 ext4_grpblk_t first; 728 ext4_grpblk_t first;
@@ -759,6 +760,9 @@ void ext4_mb_generate_buddy(struct super_block *sb,
759 * corrupt and update bb_free using bitmap value 760 * corrupt and update bb_free using bitmap value
760 */ 761 */
761 grp->bb_free = free; 762 grp->bb_free = free;
763 if (!EXT4_MB_GRP_BBITMAP_CORRUPT(grp))
764 percpu_counter_sub(&sbi->s_freeclusters_counter,
765 grp->bb_free);
762 set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state); 766 set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, &grp->bb_state);
763 } 767 }
764 mb_set_largest_free_order(sb, grp); 768 mb_set_largest_free_order(sb, grp);
@@ -1431,6 +1435,7 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
1431 right_is_free = !mb_test_bit(last + 1, e4b->bd_bitmap); 1435 right_is_free = !mb_test_bit(last + 1, e4b->bd_bitmap);
1432 1436
1433 if (unlikely(block != -1)) { 1437 if (unlikely(block != -1)) {
1438 struct ext4_sb_info *sbi = EXT4_SB(sb);
1434 ext4_fsblk_t blocknr; 1439 ext4_fsblk_t blocknr;
1435 1440
1436 blocknr = ext4_group_first_block_no(sb, e4b->bd_group); 1441 blocknr = ext4_group_first_block_no(sb, e4b->bd_group);
@@ -1441,6 +1446,9 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b,
1441 "freeing already freed block " 1446 "freeing already freed block "
1442 "(bit %u); block bitmap corrupt.", 1447 "(bit %u); block bitmap corrupt.",
1443 block); 1448 block);
1449 if (!EXT4_MB_GRP_BBITMAP_CORRUPT(e4b->bd_info))
1450 percpu_counter_sub(&sbi->s_freeclusters_counter,
1451 e4b->bd_info->bb_free);
1444 /* Mark the block group as corrupt. */ 1452 /* Mark the block group as corrupt. */
1445 set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT, 1453 set_bit(EXT4_GROUP_INFO_BBITMAP_CORRUPT_BIT,
1446 &e4b->bd_info->bb_state); 1454 &e4b->bd_info->bb_state);
diff --git a/fs/mbcache.c b/fs/mbcache.c
index bf166e388f0d..187477ded6b3 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -73,6 +73,7 @@
73#include <linux/mbcache.h> 73#include <linux/mbcache.h>
74#include <linux/init.h> 74#include <linux/init.h>
75#include <linux/blockgroup_lock.h> 75#include <linux/blockgroup_lock.h>
76#include <linux/log2.h>
76 77
77#ifdef MB_CACHE_DEBUG 78#ifdef MB_CACHE_DEBUG
78# define mb_debug(f...) do { \ 79# define mb_debug(f...) do { \
@@ -93,7 +94,7 @@
93 94
94#define MB_CACHE_WRITER ((unsigned short)~0U >> 1) 95#define MB_CACHE_WRITER ((unsigned short)~0U >> 1)
95 96
96#define MB_CACHE_ENTRY_LOCK_BITS __builtin_log2(NR_BG_LOCKS) 97#define MB_CACHE_ENTRY_LOCK_BITS ilog2(NR_BG_LOCKS)
97#define MB_CACHE_ENTRY_LOCK_INDEX(ce) \ 98#define MB_CACHE_ENTRY_LOCK_INDEX(ce) \
98 (hash_long((unsigned long)ce, MB_CACHE_ENTRY_LOCK_BITS)) 99 (hash_long((unsigned long)ce, MB_CACHE_ENTRY_LOCK_BITS))
99 100