Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Joanne Koong and committed by
Christian Brauner
9d875e0e a0f1cabe

+20 -2
+20 -2
fs/iomap/buffered-io.c
··· 219 219 } 220 220 221 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 + 237 + /* 222 238 * Calculate the range inside the folio that we actually need to read. 223 239 */ 224 240 static void iomap_adjust_read_range(struct inode *inode, struct folio *folio, ··· 279 263 /* truncate len if we find any trailing uptodate block(s) */ 280 264 while (++i <= last) { 281 265 if (ifs_block_is_uptodate(ifs, i)) { 282 - plen -= (last - i + 1) * block_size; 266 + plen -= iomap_bytes_to_truncate(*pos + plen, 267 + block_bits, last - i + 1); 283 268 last = i - 1; 284 269 break; 285 270 } ··· 296 279 unsigned end = offset_in_folio(folio, isize - 1) >> block_bits; 297 280 298 281 if (first <= end && last > end) 299 - plen -= (last - end) * block_size; 282 + plen -= iomap_bytes_to_truncate(*pos + plen, block_bits, 283 + last - end); 300 284 } 301 285 302 286 *offp = poff;