Re: [PATCH] iomap: follow the alignment requirement for iomap_dio_hole_iter()
Qu Wenruo <[email protected]> Thu, 30 Jul 2026 18:06:17 +0930
| Newsgroups | org.kernel.vger.linux-btrfs,org.kernel.vger.linux-fsdevel,org.kernel.vger.linux-xfs |
|---|---|
| Message-ID | <[email protected]> |
在 2026/7/30 17:15, Christoph Hellwig 写道:
> On Thu, Jul 30, 2026 at 10:52:10AM +0930, Qu Wenruo wrote:
>> [BUG]
>> On the latest development branch, btrfs with 8K block size on 4K page
>> sized systems will fail the following fsstress workload:
>>
>> # $fsstress -n 4 -d $mnt -s 1785675805 -v
>
> Please add this to xfstests.
In that case I'll create a more dedicated reproducer.
>
>> +/*
>> + * File systems that write out of place and always allocate new blocks
>> + * need each bio to be block aligned as that's the unit of allocation.
>> + */
>> +static unsigned int iomap_dio_alignment(const struct iomap_iter *iter,
>> + const struct iomap_dio *dio)
>> +{
>> + if (dio->flags & IOMAP_DIO_FSBLOCK_ALIGNED)
>> + return i_blocksize(iter->inode);
>> + return bdev_logical_block_size(iter->iomap.bdev);
>> +}
>
> This already exists in the VFS iomap tree (with a slightly different
> prototype).
>
>> static int iomap_dio_hole_iter(struct iomap_iter *iter, struct iomap_dio *dio)
>> {
>> - loff_t length = iov_iter_zero(iomap_length(iter), dio->submit.iter);
>> + loff_t copied = iov_iter_zero(iomap_length(iter), dio->submit.iter);
>> + const unsigned int alignment = iomap_dio_alignment(iter, dio);
>> + const loff_t aligned_copied = round_down(copied, alignment);
>>
>> - dio->size += length;
>> - if (!length)
>> + iov_iter_revert(dio->submit.iter, copied - aligned_copied);
>> + dio->size += aligned_copied;
>> + if (!aligned_copied)
>> return -EFAULT;
>> - return iomap_iter_advance(iter, length);
>> + return iomap_iter_advance(iter, aligned_copied);
>> }
>
> iomap generall expects extents to be block aligned, how do you end up
> with non-aligned reporting here?
The dio read buffer is 2 pages (matching the 8K alignment), but only the
first page is faulted in.
Furthermore btrfs has disabled page fault during dio read, so the 2nd
page will not be faulted in.
Thus iov_iter_zero() only got to zero the first page.
Btrfs always returned a hole that is properly aligned, but as long as bs
> ps, the page fault can always break in the middle, causing unaligned
range.
Thanks,
Qu