Skip to content

Commit

Permalink
ext4, jbd2: add an optimized bmap for the journal inode
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Theodore Ts'o committed Mar 11, 2023
1 parent 2b96b4a commit 62913ae
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 3 deletions.
23 changes: 23 additions & 0 deletions fs/ext4/super.c
Original file line number Diff line number Diff line change
Expand Up @@ -5742,6 +5742,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)
{
Expand All @@ -5762,6 +5784,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;
}
Expand Down
9 changes: 6 additions & 3 deletions fs/jbd2/journal.c
Original file line number Diff line number Diff line change
Expand Up @@ -970,10 +970,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) {
Expand Down
8 changes: 8 additions & 0 deletions include/linux/jbd2.h
Original file line number Diff line number Diff line change
Expand Up @@ -1308,6 +1308,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) \
Expand Down

0 comments on commit 62913ae

Please sign in to comment.