Commit 62913ae9 authored by Theodore Ts'o's avatar Theodore Ts'o
Browse files

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: default avatar <syzbot+9543479984ae9e576000@syzkaller.appspotmail.com>
Link: https://syzkaller.appspot.com/bug?id=e4aaa78795e490421c79f76ec3679006c8ff4cf0


Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent 2b96b4a5
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -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;
}
+6 −3
Original line number Diff line number Diff line
@@ -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) {
+8 −0
Original line number Diff line number Diff line
@@ -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) \