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>
This commit is contained in:
@@ -637,6 +637,8 @@ struct journal_head *journal_get_descriptor_buffer(journal_t *journal)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
|
bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
|
||||||
|
if (!bh)
|
||||||
|
return NULL;
|
||||||
lock_buffer(bh);
|
lock_buffer(bh);
|
||||||
memset(bh->b_data, 0, journal->j_blocksize);
|
memset(bh->b_data, 0, journal->j_blocksize);
|
||||||
set_buffer_uptodate(bh);
|
set_buffer_uptodate(bh);
|
||||||
@@ -733,9 +735,7 @@ journal_t * journal_init_dev(struct block_device *bdev,
|
|||||||
if (!journal->j_wbuf) {
|
if (!journal->j_wbuf) {
|
||||||
printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
|
printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
|
||||||
__func__);
|
__func__);
|
||||||
kfree(journal);
|
goto out_err;
|
||||||
journal = NULL;
|
|
||||||
goto out;
|
|
||||||
}
|
}
|
||||||
journal->j_dev = bdev;
|
journal->j_dev = bdev;
|
||||||
journal->j_fs_dev = fs_dev;
|
journal->j_fs_dev = fs_dev;
|
||||||
@@ -743,11 +743,19 @@ journal_t * journal_init_dev(struct block_device *bdev,
|
|||||||
journal->j_maxlen = len;
|
journal->j_maxlen = len;
|
||||||
|
|
||||||
bh = __getblk(journal->j_dev, start, journal->j_blocksize);
|
bh = __getblk(journal->j_dev, start, journal->j_blocksize);
|
||||||
J_ASSERT(bh != NULL);
|
if (!bh) {
|
||||||
|
printk(KERN_ERR
|
||||||
|
"%s: Cannot get buffer for journal superblock\n",
|
||||||
|
__func__);
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
journal->j_sb_buffer = bh;
|
journal->j_sb_buffer = bh;
|
||||||
journal->j_superblock = (journal_superblock_t *)bh->b_data;
|
journal->j_superblock = (journal_superblock_t *)bh->b_data;
|
||||||
out:
|
|
||||||
return journal;
|
return journal;
|
||||||
|
out_err:
|
||||||
|
kfree(journal);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -787,8 +795,7 @@ journal_t * journal_init_inode (struct inode *inode)
|
|||||||
if (!journal->j_wbuf) {
|
if (!journal->j_wbuf) {
|
||||||
printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
|
printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
|
||||||
__func__);
|
__func__);
|
||||||
kfree(journal);
|
goto out_err;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = journal_bmap(journal, 0, &blocknr);
|
err = journal_bmap(journal, 0, &blocknr);
|
||||||
@@ -796,16 +803,23 @@ journal_t * journal_init_inode (struct inode *inode)
|
|||||||
if (err) {
|
if (err) {
|
||||||
printk(KERN_ERR "%s: Cannnot locate journal superblock\n",
|
printk(KERN_ERR "%s: Cannnot locate journal superblock\n",
|
||||||
__func__);
|
__func__);
|
||||||
kfree(journal);
|
goto out_err;
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
|
bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
|
||||||
J_ASSERT(bh != NULL);
|
if (!bh) {
|
||||||
|
printk(KERN_ERR
|
||||||
|
"%s: Cannot get buffer for journal superblock\n",
|
||||||
|
__func__);
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
journal->j_sb_buffer = bh;
|
journal->j_sb_buffer = bh;
|
||||||
journal->j_superblock = (journal_superblock_t *)bh->b_data;
|
journal->j_superblock = (journal_superblock_t *)bh->b_data;
|
||||||
|
|
||||||
return journal;
|
return journal;
|
||||||
|
out_err:
|
||||||
|
kfree(journal);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user