On 2024/8/13 0:33, Darrick J. Wong wrote: > On Mon, Aug 12, 2024 at 08:11:54PM +0800, Zhang Yi wrote: >> From: Zhang Yi <yi.zhang@xxxxxxxxxx> >> >> The block range calculation in ifs_clear_range_dirty() is incorrect when >> partial clear a range in a folio. We can't clear the dirty bit of the >> first block or the last block if the start or end offset is blocksize >> unaligned, this has not yet caused any issue since we always clear a >> whole folio in iomap_writepage_map()->iomap_clear_range_dirty(). Fix >> this by round up the first block and round down the last block and >> correct the calculation of nr_blks. >> >> Signed-off-by: Zhang Yi <yi.zhang@xxxxxxxxxx> >> --- >> fs/iomap/buffered-io.c | 9 ++++++--- >> 1 file changed, 6 insertions(+), 3 deletions(-) >> >> diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c >> index f420c53d86ac..4da453394aaf 100644 >> --- a/fs/iomap/buffered-io.c >> +++ b/fs/iomap/buffered-io.c >> @@ -138,11 +138,14 @@ static void ifs_clear_range_dirty(struct folio *folio, >> { >> struct inode *inode = folio->mapping->host; >> unsigned int blks_per_folio = i_blocks_per_folio(inode, folio); >> - unsigned int first_blk = (off >> inode->i_blkbits); >> - unsigned int last_blk = (off + len - 1) >> inode->i_blkbits; >> - unsigned int nr_blks = last_blk - first_blk + 1; >> + unsigned int first_blk = DIV_ROUND_UP(off, i_blocksize(inode)); > > Is there a round up macro that doesn't involve integer division? > Sorry, I don't find a common macro now, if we want to avoid integer division, how about open code here? first_blk = round_up(off, i_blocksize(inode)) >> inode->i_blkbits; Thanks, Yi. > >> + unsigned int last_blk = (off + len) >> inode->i_blkbits; >> + unsigned int nr_blks = last_blk - first_blk; >> unsigned long flags; >> >> + if (!nr_blks) >> + return; >> + >> spin_lock_irqsave(&ifs->state_lock, flags); >> bitmap_clear(ifs->state, first_blk + blks_per_folio, nr_blks); >> spin_unlock_irqrestore(&ifs->state_lock, flags); >> -- >> 2.39.2 >> >>