diff options
author | Jan Kara <jack@suse.cz> | 2009-04-02 19:57:13 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-04-02 22:04:52 -0400 |
commit | ecca9af0a98fdacfcdc73979d08481d7b27ff986 (patch) | |
tree | 41aa40eedd27799b2fa021138173c1adcabe89a5 /fs/jbd | |
parent | 039fd8ce6258e01ec29f1637f9bf1868dd877c55 (diff) |
jbd: fix oops in jbd_journal_init_inode() on corrupted fs
On 32-bit system with CONFIG_LBD getblk can fail because provided block
number is too big. Make JBD gracefully handle that.
Signed-off-by: Jan Kara <jack@suse.cz>
Cc: <dmaciejak@fortinet.com>
Cc: <linux-ext4@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/jbd')
-rw-r--r-- | fs/jbd/journal.c | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index e79c07812afa..737f7246a4b5 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c | |||
@@ -637,6 +637,8 @@ struct journal_head *journal_get_descriptor_buffer(journal_t *journal) | |||
637 | return NULL; | 637 | return NULL; |
638 | 638 | ||
639 | bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); | 639 | bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); |
640 | if (!bh) | ||
641 | return NULL; | ||
640 | lock_buffer(bh); | 642 | lock_buffer(bh); |
641 | memset(bh->b_data, 0, journal->j_blocksize); | 643 | memset(bh->b_data, 0, journal->j_blocksize); |
642 | set_buffer_uptodate(bh); | 644 | set_buffer_uptodate(bh); |
@@ -733,9 +735,7 @@ journal_t * journal_init_dev(struct block_device *bdev, | |||
733 | if (!journal->j_wbuf) { | 735 | if (!journal->j_wbuf) { |
734 | printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", | 736 | printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", |
735 | __func__); | 737 | __func__); |
736 | kfree(journal); | 738 | goto out_err; |
737 | journal = NULL; | ||
738 | goto out; | ||
739 | } | 739 | } |
740 | journal->j_dev = bdev; | 740 | journal->j_dev = bdev; |
741 | journal->j_fs_dev = fs_dev; | 741 | journal->j_fs_dev = fs_dev; |
@@ -743,11 +743,19 @@ journal_t * journal_init_dev(struct block_device *bdev, | |||
743 | journal->j_maxlen = len; | 743 | journal->j_maxlen = len; |
744 | 744 | ||
745 | bh = __getblk(journal->j_dev, start, journal->j_blocksize); | 745 | bh = __getblk(journal->j_dev, start, journal->j_blocksize); |
746 | J_ASSERT(bh != NULL); | 746 | if (!bh) { |
747 | printk(KERN_ERR | ||
748 | "%s: Cannot get buffer for journal superblock\n", | ||
749 | __func__); | ||
750 | goto out_err; | ||
751 | } | ||
747 | journal->j_sb_buffer = bh; | 752 | journal->j_sb_buffer = bh; |
748 | journal->j_superblock = (journal_superblock_t *)bh->b_data; | 753 | journal->j_superblock = (journal_superblock_t *)bh->b_data; |
749 | out: | 754 | |
750 | return journal; | 755 | return journal; |
756 | out_err: | ||
757 | kfree(journal); | ||
758 | return NULL; | ||
751 | } | 759 | } |
752 | 760 | ||
753 | /** | 761 | /** |
@@ -787,8 +795,7 @@ journal_t * journal_init_inode (struct inode *inode) | |||
787 | if (!journal->j_wbuf) { | 795 | if (!journal->j_wbuf) { |
788 | printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", | 796 | printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", |
789 | __func__); | 797 | __func__); |
790 | kfree(journal); | 798 | goto out_err; |
791 | return NULL; | ||
792 | } | 799 | } |
793 | 800 | ||
794 | err = journal_bmap(journal, 0, &blocknr); | 801 | err = journal_bmap(journal, 0, &blocknr); |
@@ -796,16 +803,23 @@ journal_t * journal_init_inode (struct inode *inode) | |||
796 | if (err) { | 803 | if (err) { |
797 | printk(KERN_ERR "%s: Cannnot locate journal superblock\n", | 804 | printk(KERN_ERR "%s: Cannnot locate journal superblock\n", |
798 | __func__); | 805 | __func__); |
799 | kfree(journal); | 806 | goto out_err; |
800 | return NULL; | ||
801 | } | 807 | } |
802 | 808 | ||
803 | bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); | 809 | bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); |
804 | J_ASSERT(bh != NULL); | 810 | if (!bh) { |
811 | printk(KERN_ERR | ||
812 | "%s: Cannot get buffer for journal superblock\n", | ||
813 | __func__); | ||
814 | goto out_err; | ||
815 | } | ||
805 | journal->j_sb_buffer = bh; | 816 | journal->j_sb_buffer = bh; |
806 | journal->j_superblock = (journal_superblock_t *)bh->b_data; | 817 | journal->j_superblock = (journal_superblock_t *)bh->b_data; |
807 | 818 | ||
808 | return journal; | 819 | return journal; |
820 | out_err: | ||
821 | kfree(journal); | ||
822 | return NULL; | ||
809 | } | 823 | } |
810 | 824 | ||
811 | /* | 825 | /* |