Skip to content

Commit 9d875e0

Browse files
joannekoongbrauner
authored andcommitted
iomap: account for unaligned end offsets when truncating read range
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>
1 parent a0f1cab commit 9d875e0

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
@@ -218,6 +218,22 @@ static void ifs_free(struct folio *folio)
218218
kfree(ifs);
219219
}
220220

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

281298
if (first <= end && last > end)
282-
plen -= (last - end) * block_size;
299+
plen -= iomap_bytes_to_truncate(*pos + plen, block_bits,
300+
last - end);
283301
}
284302

285303
*offp = poff;

0 commit comments

Comments
 (0)