ext4, jbd2: add an optimized bmap for the journal inode
[ Upstream commit 62913ae96de747091c4dacd06d158e7729c1a76d ] The generic bmap() function exported by the VFS takes locks and does checks that are not necessary for the journal inode. So allow the file system to set a journal-optimized bmap function in journal->j_bmap. Reported-by: syzbot+9543479984ae9e576000@syzkaller.appspotmail.com Link: https://syzkaller.appspot.com/bug?id=e4aaa78795e490421c79f76ec3679006c8ff4cf0 Signed-off-by: Theodore Ts'o <tytso@mit.edu> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
1f4c1de782
commit
0bed2db354
@ -5752,6 +5752,28 @@ static struct inode *ext4_get_journal_inode(struct super_block *sb,
|
||||
return journal_inode;
|
||||
}
|
||||
|
||||
static int ext4_journal_bmap(journal_t *journal, sector_t *block)
|
||||
{
|
||||
struct ext4_map_blocks map;
|
||||
int ret;
|
||||
|
||||
if (journal->j_inode == NULL)
|
||||
return 0;
|
||||
|
||||
map.m_lblk = *block;
|
||||
map.m_len = 1;
|
||||
ret = ext4_map_blocks(NULL, journal->j_inode, &map, 0);
|
||||
if (ret <= 0) {
|
||||
ext4_msg(journal->j_inode->i_sb, KERN_CRIT,
|
||||
"journal bmap failed: block %llu ret %d\n",
|
||||
*block, ret);
|
||||
jbd2_journal_abort(journal, ret ? ret : -EIO);
|
||||
return ret;
|
||||
}
|
||||
*block = map.m_pblk;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static journal_t *ext4_get_journal(struct super_block *sb,
|
||||
unsigned int journal_inum)
|
||||
{
|
||||
@ -5772,6 +5794,7 @@ static journal_t *ext4_get_journal(struct super_block *sb,
|
||||
return NULL;
|
||||
}
|
||||
journal->j_private = sb;
|
||||
journal->j_bmap = ext4_journal_bmap;
|
||||
ext4_init_journal_params(sb, journal);
|
||||
return journal;
|
||||
}
|
||||
|
@ -971,10 +971,13 @@ int jbd2_journal_bmap(journal_t *journal, unsigned long blocknr,
|
||||
{
|
||||
int err = 0;
|
||||
unsigned long long ret;
|
||||
sector_t block = 0;
|
||||
sector_t block = blocknr;
|
||||
|
||||
if (journal->j_inode) {
|
||||
block = blocknr;
|
||||
if (journal->j_bmap) {
|
||||
err = journal->j_bmap(journal, &block);
|
||||
if (err == 0)
|
||||
*retp = block;
|
||||
} else if (journal->j_inode) {
|
||||
ret = bmap(journal->j_inode, &block);
|
||||
|
||||
if (ret || !block) {
|
||||
|
@ -1302,6 +1302,14 @@ struct journal_s
|
||||
struct buffer_head *bh,
|
||||
enum passtype pass, int off,
|
||||
tid_t expected_commit_id);
|
||||
|
||||
/**
|
||||
* @j_bmap:
|
||||
*
|
||||
* Bmap function that should be used instead of the generic
|
||||
* VFS bmap function.
|
||||
*/
|
||||
int (*j_bmap)(struct journal_s *journal, sector_t *block);
|
||||
};
|
||||
|
||||
#define jbd2_might_wait_for_commit(j) \
|
||||
|
Loading…
Reference in New Issue
Block a user