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:
Theodore Ts'o 2023-03-07 23:15:49 -05:00 committed by Greg Kroah-Hartman
parent 1f4c1de782
commit 0bed2db354
3 changed files with 37 additions and 3 deletions

View File

@ -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;
}

View File

@ -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) {

View File

@ -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) \