iomap: account for unaligned end offsets when truncating read range
[ Upstream commit 9d875e0eef ]
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>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
82b60ffbb5
commit
011e356fe4
@@ -188,6 +188,22 @@ static void ifs_free(struct folio *folio)
|
||||
kfree(ifs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate how many bytes to truncate based off the number of blocks to
|
||||
* truncate and the end position to start truncating from.
|
||||
*/
|
||||
static size_t iomap_bytes_to_truncate(loff_t end_pos, unsigned block_bits,
|
||||
unsigned blocks_truncated)
|
||||
{
|
||||
unsigned block_size = 1 << block_bits;
|
||||
unsigned block_offset = end_pos & (block_size - 1);
|
||||
|
||||
if (!block_offset)
|
||||
return blocks_truncated << block_bits;
|
||||
|
||||
return ((blocks_truncated - 1) << block_bits) + block_offset;
|
||||
}
|
||||
|
||||
/*
|
||||
* Calculate the range inside the folio that we actually need to read.
|
||||
*/
|
||||
@@ -233,7 +249,8 @@ static void iomap_adjust_read_range(struct inode *inode, struct folio *folio,
|
||||
/* truncate len if we find any trailing uptodate block(s) */
|
||||
while (++i <= last) {
|
||||
if (ifs_block_is_uptodate(ifs, i)) {
|
||||
plen -= (last - i + 1) * block_size;
|
||||
plen -= iomap_bytes_to_truncate(*pos + plen,
|
||||
block_bits, last - i + 1);
|
||||
last = i - 1;
|
||||
break;
|
||||
}
|
||||
@@ -249,7 +266,8 @@ static void iomap_adjust_read_range(struct inode *inode, struct folio *folio,
|
||||
unsigned end = offset_in_folio(folio, isize - 1) >> block_bits;
|
||||
|
||||
if (first <= end && last > end)
|
||||
plen -= (last - end) * block_size;
|
||||
plen -= iomap_bytes_to_truncate(*pos + plen, block_bits,
|
||||
last - end);
|
||||
}
|
||||
|
||||
*offp = poff;
|
||||
|
||||
Reference in New Issue
Block a user