mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
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>
This commit is contained in:
parent
2b96b4a5d9
commit
62913ae96d
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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) \
|
||||
|
Loading…
Reference in New Issue
Block a user