Skip to content

Commit adb475b

Browse files
zhangyi089gregkh
authored andcommitted
iomap: correct the range of a partial dirty clear
[ Upstream commit 88c2651 ] The block range calculation in ifs_clear_range_dirty() is incorrect when partially clearing a range in a folio. We cannot clear the dirty bit of the first block or the last block if the start or end offset is not blocksize-aligned. This has not yet caused any issues since we always clear a whole folio in iomap_writeback_folio(). Fix this by rounding up the first block to blocksize alignment, and calculate the last block by rounding down (using truncation). Correct the nr_blks calculation accordingly. Fixes: 4ce02c6 ("iomap: Add per-block dirty state tracking to improve performance") Signed-off-by: Zhang Yi <yi.zhang@huawei.com> Link: https://patch.msgid.link/20260714082325.325163-2-yi.zhang@huaweicloud.com Reviewed-by: Joanne Koong <joannelkoong@gmail.com> Reviewed-by: "Darrick J. Wong" <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 28cb5d8 commit adb475b

1 file changed

Lines changed: 8 additions & 4 deletions

File tree

fs/iomap/buffered-io.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -137,13 +137,17 @@ static void ifs_clear_range_dirty(struct folio *folio,
137137
{
138138
struct inode *inode = folio->mapping->host;
139139
unsigned int blks_per_folio = i_blocks_per_folio(inode, folio);
140-
unsigned int first_blk = (off >> inode->i_blkbits);
141-
unsigned int last_blk = (off + len - 1) >> inode->i_blkbits;
142-
unsigned int nr_blks = last_blk - first_blk + 1;
140+
unsigned int first_blk = round_up(off, i_blocksize(inode)) >>
141+
inode->i_blkbits;
142+
unsigned int last_blk = (off + len) >> inode->i_blkbits;
143143
unsigned long flags;
144144

145+
if (first_blk >= last_blk)
146+
return;
147+
145148
spin_lock_irqsave(&ifs->state_lock, flags);
146-
bitmap_clear(ifs->state, first_blk + blks_per_folio, nr_blks);
149+
bitmap_clear(ifs->state, first_blk + blks_per_folio,
150+
last_blk - first_blk);
147151
spin_unlock_irqrestore(&ifs->state_lock, flags);
148152
}
149153

0 commit comments

Comments
 (0)