Message ID | 20250217065955.3829229-1-yi.zhang@huaweicloud.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | jbd2: fix off-by-one while erasing journal | expand |
On Mon 17-02-25 14:59:55, Zhang Yi wrote: > From: Zhang Yi <yi.zhang@huawei.com> > > 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: 01d5d96542fd ("ext4: add discard/zeroout flags to journal flush") > Signed-off-by: Zhang Yi <yi.zhang@huawei.com> Looks good! Feel free to add: Reviewed-by: Jan Kara <jack@suse.cz> Honza > --- > fs/jbd2/journal.c | 15 ++++++--------- > 1 file changed, 6 insertions(+), 9 deletions(-) > > diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c > index d8084b31b361..49a9e99cbc03 100644 > --- a/fs/jbd2/journal.c > +++ b/fs/jbd2/journal.c > @@ -1965,17 +1965,15 @@ static int __jbd2_journal_erase(journal_t *journal, unsigned int flags) > return err; > } > > - if (block_start == ~0ULL) { > - block_start = phys_block; > - block_stop = block_start - 1; > - } > + if (block_start == ~0ULL) > + block_stop = block_start = phys_block; > > /* > * last block not contiguous with current block, > * process last contiguous region and return to this block on > * next loop > */ > - if (phys_block != block_stop + 1) { > + if (phys_block != block_stop) { > block--; > } else { > block_stop++; > @@ -1994,11 +1992,10 @@ static int __jbd2_journal_erase(journal_t *journal, unsigned int flags) > */ > byte_start = block_start * journal->j_blocksize; > byte_stop = block_stop * journal->j_blocksize; > - byte_count = (block_stop - block_start + 1) * > - journal->j_blocksize; > + byte_count = (block_stop - block_start) * journal->j_blocksize; > > truncate_inode_pages_range(journal->j_dev->bd_mapping, > - byte_start, byte_stop); > + byte_start, byte_stop - 1); > > if (flags & JBD2_JOURNAL_FLUSH_DISCARD) { > err = blkdev_issue_discard(journal->j_dev, > @@ -2013,7 +2010,7 @@ static int __jbd2_journal_erase(journal_t *journal, unsigned int flags) > } > > if (unlikely(err != 0)) { > - pr_err("JBD2: (error %d) unable to wipe journal at physical blocks %llu - %llu", > + pr_err("JBD2: (error %d) unable to wipe journal at physical blocks [%llu, %llu)", > err, block_start, block_stop); > return err; > } > -- > 2.46.1 >
On 2025/2/17 14:59, Zhang Yi wrote: > From: Zhang Yi <yi.zhang@huawei.com> > > 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: 01d5d96542fd ("ext4: add discard/zeroout flags to journal flush") > Signed-off-by: Zhang Yi <yi.zhang@huawei.com> Looks good, thanks for the patch! Reviewed-by: Baokun Li <libaokun1@huawei.com> > --- > fs/jbd2/journal.c | 15 ++++++--------- > 1 file changed, 6 insertions(+), 9 deletions(-) > > diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c > index d8084b31b361..49a9e99cbc03 100644 > --- a/fs/jbd2/journal.c > +++ b/fs/jbd2/journal.c > @@ -1965,17 +1965,15 @@ static int __jbd2_journal_erase(journal_t *journal, unsigned int flags) > return err; > } > > - if (block_start == ~0ULL) { > - block_start = phys_block; > - block_stop = block_start - 1; > - } > + if (block_start == ~0ULL) > + block_stop = block_start = phys_block; > > /* > * last block not contiguous with current block, > * process last contiguous region and return to this block on > * next loop > */ > - if (phys_block != block_stop + 1) { > + if (phys_block != block_stop) { > block--; > } else { > block_stop++; > @@ -1994,11 +1992,10 @@ static int __jbd2_journal_erase(journal_t *journal, unsigned int flags) > */ > byte_start = block_start * journal->j_blocksize; > byte_stop = block_stop * journal->j_blocksize; > - byte_count = (block_stop - block_start + 1) * > - journal->j_blocksize; > + byte_count = (block_stop - block_start) * journal->j_blocksize; > > truncate_inode_pages_range(journal->j_dev->bd_mapping, > - byte_start, byte_stop); > + byte_start, byte_stop - 1); > > if (flags & JBD2_JOURNAL_FLUSH_DISCARD) { > err = blkdev_issue_discard(journal->j_dev, > @@ -2013,7 +2010,7 @@ static int __jbd2_journal_erase(journal_t *journal, unsigned int flags) > } > > if (unlikely(err != 0)) { > - pr_err("JBD2: (error %d) unable to wipe journal at physical blocks %llu - %llu", > + pr_err("JBD2: (error %d) unable to wipe journal at physical blocks [%llu, %llu)", > err, block_start, block_stop); > return err; > }
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c index d8084b31b361..49a9e99cbc03 100644 --- a/fs/jbd2/journal.c +++ b/fs/jbd2/journal.c @@ -1965,17 +1965,15 @@ static int __jbd2_journal_erase(journal_t *journal, unsigned int flags) return err; } - if (block_start == ~0ULL) { - block_start = phys_block; - block_stop = block_start - 1; - } + if (block_start == ~0ULL) + block_stop = block_start = phys_block; /* * last block not contiguous with current block, * process last contiguous region and return to this block on * next loop */ - if (phys_block != block_stop + 1) { + if (phys_block != block_stop) { block--; } else { block_stop++; @@ -1994,11 +1992,10 @@ static int __jbd2_journal_erase(journal_t *journal, unsigned int flags) */ byte_start = block_start * journal->j_blocksize; byte_stop = block_stop * journal->j_blocksize; - byte_count = (block_stop - block_start + 1) * - journal->j_blocksize; + byte_count = (block_stop - block_start) * journal->j_blocksize; truncate_inode_pages_range(journal->j_dev->bd_mapping, - byte_start, byte_stop); + byte_start, byte_stop - 1); if (flags & JBD2_JOURNAL_FLUSH_DISCARD) { err = blkdev_issue_discard(journal->j_dev, @@ -2013,7 +2010,7 @@ static int __jbd2_journal_erase(journal_t *journal, unsigned int flags) } if (unlikely(err != 0)) { - pr_err("JBD2: (error %d) unable to wipe journal at physical blocks %llu - %llu", + pr_err("JBD2: (error %d) unable to wipe journal at physical blocks [%llu, %llu)", err, block_start, block_stop); return err; }