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 e79c07812af..737f7246a4b 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 | /* |
