Skip to content

Commit 18aba2a

Browse files
zhangyi089tytso
authored andcommitted
jbd2: fix off-by-one while erasing journal
In __jbd2_journal_erase(), the block_stop parameter includes the last block of a contiguous region; however, the calculation of byte_stop is incorrect, as it does not account for the bytes in that last block. Consequently, the page cache is not cleared properly, which occasionally causes the ext4/050 test to fail. Since block_stop operates on inclusion semantics, it involves repeated increments and decrements by 1, significantly increasing the complexity of the calculations. Optimize the calculation and fix the incorrect byte_stop by make both block_stop and byte_stop to use exclusion semantics. This fixes a failure in fstests ext4/050. Fixes: 01d5d96 ("ext4: add discard/zeroout flags to journal flush") Signed-off-by: Zhang Yi <[email protected]> Reviewed-by: Baokun Li <[email protected]> Reviewed-by: Jan Kara <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Theodore Ts'o <[email protected]>
1 parent 08be56f commit 18aba2a

File tree

1 file changed

+6
-9
lines changed

1 file changed

+6
-9
lines changed

fs/jbd2/journal.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1964,17 +1964,15 @@ static int __jbd2_journal_erase(journal_t *journal, unsigned int flags)
19641964
return err;
19651965
}
19661966

1967-
if (block_start == ~0ULL) {
1968-
block_start = phys_block;
1969-
block_stop = block_start - 1;
1970-
}
1967+
if (block_start == ~0ULL)
1968+
block_stop = block_start = phys_block;
19711969

19721970
/*
19731971
* last block not contiguous with current block,
19741972
* process last contiguous region and return to this block on
19751973
* next loop
19761974
*/
1977-
if (phys_block != block_stop + 1) {
1975+
if (phys_block != block_stop) {
19781976
block--;
19791977
} else {
19801978
block_stop++;
@@ -1993,11 +1991,10 @@ static int __jbd2_journal_erase(journal_t *journal, unsigned int flags)
19931991
*/
19941992
byte_start = block_start * journal->j_blocksize;
19951993
byte_stop = block_stop * journal->j_blocksize;
1996-
byte_count = (block_stop - block_start + 1) *
1997-
journal->j_blocksize;
1994+
byte_count = (block_stop - block_start) * journal->j_blocksize;
19981995

19991996
truncate_inode_pages_range(journal->j_dev->bd_mapping,
2000-
byte_start, byte_stop);
1997+
byte_start, byte_stop - 1);
20011998

20021999
if (flags & JBD2_JOURNAL_FLUSH_DISCARD) {
20032000
err = blkdev_issue_discard(journal->j_dev,
@@ -2012,7 +2009,7 @@ static int __jbd2_journal_erase(journal_t *journal, unsigned int flags)
20122009
}
20132010

20142011
if (unlikely(err != 0)) {
2015-
pr_err("JBD2: (error %d) unable to wipe journal at physical blocks %llu - %llu",
2012+
pr_err("JBD2: (error %d) unable to wipe journal at physical blocks [%llu, %llu)",
20162013
err, block_start, block_stop);
20172014
return err;
20182015
}

0 commit comments

Comments
 (0)