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? --D > + 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 > >