From 96126e20ad81a7c4f8c9fc55bc5b42d0ae3d696b Mon Sep 17 00:00:00 2001 From: Jan Kara Date: Mon, 12 Jul 2010 21:04:31 +0200 Subject: [PATCH] --- yaml --- r: 206279 b: refs/heads/master c: f25f624263445785b94f39739a6339ba9ed3275d h: refs/heads/master i: 206277: ebdd86d16d8505992980f52009b4b7b241ea651c 206275: 81e5025d0cf4827e99af956924e8475e8af19c9b 206271: 875ffcd229a96ccdf9779498b2527546fba61373 v: v3 --- [refs] | 2 +- trunk/fs/ext3/inode.c | 46 +++++++++++++++++++++++-------------------- 2 files changed, 26 insertions(+), 22 deletions(-) diff --git a/[refs] b/[refs] index d07b47703322..9686a35f86b7 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 4c4d3901225518ed1a4c938ba15ba09842a00770 +refs/heads/master: f25f624263445785b94f39739a6339ba9ed3275d diff --git a/trunk/fs/ext3/inode.c b/trunk/fs/ext3/inode.c index a786db403efc..436e5bbccbc2 100644 --- a/trunk/fs/ext3/inode.c +++ b/trunk/fs/ext3/inode.c @@ -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. @@ -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) {