Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 206279
b: refs/heads/master
c: f25f624
h: refs/heads/master
i:
  206277: ebdd86d
  206275: 81e5025
  206271: 875ffcd
v: v3
  • Loading branch information
Jan Kara committed Jul 21, 2010
1 parent bc7d046 commit 96126e2
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 22 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 4c4d3901225518ed1a4c938ba15ba09842a00770
refs/heads/master: f25f624263445785b94f39739a6339ba9ed3275d
46 changes: 25 additions & 21 deletions trunk/fs/ext3/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -2269,27 +2269,6 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode,
(__le32*)bh->b_data + addr_per_block,
depth);

/*
* We've probably journalled the indirect block several
* times during the truncate. But it's no longer
* needed and we now drop it from the transaction via
* journal_revoke().
*
* That's easy if it's exclusively part of this
* transaction. But if it's part of the committing
* transaction then journal_forget() will simply
* brelse() it. That means that if the underlying
* block is reallocated in ext3_get_block(),
* unmap_underlying_metadata() will find this block
* and will try to get rid of it. damn, damn.
*
* If this block has already been committed to the
* journal, a revoke record will be written. And
* revoke records must be emitted *before* clearing
* this block's bit in the bitmaps.
*/
ext3_forget(handle, 1, inode, bh, bh->b_blocknr);

/*
* Everything below this this pointer has been
* released. Now let this top-of-subtree go.
Expand All @@ -2313,6 +2292,31 @@ static void ext3_free_branches(handle_t *handle, struct inode *inode,
truncate_restart_transaction(handle, inode);
}

/*
* We've probably journalled the indirect block several
* times during the truncate. But it's no longer
* needed and we now drop it from the transaction via
* journal_revoke().
*
* That's easy if it's exclusively part of this
* transaction. But if it's part of the committing
* transaction then journal_forget() will simply
* brelse() it. That means that if the underlying
* block is reallocated in ext3_get_block(),
* unmap_underlying_metadata() will find this block
* and will try to get rid of it. damn, damn. Thus
* we don't allow a block to be reallocated until
* a transaction freeing it has fully committed.
*
* We also have to make sure journal replay after a
* crash does not overwrite non-journaled data blocks
* with old metadata when the block got reallocated for
* data. Thus we have to store a revoke record for a
* block in the same transaction in which we free the
* block.
*/
ext3_forget(handle, 1, inode, bh, bh->b_blocknr);

ext3_free_blocks(handle, inode, nr, 1);

if (parent_bh) {
Expand Down

0 comments on commit 96126e2

Please sign in to comment.