Skip to content

Commit 62913ae

Browse files
committed
ext4, jbd2: add an optimized bmap for the journal inode
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: [email protected] Link: https://syzkaller.appspot.com/bug?id=e4aaa78795e490421c79f76ec3679006c8ff4cf0 Signed-off-by: Theodore Ts'o <[email protected]>
1 parent 2b96b4a commit 62913ae

File tree

3 files changed

+37
-3
lines changed

3 files changed

+37
-3
lines changed

fs/ext4/super.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5742,6 +5742,28 @@ static struct inode *ext4_get_journal_inode(struct super_block *sb,
57425742
return journal_inode;
57435743
}
57445744

5745+
static int ext4_journal_bmap(journal_t *journal, sector_t *block)
5746+
{
5747+
struct ext4_map_blocks map;
5748+
int ret;
5749+
5750+
if (journal->j_inode == NULL)
5751+
return 0;
5752+
5753+
map.m_lblk = *block;
5754+
map.m_len = 1;
5755+
ret = ext4_map_blocks(NULL, journal->j_inode, &map, 0);
5756+
if (ret <= 0) {
5757+
ext4_msg(journal->j_inode->i_sb, KERN_CRIT,
5758+
"journal bmap failed: block %llu ret %d\n",
5759+
*block, ret);
5760+
jbd2_journal_abort(journal, ret ? ret : -EIO);
5761+
return ret;
5762+
}
5763+
*block = map.m_pblk;
5764+
return 0;
5765+
}
5766+
57455767
static journal_t *ext4_get_journal(struct super_block *sb,
57465768
unsigned int journal_inum)
57475769
{
@@ -5762,6 +5784,7 @@ static journal_t *ext4_get_journal(struct super_block *sb,
57625784
return NULL;
57635785
}
57645786
journal->j_private = sb;
5787+
journal->j_bmap = ext4_journal_bmap;
57655788
ext4_init_journal_params(sb, journal);
57665789
return journal;
57675790
}

fs/jbd2/journal.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -970,10 +970,13 @@ int jbd2_journal_bmap(journal_t *journal, unsigned long blocknr,
970970
{
971971
int err = 0;
972972
unsigned long long ret;
973-
sector_t block = 0;
973+
sector_t block = blocknr;
974974

975-
if (journal->j_inode) {
976-
block = blocknr;
975+
if (journal->j_bmap) {
976+
err = journal->j_bmap(journal, &block);
977+
if (err == 0)
978+
*retp = block;
979+
} else if (journal->j_inode) {
977980
ret = bmap(journal->j_inode, &block);
978981

979982
if (ret || !block) {

include/linux/jbd2.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1308,6 +1308,14 @@ struct journal_s
13081308
struct buffer_head *bh,
13091309
enum passtype pass, int off,
13101310
tid_t expected_commit_id);
1311+
1312+
/**
1313+
* @j_bmap:
1314+
*
1315+
* Bmap function that should be used instead of the generic
1316+
* VFS bmap function.
1317+
*/
1318+
int (*j_bmap)(struct journal_s *journal, sector_t *block);
13111319
};
13121320

13131321
#define jbd2_might_wait_for_commit(j) \

0 commit comments

Comments
 (0)