Skip to content

Commit 56d35a4

Browse files
jankaratytso
authored andcommitted
ext4: Fix dirtying of journalled buffers in data=journal mode
In data=journal mode, we still use block_write_begin() to prepare page for writing. This function can occasionally mark buffer dirty which violates journalling assumptions - when a buffer is part of a transaction, it should be dirty and a buffer can be already part of a forget list of some transaction when block_write_begin() gets called. This violation of journalling assumptions then results in "JBD: Spotted dirty metadata buffer..." warnings. In fact, temporary dirtying the buffer while the page is still locked does not really cause problems to the journalling because we won't write the buffer until the page gets unlocked. So we just have to make sure to clear dirty bits before unlocking the page. Signed-off-by: Jan Kara <jack@suse.cz>
1 parent 0cfc925 commit 56d35a4

File tree

1 file changed

+17
-1
lines changed

1 file changed

+17
-1
lines changed

fs/ext4/inode.c

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1527,9 +1527,25 @@ static int walk_page_buffers(handle_t *handle,
15271527
static int do_journal_get_write_access(handle_t *handle,
15281528
struct buffer_head *bh)
15291529
{
1530+
int dirty = buffer_dirty(bh);
1531+
int ret;
1532+
15301533
if (!buffer_mapped(bh) || buffer_freed(bh))
15311534
return 0;
1532-
return ext4_journal_get_write_access(handle, bh);
1535+
/*
1536+
* __block_prepare_write() could have dirtied some buffers. Clean
1537+
* the dirty bit as jbd2_journal_get_write_access() could complain
1538+
* otherwise about fs integrity issues. Setting of the dirty bit
1539+
* by __block_prepare_write() isn't a real problem here as we clear
1540+
* the bit before releasing a page lock and thus writeback cannot
1541+
* ever write the buffer.
1542+
*/
1543+
if (dirty)
1544+
clear_buffer_dirty(bh);
1545+
ret = ext4_journal_get_write_access(handle, bh);
1546+
if (!ret && dirty)
1547+
ret = ext4_handle_dirty_metadata(handle, NULL, bh);
1548+
return ret;
15331549
}
15341550

15351551
/*

0 commit comments

Comments
 (0)