diff options
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r-- | fs/ext4/inode.c | 35 |
1 files changed, 13 insertions, 22 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 755ba8682233..699d1d01c5df 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c | |||
@@ -4490,27 +4490,6 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode, | |||
4490 | depth); | 4490 | depth); |
4491 | 4491 | ||
4492 | /* | 4492 | /* |
4493 | * We've probably journalled the indirect block several | ||
4494 | * times during the truncate. But it's no longer | ||
4495 | * needed and we now drop it from the transaction via | ||
4496 | * jbd2_journal_revoke(). | ||
4497 | * | ||
4498 | * That's easy if it's exclusively part of this | ||
4499 | * transaction. But if it's part of the committing | ||
4500 | * transaction then jbd2_journal_forget() will simply | ||
4501 | * brelse() it. That means that if the underlying | ||
4502 | * block is reallocated in ext4_get_block(), | ||
4503 | * unmap_underlying_metadata() will find this block | ||
4504 | * and will try to get rid of it. damn, damn. | ||
4505 | * | ||
4506 | * If this block has already been committed to the | ||
4507 | * journal, a revoke record will be written. And | ||
4508 | * revoke records must be emitted *before* clearing | ||
4509 | * this block's bit in the bitmaps. | ||
4510 | */ | ||
4511 | ext4_forget(handle, 1, inode, bh, bh->b_blocknr); | ||
4512 | |||
4513 | /* | ||
4514 | * Everything below this this pointer has been | 4493 | * Everything below this this pointer has been |
4515 | * released. Now let this top-of-subtree go. | 4494 | * released. Now let this top-of-subtree go. |
4516 | * | 4495 | * |
@@ -4534,8 +4513,20 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode, | |||
4534 | blocks_for_truncate(inode)); | 4513 | blocks_for_truncate(inode)); |
4535 | } | 4514 | } |
4536 | 4515 | ||
4516 | /* | ||
4517 | * The forget flag here is critical because if | ||
4518 | * we are journaling (and not doing data | ||
4519 | * journaling), we have to make sure a revoke | ||
4520 | * record is written to prevent the journal | ||
4521 | * replay from overwriting the (former) | ||
4522 | * indirect block if it gets reallocated as a | ||
4523 | * data block. This must happen in the same | ||
4524 | * transaction where the data blocks are | ||
4525 | * actually freed. | ||
4526 | */ | ||
4537 | ext4_free_blocks(handle, inode, 0, nr, 1, | 4527 | ext4_free_blocks(handle, inode, 0, nr, 1, |
4538 | EXT4_FREE_BLOCKS_METADATA); | 4528 | EXT4_FREE_BLOCKS_METADATA| |
4529 | EXT4_FREE_BLOCKS_FORGET); | ||
4539 | 4530 | ||
4540 | if (parent_bh) { | 4531 | if (parent_bh) { |
4541 | /* | 4532 | /* |