diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-30 18:35:16 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-30 18:35:16 -0400 |
commit | 8c673cbc7682b3f2862fe42f8069cac20c09e160 (patch) | |
tree | f20de69903a1c3d95f92098e24139c69c2d6a894 /fs | |
parent | 4476c0eead051ae6ff8abbc358763b00790d1635 (diff) | |
parent | ffb5387e85d528fb6d0d924abfa3fbf0fc484071 (diff) |
Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4
Pull ext4 bugfix from Ted Ts'o:
"This fixes the root cause of the ext4 data corruption bug which raised
a ruckus on LWN, Phoronix, and Slashdot.
This bug only showed up when non-standard mount options
(journal_async_commit and/or journal_checksum) were enabled, and when
the file system was not cleanly unmounted, but the root cause was the
inode bitmap modifications was not being properly journaled.
This could potentially lead to minor file system corruptions (pass 5
complaints with the inode allocation bitmap) after an unclean shutdown
under the wrong/unlucky workloads, but it turned into major failure if
the journal_checksum and/or jouaral_async_commit was enabled."
* tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
ext4: fix unjournaled inode bitmap modification
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext4/ialloc.c | 19 |
1 files changed, 9 insertions, 10 deletions
diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 4facdd29a350..3a100e7a62a8 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c | |||
@@ -725,6 +725,10 @@ repeat_in_this_group: | |||
725 | "inode=%lu", ino + 1); | 725 | "inode=%lu", ino + 1); |
726 | continue; | 726 | continue; |
727 | } | 727 | } |
728 | BUFFER_TRACE(inode_bitmap_bh, "get_write_access"); | ||
729 | err = ext4_journal_get_write_access(handle, inode_bitmap_bh); | ||
730 | if (err) | ||
731 | goto fail; | ||
728 | ext4_lock_group(sb, group); | 732 | ext4_lock_group(sb, group); |
729 | ret2 = ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data); | 733 | ret2 = ext4_test_and_set_bit(ino, inode_bitmap_bh->b_data); |
730 | ext4_unlock_group(sb, group); | 734 | ext4_unlock_group(sb, group); |
@@ -738,6 +742,11 @@ repeat_in_this_group: | |||
738 | goto out; | 742 | goto out; |
739 | 743 | ||
740 | got: | 744 | got: |
745 | BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata"); | ||
746 | err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh); | ||
747 | if (err) | ||
748 | goto fail; | ||
749 | |||
741 | /* We may have to initialize the block bitmap if it isn't already */ | 750 | /* We may have to initialize the block bitmap if it isn't already */ |
742 | if (ext4_has_group_desc_csum(sb) && | 751 | if (ext4_has_group_desc_csum(sb) && |
743 | gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { | 752 | gdp->bg_flags & cpu_to_le16(EXT4_BG_BLOCK_UNINIT)) { |
@@ -771,11 +780,6 @@ got: | |||
771 | goto fail; | 780 | goto fail; |
772 | } | 781 | } |
773 | 782 | ||
774 | BUFFER_TRACE(inode_bitmap_bh, "get_write_access"); | ||
775 | err = ext4_journal_get_write_access(handle, inode_bitmap_bh); | ||
776 | if (err) | ||
777 | goto fail; | ||
778 | |||
779 | BUFFER_TRACE(group_desc_bh, "get_write_access"); | 783 | BUFFER_TRACE(group_desc_bh, "get_write_access"); |
780 | err = ext4_journal_get_write_access(handle, group_desc_bh); | 784 | err = ext4_journal_get_write_access(handle, group_desc_bh); |
781 | if (err) | 785 | if (err) |
@@ -823,11 +827,6 @@ got: | |||
823 | } | 827 | } |
824 | ext4_unlock_group(sb, group); | 828 | ext4_unlock_group(sb, group); |
825 | 829 | ||
826 | BUFFER_TRACE(inode_bitmap_bh, "call ext4_handle_dirty_metadata"); | ||
827 | err = ext4_handle_dirty_metadata(handle, NULL, inode_bitmap_bh); | ||
828 | if (err) | ||
829 | goto fail; | ||
830 | |||
831 | BUFFER_TRACE(group_desc_bh, "call ext4_handle_dirty_metadata"); | 830 | BUFFER_TRACE(group_desc_bh, "call ext4_handle_dirty_metadata"); |
832 | err = ext4_handle_dirty_metadata(handle, NULL, group_desc_bh); | 831 | err = ext4_handle_dirty_metadata(handle, NULL, group_desc_bh); |
833 | if (err) | 832 | if (err) |