aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4/inode.c
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2009-11-23 07:17:05 -0500
committerTheodore Ts'o <tytso@mit.edu>2009-11-23 07:17:05 -0500
commite6362609b6c71c5b802026be9cf263bbdd67a50e (patch)
treebe908b6b0566f70d31378bf11b548a0d59ae0218 /fs/ext4/inode.c
parent4433871130f36585fde38e7dd817433296648945 (diff)
ext4: call ext4_forget() from ext4_free_blocks()
Add the facility for ext4_forget() to be called from ext4_free_blocks(). This simplifies the code in a large number of places, and centralizes most of the work of calling ext4_forget() into a single place. Also fix a bug in the extents migration code; it wasn't calling ext4_forget() when releasing the indirect blocks during the conversion. As a result, if the system cashed during or shortly after the extents migration, and the released indirect blocks get reused as data blocks, the journal replay would corrupt the data blocks. With this new patch, fixing this bug was as simple as adding the EXT4_FREE_BLOCKS_FORGET flags to the call to ext4_free_blocks(). Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> Cc: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
Diffstat (limited to 'fs/ext4/inode.c')
-rw-r--r--fs/ext4/inode.c67
1 files changed, 26 insertions, 41 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 72c694323492..3b28e1fbfc90 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -669,7 +669,7 @@ allocated:
669 return ret; 669 return ret;
670failed_out: 670failed_out:
671 for (i = 0; i < index; i++) 671 for (i = 0; i < index; i++)
672 ext4_free_blocks(handle, inode, new_blocks[i], 1, 0); 672 ext4_free_blocks(handle, inode, 0, new_blocks[i], 1, 0);
673 return ret; 673 return ret;
674} 674}
675 675
@@ -765,20 +765,20 @@ static int ext4_alloc_branch(handle_t *handle, struct inode *inode,
765 return err; 765 return err;
766failed: 766failed:
767 /* Allocation failed, free what we already allocated */ 767 /* Allocation failed, free what we already allocated */
768 ext4_free_blocks(handle, inode, 0, new_blocks[0], 1, 0);
768 for (i = 1; i <= n ; i++) { 769 for (i = 1; i <= n ; i++) {
769 BUFFER_TRACE(branch[i].bh, "call jbd2_journal_forget");
770 /* 770 /*
771 * Note: is_metadata is 0 because branch[i].bh is 771 * branch[i].bh is newly allocated, so there is no
772 * newly allocated, so there is no need to revoke the 772 * need to revoke the block, which is why we don't
773 * block. If we do, it's harmless, but not necessary. 773 * need to set EXT4_FREE_BLOCKS_METADATA.
774 */ 774 */
775 ext4_forget(handle, 0, inode, branch[i].bh, 775 ext4_free_blocks(handle, inode, 0, new_blocks[i], 1,
776 branch[i].bh->b_blocknr); 776 EXT4_FREE_BLOCKS_FORGET);
777 } 777 }
778 for (i = 0; i < indirect_blks; i++) 778 for (i = n+1; i < indirect_blks; i++)
779 ext4_free_blocks(handle, inode, new_blocks[i], 1, 0); 779 ext4_free_blocks(handle, inode, 0, new_blocks[i], 1, 0);
780 780
781 ext4_free_blocks(handle, inode, new_blocks[i], num, 0); 781 ext4_free_blocks(handle, inode, 0, new_blocks[i], num, 0);
782 782
783 return err; 783 return err;
784} 784}
@@ -857,18 +857,16 @@ static int ext4_splice_branch(handle_t *handle, struct inode *inode,
857 857
858err_out: 858err_out:
859 for (i = 1; i <= num; i++) { 859 for (i = 1; i <= num; i++) {
860 BUFFER_TRACE(where[i].bh, "call jbd2_journal_forget");
861 /* 860 /*
862 * Note: is_metadata is 0 because branch[i].bh is 861 * branch[i].bh is newly allocated, so there is no
863 * newly allocated, so there is no need to revoke the 862 * need to revoke the block, which is why we don't
864 * block. If we do, it's harmless, but not necessary. 863 * need to set EXT4_FREE_BLOCKS_METADATA.
865 */ 864 */
866 ext4_forget(handle, 0, inode, where[i].bh, 865 ext4_free_blocks(handle, inode, where[i].bh, 0, 1,
867 where[i].bh->b_blocknr); 866 EXT4_FREE_BLOCKS_FORGET);
868 ext4_free_blocks(handle, inode,
869 le32_to_cpu(where[i-1].key), 1, 0);
870 } 867 }
871 ext4_free_blocks(handle, inode, le32_to_cpu(where[num].key), blks, 0); 868 ext4_free_blocks(handle, inode, 0, le32_to_cpu(where[num].key),
869 blks, 0);
872 870
873 return err; 871 return err;
874} 872}
@@ -4080,7 +4078,10 @@ static void ext4_clear_blocks(handle_t *handle, struct inode *inode,
4080 __le32 *last) 4078 __le32 *last)
4081{ 4079{
4082 __le32 *p; 4080 __le32 *p;
4083 int is_metadata = S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode); 4081 int flags = EXT4_FREE_BLOCKS_FORGET;
4082
4083 if (S_ISDIR(inode->i_mode) || S_ISLNK(inode->i_mode))
4084 flags |= EXT4_FREE_BLOCKS_METADATA;
4084 4085
4085 if (try_to_extend_transaction(handle, inode)) { 4086 if (try_to_extend_transaction(handle, inode)) {
4086 if (bh) { 4087 if (bh) {
@@ -4096,27 +4097,10 @@ static void ext4_clear_blocks(handle_t *handle, struct inode *inode,
4096 } 4097 }
4097 } 4098 }
4098 4099
4099 /* 4100 for (p = first; p < last; p++)
4100 * Any buffers which are on the journal will be in memory. We 4101 *p = 0;
4101 * find them on the hash table so jbd2_journal_revoke() will
4102 * run jbd2_journal_forget() on them. We've already detached
4103 * each block from the file, so bforget() in
4104 * jbd2_journal_forget() should be safe.
4105 *
4106 * AKPM: turn on bforget in jbd2_journal_forget()!!!
4107 */
4108 for (p = first; p < last; p++) {
4109 u32 nr = le32_to_cpu(*p);
4110 if (nr) {
4111 struct buffer_head *tbh;
4112
4113 *p = 0;
4114 tbh = sb_find_get_block(inode->i_sb, nr);
4115 ext4_forget(handle, is_metadata, inode, tbh, nr);
4116 }
4117 }
4118 4102
4119 ext4_free_blocks(handle, inode, block_to_free, count, is_metadata); 4103 ext4_free_blocks(handle, inode, 0, block_to_free, count, flags);
4120} 4104}
4121 4105
4122/** 4106/**
@@ -4304,7 +4288,8 @@ static void ext4_free_branches(handle_t *handle, struct inode *inode,
4304 blocks_for_truncate(inode)); 4288 blocks_for_truncate(inode));
4305 } 4289 }
4306 4290
4307 ext4_free_blocks(handle, inode, nr, 1, 1); 4291 ext4_free_blocks(handle, inode, 0, nr, 1,
4292 EXT4_FREE_BLOCKS_METADATA);
4308 4293
4309 if (parent_bh) { 4294 if (parent_bh) {
4310 /* 4295 /*