Skip to content

Commit ae4b39a

Browse files
joannekoongopsiff
authored andcommitted
iomap: account for unaligned end offsets when truncating read range
[ Upstream commit 9d875e0 ] The end position to start truncating from may be at an offset into a block, which under the current logic would result in overtruncation. Adjust the calculation to account for unaligned end offsets. Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Link: https://patch.msgid.link/20251111193658.3495942-3-joannelkoong@gmail.com Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <djwong@kernel.org> Signed-off-by: Christian Brauner <brauner@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org> (cherry picked from commit bfa4924cbc5204cac3e8fa02048d94be1eb50062) Signed-off-by: Wentao Guan <guanwentao@uniontech.com>
1 parent bc44972 commit ae4b39a

1 file changed

Lines changed: 20 additions & 2 deletions

File tree

fs/iomap/buffered-io.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,22 @@ static void ifs_free(struct folio *folio)
217217
kfree(ifs);
218218
}
219219

220+
/*
221+
* Calculate how many bytes to truncate based off the number of blocks to
222+
* truncate and the end position to start truncating from.
223+
*/
224+
static size_t iomap_bytes_to_truncate(loff_t end_pos, unsigned block_bits,
225+
unsigned blocks_truncated)
226+
{
227+
unsigned block_size = 1 << block_bits;
228+
unsigned block_offset = end_pos & (block_size - 1);
229+
230+
if (!block_offset)
231+
return blocks_truncated << block_bits;
232+
233+
return ((blocks_truncated - 1) << block_bits) + block_offset;
234+
}
235+
220236
/*
221237
* Calculate the range inside the folio that we actually need to read.
222238
*/
@@ -262,7 +278,8 @@ static void iomap_adjust_read_range(struct inode *inode, struct folio *folio,
262278
/* truncate len if we find any trailing uptodate block(s) */
263279
while (++i <= last) {
264280
if (ifs_block_is_uptodate(ifs, i)) {
265-
plen -= (last - i + 1) * block_size;
281+
plen -= iomap_bytes_to_truncate(*pos + plen,
282+
block_bits, last - i + 1);
266283
last = i - 1;
267284
break;
268285
}
@@ -278,7 +295,8 @@ static void iomap_adjust_read_range(struct inode *inode, struct folio *folio,
278295
unsigned end = offset_in_folio(folio, isize - 1) >> block_bits;
279296

280297
if (first <= end && last > end)
281-
plen -= (last - end) * block_size;
298+
plen -= iomap_bytes_to_truncate(*pos + plen, block_bits,
299+
last - end);
282300
}
283301

284302
*offp = poff;

0 commit comments

Comments
 (0)