mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 18:41:58 +09:00
ext4, jbd2: add an optimized bmap for the journal inode
[ Upstream commit 62913ae96d ]
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>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
1f4c1de782
commit
0bed2db354
@@ -5752,6 +5752,28 @@ static struct inode *ext4_get_journal_inode(struct super_block *sb,
|
|||||||
return journal_inode;
|
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,
|
static journal_t *ext4_get_journal(struct super_block *sb,
|
||||||
unsigned int journal_inum)
|
unsigned int journal_inum)
|
||||||
{
|
{
|
||||||
@@ -5772,6 +5794,7 @@ static journal_t *ext4_get_journal(struct super_block *sb,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
journal->j_private = sb;
|
journal->j_private = sb;
|
||||||
|
journal->j_bmap = ext4_journal_bmap;
|
||||||
ext4_init_journal_params(sb, journal);
|
ext4_init_journal_params(sb, journal);
|
||||||
return journal;
|
return journal;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -971,10 +971,13 @@ int jbd2_journal_bmap(journal_t *journal, unsigned long blocknr,
|
|||||||
{
|
{
|
||||||
int err = 0;
|
int err = 0;
|
||||||
unsigned long long ret;
|
unsigned long long ret;
|
||||||
sector_t block = 0;
|
sector_t block = blocknr;
|
||||||
|
|
||||||
if (journal->j_inode) {
|
if (journal->j_bmap) {
|
||||||
block = blocknr;
|
err = journal->j_bmap(journal, &block);
|
||||||
|
if (err == 0)
|
||||||
|
*retp = block;
|
||||||
|
} else if (journal->j_inode) {
|
||||||
ret = bmap(journal->j_inode, &block);
|
ret = bmap(journal->j_inode, &block);
|
||||||
|
|
||||||
if (ret || !block) {
|
if (ret || !block) {
|
||||||
|
|||||||
@@ -1302,6 +1302,14 @@ struct journal_s
|
|||||||
struct buffer_head *bh,
|
struct buffer_head *bh,
|
||||||
enum passtype pass, int off,
|
enum passtype pass, int off,
|
||||||
tid_t expected_commit_id);
|
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) \
|
#define jbd2_might_wait_for_commit(j) \
|
||||||
|
|||||||
Reference in New Issue
Block a user