aboutsummaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorTheodore Ts'o2023-03-07 23:15:49 -0500
committerTheodore Ts'o2023-03-11 00:44:24 -0500
commit62913ae96de747091c4dacd06d158e7729c1a76d (patch)
treeb8216b43eed65fb2f7ddbedb9bdb7697a890b861 /fs
parent2b96b4a5d9443ca4cad58b0040be455803c05a42 (diff)
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: syzbot+9543479984ae9e576000@syzkaller.appspotmail.com Link: https://syzkaller.appspot.com/bug?id=e4aaa78795e490421c79f76ec3679006c8ff4cf0 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/super.c23
-rw-r--r--fs/jbd2/journal.c9
2 files changed, 29 insertions, 3 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 2192b4111442..46b7345d2b6a 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -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)
{
@@ -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;
}
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index 2696f43e7239..c84f588fdcd0 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -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) {