Re: [PATCH RFC] btrfs: implement a new compat RO feature, data_io_size

"Sun YangKai" <[email protected]> Fri, 31 Jul 2026 19:40:52 +0800
Newsgroups org.kernel.vger.linux-btrfs
Message-ID <[email protected]>
On 2026/7/22 18:03, Qu Wenruo wrote:
>=20
>=20
> =E5=9C=A8 2026/7/22 19:28, Sun YangKai =E5=86=99=E9=81=93:
>> On 2026/7/22 17:25, Qu Wenruo wrote:
>>>
>>>
>>> =E5=9C=A8 2026/7/22 18:52, Sun YangKai =E5=86=99=E9=81=93:
>>>> On 2026/6/28 14:27, Qu Wenruo wrote:
>>>>> To address the btrfs RAID56 write-hole problem, there is one idea to
>>>>> solve it:
>>>>>
>>>>> =C2=A0=C2=A0=C2=A0 Make sure all data writes are full stripe aligned
>>>>> However based on that idea, we can have two different directions to
>>>>> implement:
>>>>>
>>>>> - Keep the sector size untouched, introduce a newer io size for data
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0 E.g. sector size is still 4K, but data io si=
ze is 16K, and RAID56
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0 full stripe size is also set to 16K.
>>>>
>>>> Sorry, I cannot follow you here about "RAID56 full stripe size is also
>>>> set to 16K".
>>>
>>> Just as what it reads.
>>>
>>> Not using the fixed 64K stripe size, but per-chunk full stripe size.
>>
>> I appreciate that you'd love to explain more about this.
>>
>> But I still cannot understand how 16KiB full stripe size can fit on a 4
>> disks RAID5 for example. Currently we have 3*64KiB =3D 192KiB as full
>> stripe size for this kind of setup. But if using 16KiB full stripe size,
>> how many data on each disk and how's the logical address mapped to those
>> disks?
>=20
> Full stripe 16K, then the new RAID5F chunks will require power-of-2=20
> disks, and no more than 16K/4K disks.
>=20
> So no 4 disks RAID5F chunk in the first place.

I've got your idea and got the following 2 concerns:

1. the device count is limited to 3 or 5 device for RAID5, and 4 or 6=20
devices for RAID6, losing the flexibility currently btrfs have;

2. On each device, we will send a lot of 4KiB or 8KiB io, which might be=20
not good for performance;

So I personally don't think this is a good way to fix the write hole issue.

>>
>> Thanks,
>> Sun YangKai
>>
>>>>
>>>> Currently I think we have a 64KiB chunk on each disk, and for n disks
>>>> RAID5, we have (n-1) * 64KiB as data's full stripe size and one more
>>>> 64KiB for parity if I understand it correctly. Then how can we limit=
=20
>>>> the
>>>> full stripe size to 16K with n devices?
>>>>
>>>> 16K/(n-1) bytes on each disk is insane. Or we just limit device count
>>>> for RAID5 to a specific number like 3 disks so we can have 2 device fo=
r
>>>> data, 1 for parity and can get a 8KiB chunk on each disk?
>>>>
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0 This allows us to reuse the existing sector =
size based
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0 read-repair/scrub.
>>>>>
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0 And this patch is the PoC of this idea.
>>>>>
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0 The problems are also obvious, we need to no=
t only introduce a
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0 dedicated compat RO flag, but also convert a=
lmost all sectorsize
>>>>> users
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0 to use the new data_io_size, except data che=
cksum and read-repair
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0 related code.
>>>>>
>>>>> - Use larger block size, introduce a newer sub-block RAID56 repair
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0 E.g. sector size is 16K, and RAID56 full str=
ipe size is also=20
>>>>> set to
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0 16K.
>>>>>
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0 This allows us to reuse the existing experim=
ental bs > ps=20
>>>>> support.
>>>>>
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0 The problems are that we need a completely n=
ew RAID56 sub-block
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0 rebuild handling.
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0 And the new rebuild can be very slow. Since =
we do not know exact
>>>>> which
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0 sub-block is corrupted, we have to exhaust a=
ll combinations just
>>>>> for a
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0 single block.
>>>>>
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0 And the current btrfs_map_block() also need =
to support sub-block
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0 splitting, which is completely new, and will=
 also affect checksum
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0 handling.
>>>>>
>>>>> So far it looks like the new data io size is the easier solution, thu=
s
>>>>> here is the RFC patch.
>>>>>
>>>>> But in reality, this RFC patch is already super huge, almost touching
>>>>> all call sites using fs_info->sectorsize, and there are still a lot o=
f
>>>>> left-over and causing all kinds of warnings.
>>>>>
>>>>> For now I'm wondering if it would be better just to replace sectorsiz=
e
>>>>> with data_io_size, and introduce a dedicated member for checksum/=20
>>>>> scrub.
>>>>>
>>>>> Signed-off-by: Qu Wenruo <[email protected]>
>>>>> ---
>>>>> Reason for RFC:
>>>>> This patch is still very unstable, there are still a lot of sites not
>>>>> properly converted to use the new fs_info->data_io_size.
>>>>>
>>>>> This is only for proof-of-concept purpose.
>>>>> ---
>>>>> =C2=A0=C2=A0=C2=A0 fs/btrfs/accessors.h=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 |=C2=A0 2 +
>>>>> =C2=A0=C2=A0=C2=A0 fs/btrfs/direct-io.c=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 |=C2=A0 6 +--
>>>>> =C2=A0=C2=A0=C2=A0 fs/btrfs/disk-io.c=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 | 23 ++++++++++-
>>>>> =C2=A0=C2=A0=C2=A0 fs/btrfs/file.c=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 | 68 ++++++=
+++++++++
>>>>> +-----------------
>>>>> =C2=A0=C2=A0=C2=A0 fs/btrfs/fs.h=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 |=
=C2=A0 9 ++++-
>>>>> =C2=A0=C2=A0=C2=A0 fs/btrfs/inode.c=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 | 60 ++++++++++++=
++---------------
>>>>> =C2=A0=C2=A0=C2=A0 fs/btrfs/lzo.c=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 |=C2=A0 =
2 +-
>>>>> =C2=A0=C2=A0=C2=A0 fs/btrfs/sysfs.c=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 |=C2=A0 2 +
>>>>> =C2=A0=C2=A0=C2=A0 fs/btrfs/tests/btrfs-tests.c=C2=A0=C2=A0=C2=A0 |=
=C2=A0 1 +
>>>>> =C2=A0=C2=A0=C2=A0 include/uapi/linux/btrfs.h=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0 |=C2=A0 7 ++++
>>>>> =C2=A0=C2=A0=C2=A0 include/uapi/linux/btrfs_tree.h |=C2=A0 3 +-
>>>>> =C2=A0=C2=A0=C2=A0 11 files changed, 112 insertions(+), 71 deletions(=
-)
>>>>>
>>>>> diff --git a/fs/btrfs/accessors.h b/fs/btrfs/accessors.h
>>>>> index 8938357fcb40..7a5206db2224 100644
>>>>> --- a/fs/btrfs/accessors.h
>>>>> +++ b/fs/btrfs/accessors.h
>>>>> @@ -889,6 +889,8 @@
>>>>> BTRFS_SETGET_STACK_FUNCS(super_remap_root_generation, struct
>>>>> btrfs_super_block,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0 remap_root_generation, 64);
>>>>> =C2=A0=C2=A0=C2=A0 BTRFS_SETGET_STACK_FUNCS(super_remap_root_level, s=
truct
>>>>> btrfs_super_block,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0 remap_root_level, 8);
>>>>> +BTRFS_SETGET_STACK_FUNCS(super_data_io_size, struct=20
>>>>> btrfs_super_block,
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0 data_io_size, 32);
>>>>> =C2=A0=C2=A0=C2=A0 /* struct btrfs_file_extent_item */
>>>>> =C2=A0=C2=A0=C2=A0 BTRFS_SETGET_STACK_FUNCS(stack_file_extent_type, s=
truct
>>>>> btrfs_file_extent_item,
>>>>> diff --git a/fs/btrfs/direct-io.c b/fs/btrfs/direct-io.c
>>>>> index 3e227292b0ac..df1b2f2725ca 100644
>>>>> --- a/fs/btrfs/direct-io.c
>>>>> +++ b/fs/btrfs/direct-io.c
>>>>> @@ -186,7 +186,7 @@ static struct extent_map
>>>>> *btrfs_new_extent_direct(struct btrfs_inode *inode,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 alloc_hint =3D btrfs_get_e=
xtent_allocation_hint(inode, start,=20
>>>>> len);
>>>>> =C2=A0=C2=A0=C2=A0 again:
>>>>> -=C2=A0=C2=A0=C2=A0 ret =3D btrfs_reserve_extent(root, len, len, fs_i=
nfo->sectorsize,
>>>>> +=C2=A0=C2=A0=C2=A0 ret =3D btrfs_reserve_extent(root, len, len, fs_i=
nfo->data_io_size,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 0, alloc_hi=
nt, &ins, true, true);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (ret =3D=3D -EAGAIN) {
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 AS=
SERT(btrfs_is_zoned(fs_info));
>>>>> @@ -395,7 +395,7 @@ static int btrfs_dio_iomap_begin(struct inode
>>>>> *inode, loff_t start,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 * to allocate a cont=
iguous array for the checksums.
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 */
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (!write)
>>>>> -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 len =3D min_t(u64, len, f=
s_info->sectorsize * BIO_MAX_VECS);
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 len =3D min_t(u64, len, f=
s_info->data_io_size * BIO_MAX_VECS);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 lockstart =3D start;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 lockend =3D start + len - =
1;
>>>>> @@ -829,7 +829,7 @@ static struct iomap_dio *btrfs_dio_write(struct
>>>>> kiocb *iocb, struct iov_iter *it
>>>>> =C2=A0=C2=A0=C2=A0 static ssize_t check_direct_IO(struct btrfs_fs_inf=
o *fs_info,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 const struc=
t iov_iter *iter, loff_t offset)
>>>>> =C2=A0=C2=A0=C2=A0 {
>>>>> -=C2=A0=C2=A0=C2=A0 const u32 blocksize_mask =3D fs_info->sectorsize =
- 1;
>>>>> +=C2=A0=C2=A0=C2=A0 const u32 blocksize_mask =3D fs_info->data_io_siz=
e - 1;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (offset & blocksize_mas=
k)
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 re=
turn -EINVAL;
>>>>> diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
>>>>> index e4ffcd49d7af..29797b767df7 100644
>>>>> --- a/fs/btrfs/disk-io.c
>>>>> +++ b/fs/btrfs/disk-io.c
>>>>> @@ -2508,6 +2508,23 @@ int btrfs_validate_super(const struct
>>>>> btrfs_fs_info *fs_info,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 re=
t =3D -EINVAL;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }
>>>>> +=C2=A0=C2=A0=C2=A0 if (btrfs_fs_compat_ro(fs_info, DATA_IO_SIZE)) {
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 const u32 data_io_size =
=3D btrfs_super_data_io_size(sb);
>>>>> +
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /*
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 * If data io size i=
s set, make sure it is not smaller than
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 * sectorsize.
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 * And for now we on=
ly support data io size up to
>>>>> MAX_BLOCKSIZE.
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 */
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (unlikely(!is_power_of=
_2(data_io_size) ||
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 data_io_size < sectorsize ||
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 data_io_size > BTRFS_MAX_BLOCKSIZE)) {
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 b=
trfs_err(fs_info,
>>>>> +=C2=A0=C2=A0=C2=A0 "invalid data io size, has %u expect power of 2 n=
umber in range
>>>>> [%u, %u]",
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 data_io_size, sectorsize, BTRFS_MAX_BL=
OCKSIZE);
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 r=
et =3D -EINVAL;
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }
>>>>> +=C2=A0=C2=A0=C2=A0 }
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (btrfs_fs_incompat(fs_i=
nfo, REMAP_TREE)) {
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /*
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 * Reduce test matrix for remap tree by requiring block-
>>>>> group-tree
>>>>> @@ -3472,8 +3489,12 @@ int __cold open_ctree(struct super_block *sb,
>>>>> struct btrfs_fs_devices *fs_device
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 fs_info->nodesize =3D node=
size;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 fs_info->nodesize_bits =3D=
 ilog2(nodesize);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 fs_info->sectorsize =3D se=
ctorsize;
>>>>> +=C2=A0=C2=A0=C2=A0 if (btrfs_fs_compat_ro(fs_info, DATA_IO_SIZE))
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 fs_info->data_io_size =3D=
 btrfs_super_data_io_size(disk_super);
>>>>> +=C2=A0=C2=A0=C2=A0 else
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 fs_info->data_io_size =3D=
 sectorsize;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 fs_info->sectorsize_bits =
=3D ilog2(sectorsize);
>>>>> -=C2=A0=C2=A0=C2=A0 fs_info->block_min_order =3D ilog2(round_up(secto=
rsize, PAGE_SIZE)
>>>>>>> PAGE_SHIFT);
>>>>> +=C2=A0=C2=A0=C2=A0 fs_info->block_min_order =3D ilog2(round_up(fs_in=
fo->data_io_size,
>>>>> PAGE_SIZE) >> PAGE_SHIFT);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 fs_info->block_max_order =
=3D calc_block_max_order(fs_info-
>>>>>> sectorsize_bits);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 fs_info->csums_per_leaf =
=3D BTRFS_MAX_ITEM_SIZE(fs_info) /
>>>>> fs_info->csum_size;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 fs_info->fs_devices->fs_in=
fo =3D fs_info;
>>>>> diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
>>>>> index df8f6f565070..8397d96a5992 100644
>>>>> --- a/fs/btrfs/file.c
>>>>> +++ b/fs/btrfs/file.c
>>>>> @@ -45,8 +45,8 @@
>>>>> =C2=A0=C2=A0=C2=A0 static void btrfs_drop_folio(struct btrfs_fs_info =
*fs_info, struct
>>>>> folio *folio,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 u64 pos, u64 copied)
>>>>> =C2=A0=C2=A0=C2=A0 {
>>>>> -=C2=A0=C2=A0=C2=A0 u64 block_start =3D round_down(pos, fs_info->sect=
orsize);
>>>>> -=C2=A0=C2=A0=C2=A0 u64 block_len =3D round_up(pos + copied, fs_info-=
>sectorsize) -
>>>>> block_start;
>>>>> +=C2=A0=C2=A0=C2=A0 u64 block_start =3D round_down(pos, fs_info->data=
_io_size);
>>>>> +=C2=A0=C2=A0=C2=A0 u64 block_len =3D round_up(pos + copied, fs_info-=
>data_io_size) -
>>>>> block_start;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ASSERT(block_len <=3D U32_=
MAX);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 folio_unlock(folio);
>>>>> @@ -78,8 +78,8 @@ int btrfs_dirty_folio(struct btrfs_inode *inode,
>>>>> struct folio *folio, loff_t pos
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (noreserve)
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ex=
tra_bits |=3D EXTENT_NORESERVE;
>>>>> -=C2=A0=C2=A0=C2=A0 start_pos =3D round_down(pos, fs_info->sectorsize=
);
>>>>> -=C2=A0=C2=A0=C2=A0 num_bytes =3D round_up(end_pos - start_pos, fs_in=
fo->sectorsize);
>>>>> +=C2=A0=C2=A0=C2=A0 start_pos =3D round_down(pos, fs_info->data_io_si=
ze);
>>>>> +=C2=A0=C2=A0=C2=A0 num_bytes =3D round_up(end_pos - start_pos, fs_in=
fo->data_io_size);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ASSERT(num_bytes <=3D U32_=
MAX);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ASSERT(folio_pos(folio) <=
=3D pos && folio_next_pos(folio) >=3D
>>>>> end_pos);
>>>>> @@ -395,7 +395,7 @@ int btrfs_drop_extents(struct btrfs_trans_handle
>>>>> *trans,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 extent_type =3D=3D BTRFS_FILE=
_EXTENT_INLINE) {
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 args->bytes_found +=3D extent=
_end - key.offset;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 extent_end =3D ALIGN(extent_e=
nd,
>>>>> -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 fs_info->sectorsize);
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0 fs_info->data_io_size);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 } else if (update_refs && disk_bytenr > 0) {
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct btrfs_ref ref =3D {
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 .acti=
on =3D BTRFS_DROP_DELAYED_REF,
>>>>> @@ -788,7 +788,7 @@ static int prepare_uptodate_folio(struct inode
>>>>> *inode, struct folio *folio, u64
>>>>> =C2=A0=C2=A0=C2=A0 {
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 u64 clamp_start =3D max_t(=
u64, pos, folio_pos(folio));
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 u64 clamp_end =3D min_t(u6=
4, pos + len, folio_next_pos(folio));
>>>>> -=C2=A0=C2=A0=C2=A0 const u32 blocksize =3D inode_to_fs_info(inode)->=
sectorsize;
>>>>> +=C2=A0=C2=A0=C2=A0 const u32 blocksize =3D inode_to_fs_info(inode)->=
data_io_size;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 int ret =3D 0;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (folio_test_uptodate(fo=
lio))
>>>>> @@ -893,8 +893,8 @@ lock_and_cleanup_extent_if_need(struct
>>>>> btrfs_inode *inode, struct folio *folio,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 u64 last_pos;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 int ret =3D 0;
>>>>> -=C2=A0=C2=A0=C2=A0 start_pos =3D round_down(pos, fs_info->sectorsize=
);
>>>>> -=C2=A0=C2=A0=C2=A0 last_pos =3D round_up(pos + write_bytes, fs_info-=
>sectorsize) - 1;
>>>>> +=C2=A0=C2=A0=C2=A0 start_pos =3D round_down(pos, fs_info->data_io_si=
ze);
>>>>> +=C2=A0=C2=A0=C2=A0 last_pos =3D round_up(pos + write_bytes, fs_info-=
>data_io_size)=20
>>>>> - 1;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (start_pos < inode->vfs=
_inode.i_size) {
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 st=
ruct btrfs_ordered_extent *ordered;
>>>>> @@ -978,9 +978,9 @@ int btrfs_check_nocow_lock(struct btrfs_inode
>>>>> *inode, loff_t pos,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (!btrfs_drew_try_write_=
lock(&root->snapshot_lock))
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 re=
turn -EAGAIN;
>>>>> -=C2=A0=C2=A0=C2=A0 lockstart =3D round_down(pos, fs_info->sectorsize=
);
>>>>> +=C2=A0=C2=A0=C2=A0 lockstart =3D round_down(pos, fs_info->data_io_si=
ze);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 lockend =3D round_up(pos +=
 *write_bytes,
>>>>> -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0 fs_info->sectorsize) - 1;
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0 fs_info->data_io_size) - 1;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (nowait) {
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if=
 (!btrfs_try_lock_ordered_range(inode, lockstart,=20
>>>>> lockend,
>>>>> @@ -1067,7 +1067,7 @@ int btrfs_write_check(struct kiocb *iocb,
>>>>> size_t count)
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 oldsize =3D i_size_read(in=
ode);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (pos > oldsize) {
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /*=
 Expand hole size to cover write data, preventing empty
>>>>> gap */
>>>>> -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 loff_t end_pos =3D round_=
up(pos + count, fs_info->sectorsize);
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 loff_t end_pos =3D round_=
up(pos + count, fs_info-=20
>>>>> >data_io_size);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 re=
t =3D btrfs_cont_expand(BTRFS_I(inode), oldsize, end_pos);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if=
 (ret)
>>>>> @@ -1090,7 +1090,7 @@ static void release_space(struct btrfs_inode
>>>>> *inode, struct extent_changeset *da
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 co=
nst struct btrfs_fs_info *fs_info =3D inode->root-=20
>>>>> >fs_info;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 bt=
rfs_delalloc_release_space(inode, data_reserved,
>>>>> -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 round_down(start, fs_info->sectorsize),
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 round_down(start, fs_info->data_io_size),
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0 len, true);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }
>>>>> =C2=A0=C2=A0=C2=A0 }
>>>>> @@ -1107,7 +1107,7 @@ static ssize_t reserve_space(struct btrfs_inode
>>>>> *inode,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 bool *only_release_meta=
data)
>>>>> =C2=A0=C2=A0=C2=A0 {
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 const struct btrfs_fs_info=
 *fs_info =3D inode->root->fs_info;
>>>>> -=C2=A0=C2=A0=C2=A0 const unsigned int block_offset =3D (start & (fs_=
info->sectorsize
>>>>> - 1));
>>>>> +=C2=A0=C2=A0=C2=A0 const unsigned int block_offset =3D (start & (fs_=
info-
>>>>>> data_io_size - 1));
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 size_t reserve_bytes;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 int ret;
>>>>> @@ -1132,7 +1132,7 @@ static ssize_t reserve_space(struct btrfs_inode
>>>>> *inode,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 *o=
nly_release_metadata =3D true;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }
>>>>> -=C2=A0=C2=A0=C2=A0 reserve_bytes =3D round_up(*len + block_offset, f=
s_info-=20
>>>>> >sectorsize);
>>>>> +=C2=A0=C2=A0=C2=A0 reserve_bytes =3D round_up(*len + block_offset, f=
s_info-
>>>>>> data_io_size);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 WARN_ON(reserve_bytes =3D=
=3D 0);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ret =3D btrfs_delalloc_res=
erve_metadata(inode, reserve_bytes,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 reserve_bytes, nowait);
>>>>> @@ -1192,7 +1192,7 @@ static int copy_one_range(struct btrfs_inode
>>>>> *inode, struct iov_iter *iter,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct extent_state *cache=
d_state =3D NULL;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 size_t write_bytes =3D cal=
c_write_bytes(inode, iter, start);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 size_t copied;
>>>>> -=C2=A0=C2=A0=C2=A0 const u64 reserved_start =3D round_down(start, fs=
_info-=20
>>>>> >sectorsize);
>>>>> +=C2=A0=C2=A0=C2=A0 const u64 reserved_start =3D round_down(start, fs=
_info-
>>>>>> data_io_size);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 u64 reserved_len;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct folio *folio =3D NU=
LL;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 int extents_locked;
>>>>> @@ -1301,7 +1301,7 @@ static int copy_one_range(struct btrfs_inode
>>>>> *inode, struct iov_iter *iter,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /*=
 Release the reserved space beyond the last block. */
>>>>> -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 last_block =3D round_up(s=
tart + copied, fs_info->sectorsize);
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 last_block =3D round_up(s=
tart + copied, fs_info->data_io_size);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 sh=
rink_reserved_space(inode, *data_reserved,=20
>>>>> reserved_start,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0 reserved_len, last_block - reserved_start,
>>>>> @@ -1938,7 +1938,7 @@ static vm_fault_t btrfs_page_mkwrite(struct
>>>>> vm_fault *vmf)
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (folio_contains(folio, =
(size - 1) >> PAGE_SHIFT)) {
>>>>> -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 reserved_space =3D round_=
up(size - page_start, fs_info-
>>>>>> sectorsize);
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 reserved_space =3D round_=
up(size - page_start, fs_info-
>>>>>> data_io_size);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if=
 (reserved_space < fsize) {
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 const u64 to_free =3D fsize - reserved_space;
>>>>> @@ -2182,8 +2182,8 @@ static int find_first_non_hole(struct
>>>>> btrfs_inode *inode, u64 *start, u64 *len)
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 int ret =3D 0;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 em =3D btrfs_get_extent(in=
ode, NULL,
>>>>> -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 round_down(*start, fs_info->sectorsize=
),
>>>>> -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 round_up(*len, fs_info->sectorsize));
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 round_down(*start, fs_info->data_io_si=
ze),
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 round_up(*len, fs_info->data_io_size))=
;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (IS_ERR(em))
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 re=
turn PTR_ERR(em);
>>>>> @@ -2396,7 +2396,7 @@ int btrfs_replace_file_extents(struct
>>>>> btrfs_inode *inode,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct btrfs_root *root =
=3D inode->root;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct btrfs_fs_info *fs_i=
nfo =3D root->fs_info;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 const u64 min_size =3D=20
>>>>> btrfs_calc_insert_metadata_size(fs_info, 1);
>>>>> -=C2=A0=C2=A0=C2=A0 u64 ino_size =3D round_up(inode->vfs_inode.i_size=
, fs_info-
>>>>>> sectorsize);
>>>>> +=C2=A0=C2=A0=C2=A0 u64 ino_size =3D round_up(inode->vfs_inode.i_size=
, fs_info-
>>>>>> data_io_size);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct btrfs_trans_handle =
*trans =3D NULL;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct btrfs_block_rsv rsv=
;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 unsigned int rsv_count;
>>>>> @@ -2667,7 +2667,7 @@ static int btrfs_punch_hole(struct file *file,
>>>>> loff_t offset, loff_t len)
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (ret)
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 go=
to out_only_mutex;
>>>>> -=C2=A0=C2=A0=C2=A0 ino_size =3D round_up(inode->i_size, fs_info->sec=
torsize);
>>>>> +=C2=A0=C2=A0=C2=A0 ino_size =3D round_up(inode->i_size, fs_info->dat=
a_io_size);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ret =3D find_first_non_hol=
e(BTRFS_I(inode), &offset, &len);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (ret < 0)
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 go=
to out_only_mutex;
>>>>> @@ -2681,15 +2681,15 @@ static int btrfs_punch_hole(struct file
>>>>> *file, loff_t offset, loff_t len)
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (ret)
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 go=
to out_only_mutex;
>>>>> -=C2=A0=C2=A0=C2=A0 lockstart =3D round_up(offset, fs_info->sectorsiz=
e);
>>>>> -=C2=A0=C2=A0=C2=A0 lockend =3D round_down(offset + len, fs_info->sec=
torsize) - 1;
>>>>> +=C2=A0=C2=A0=C2=A0 lockstart =3D round_up(offset, fs_info->data_io_s=
ize);
>>>>> +=C2=A0=C2=A0=C2=A0 lockend =3D round_down(offset + len, fs_info->dat=
a_io_size) - 1;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 same_block =3D (BTRFS_BYTE=
S_TO_BLKS(fs_info, offset))
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 =
=3D=3D (BTRFS_BYTES_TO_BLKS(fs_info, offset + len - 1));
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /*
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 * Only do this if we=
 are in the same block and we aren't
>>>>> doing the
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 * entire block.
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 */
>>>>> -=C2=A0=C2=A0=C2=A0 if (same_block && len < fs_info->sectorsize) {
>>>>> +=C2=A0=C2=A0=C2=A0 if (same_block && len < fs_info->data_io_size) {
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if=
 (offset < ino_size) {
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 truncated_block =3D true;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 ret =3D btrfs_truncate_block(BTRFS_I(inode), offset +
>>>>> len - 1,
>>>>> @@ -2858,8 +2858,8 @@ static int btrfs_fallocate_update_isize(struct
>>>>> inode *inode,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (mode & FALLOC_FL_KEEP_=
SIZE || end <=3D i_size_read(inode))
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 re=
turn 0;
>>>>> -=C2=A0=C2=A0=C2=A0 range_start =3D round_down(i_size_read(inode), ro=
ot->fs_info-
>>>>>> sectorsize);
>>>>> -=C2=A0=C2=A0=C2=A0 range_end =3D round_up(end, root->fs_info->sector=
size);
>>>>> +=C2=A0=C2=A0=C2=A0 range_start =3D round_down(i_size_read(inode), ro=
ot->fs_info-
>>>>>> data_io_size);
>>>>> +=C2=A0=C2=A0=C2=A0 range_end =3D round_up(end, root->fs_info->data_i=
o_size);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ret =3D btrfs_inode_set_fi=
le_extent_range(BTRFS_I(inode),
>>>>> range_start,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0 range_end - range_start);
>>>>> @@ -2889,7 +2889,7 @@ static int
>>>>> btrfs_zero_range_check_range_boundary(struct btrfs_inode *inode,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0 u64 offset)
>>>>> =C2=A0=C2=A0=C2=A0 {
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct extent_map *em;
>>>>> -=C2=A0=C2=A0=C2=A0 const u32 sectorsize =3D inode->root->fs_info->se=
ctorsize;
>>>>> +=C2=A0=C2=A0=C2=A0 const u32 sectorsize =3D inode->root->fs_info->da=
ta_io_size;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 int ret;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 offset =3D round_down(offs=
et, sectorsize);
>>>>> @@ -2916,7 +2916,7 @@ static int btrfs_zero_range(struct inode *inode=
,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct btrfs_fs_info *fs_i=
nfo =3D BTRFS_I(inode)->root->fs_info;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct extent_map *em;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct extent_changeset *d=
ata_reserved =3D NULL;
>>>>> -=C2=A0=C2=A0=C2=A0 const u32 sectorsize =3D fs_info->sectorsize;
>>>>> +=C2=A0=C2=A0=C2=A0 const u32 sectorsize =3D fs_info->data_io_size;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 int ret;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 u64 alloc_hint =3D 0;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 const u64 orig_start =3D o=
ffset;
>>>>> @@ -3065,7 +3065,7 @@ static int btrfs_zero_range(struct inode *inode=
,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 re=
t =3D btrfs_prealloc_file_range(inode, mode, alloc_start,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0 alloc_end - alloc_start,
>>>>> -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 fs=
_info->sectorsize,
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 fs=
_info->data_io_size,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0 offset + len, &alloc_hint);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 bt=
rfs_unlock_extent(&BTRFS_I(inode)->io_tree, lockstart,
>>>>> lockend,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 &cach=
ed_state);
>>>>> @@ -3105,7 +3105,7 @@ static long btrfs_fallocate(struct file *file,
>>>>> int mode,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 u64 data_space_reserved =
=3D 0;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 u64 qgroup_reserved =3D 0;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct extent_map *em;
>>>>> -=C2=A0=C2=A0=C2=A0 int blocksize =3D BTRFS_I(inode)->root->fs_info->=
sectorsize;
>>>>> +=C2=A0=C2=A0=C2=A0 int blocksize =3D BTRFS_I(inode)->root->fs_info->=
data_io_size;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 int ret;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (btrfs_is_shutdown(inod=
e_to_fs_info(inode)))
>>>>> @@ -3414,7 +3414,7 @@ bool btrfs_find_delalloc_in_range(struct
>>>>> btrfs_inode *inode, u64 start, u64 end,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct extent_sta=
te **cached_state,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 u64 *delalloc_sta=
rt_ret, u64 *delalloc_end_ret)
>>>>> =C2=A0=C2=A0=C2=A0 {
>>>>> -=C2=A0=C2=A0=C2=A0 u64 cur_offset =3D round_down(start, inode->root-=
>fs_info-
>>>>>> sectorsize);
>>>>> +=C2=A0=C2=A0=C2=A0 u64 cur_offset =3D round_down(start, inode->root-=
>fs_info-
>>>>>> data_io_size);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 u64 prev_delalloc_end =3D =
0;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 bool search_io_tree =3D tr=
ue;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 bool ret =3D false;
>>>>> @@ -3602,10 +3602,10 @@ static loff_t find_desired_extent(struct file
>>>>> *file, loff_t offset, int whence)
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 */
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 start =3D max_t(loff_t, 0,=
 offset);
>>>>> -=C2=A0=C2=A0=C2=A0 lockstart =3D round_down(start, fs_info->sectorsi=
ze);
>>>>> -=C2=A0=C2=A0=C2=A0 lockend =3D round_up(i_size, fs_info->sectorsize)=
;
>>>>> +=C2=A0=C2=A0=C2=A0 lockstart =3D round_down(start, fs_info->data_io_=
size);
>>>>> +=C2=A0=C2=A0=C2=A0 lockend =3D round_up(i_size, fs_info->data_io_siz=
e);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (lockend <=3D lockstart=
)
>>>>> -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 lockend =3D lockstart + f=
s_info->sectorsize;
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 lockend =3D lockstart + f=
s_info->data_io_size;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 lockend--;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 path =3D btrfs_alloc_path(=
);
>>>>> diff --git a/fs/btrfs/fs.h b/fs/btrfs/fs.h
>>>>> index ab5ed7b4f639..cee4c772cfd9 100644
>>>>> --- a/fs/btrfs/fs.h
>>>>> +++ b/fs/btrfs/fs.h
>>>>> @@ -299,7 +299,7 @@ enum {
>>>>> =C2=A0=C2=A0=C2=A0 #define BTRFS_FEATURE_COMPAT_SAFE_SET=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 0ULL
>>>>> =C2=A0=C2=A0=C2=A0 #define BTRFS_FEATURE_COMPAT_SAFE_CLEAR=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 0ULL
>>>>> -#define BTRFS_FEATURE_COMPAT_RO_SUPP=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 \
>>>>> +#define BTRFS_FEATURE_COMPAT_RO_SUPP_STABLE=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0 \
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (BTRFS_FEATURE_COMPAT_RO_F=
REE_SPACE_TREE |=C2=A0=C2=A0=C2=A0 \
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 BTRFS_FEATURE_COMPAT=
_RO_FREE_SPACE_TREE_VALID | \
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 BTRFS_FEATURE_COMPAT=
_RO_VERITY |=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 \
>>>>> @@ -335,11 +335,17 @@ enum {
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 BTRFS_FEATURE_INCOMP=
AT_EXTENT_TREE_V2 | \
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 BTRFS_FEATURE_INCOMP=
AT_REMAP_TREE)
>>>>> +#define BTRFS_FEATURE_COMPAT_RO_SUPP=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0 \
>>>>> +=C2=A0=C2=A0=C2=A0 (BTRFS_FEATURE_COMPAT_RO_SUPP_STABLE |=C2=A0=C2=
=A0=C2=A0 \
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0 BTRFS_FEATURE_COMPAT_RO_DATA_IO_SIZE)
>>>>> =C2=A0=C2=A0=C2=A0 #else
>>>>> =C2=A0=C2=A0=C2=A0 #define BTRFS_FEATURE_INCOMPAT_SUPP=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0 \
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (BTRFS_FEATURE_INCOMPAT_SU=
PP_STABLE)
>>>>> +#define BTRFS_FEATURE_COMPAT_RO_SUPP=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0 \
>>>>> +=C2=A0=C2=A0=C2=A0 (BTRFS_FEATURE_COMPAT_RO_SUPP_STABLE)
>>>>> +
>>>>> =C2=A0=C2=A0=C2=A0 #endif
>>>>> =C2=A0=C2=A0=C2=A0 #define BTRFS_FEATURE_INCOMPAT_SAFE_SET=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 \
>>>>> @@ -892,6 +898,7 @@ struct btrfs_fs_info {
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 u32 csum_size;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 u32 csums_per_leaf;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 u32 csum_type;
>>>>> +=C2=A0=C2=A0=C2=A0 u32 data_io_size;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /*
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 * Maximum size of an=
 extent. BTRFS_MAX_EXTENT_SIZE on regular
>>>>> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
>>>>> index b696dd329fd7..de0364ce950b 100644
>>>>> --- a/fs/btrfs/inode.c
>>>>> +++ b/fs/btrfs/inode.c
>>>>> @@ -190,7 +190,7 @@ static int data_reloc_print_warning_inode(u64
>>>>> inum, u64 offset, u64 num_bytes,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 bt=
rfs_warn(fs_info,
>>>>> =C2=A0=C2=A0=C2=A0 "checksum error at logical %llu mirror %u root %ll=
u inode %llu
>>>>> offset %llu length %u links %u (path: %s)",
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 warn->logical, warn->mirror_num, ro=
ot, inum,=20
>>>>> offset,
>>>>> -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0 fs_info->sectorsize, nlink,
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0 fs_info->data_io_size, nlink,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (char *)(unsigned long)ipath->fspat=
h->val[i]);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }
>>>>> @@ -1397,7 +1397,7 @@ static noinline int cow_file_range(struct
>>>>> btrfs_inode *inode,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (btrfs_is_data_reloc_ro=
ot(root))
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 mi=
n_alloc_size =3D num_bytes;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 else
>>>>> -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 min_alloc_size =3D fs_inf=
o->sectorsize;
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 min_alloc_size =3D fs_inf=
o->data_io_size;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 while (num_bytes > 0) {
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 re=
t =3D cow_one_range(inode, locked_folio, &ins, &cached,
>>>>> start,
>>>>> @@ -2783,7 +2783,7 @@ int btrfs_set_extent_delalloc(struct
>>>>> btrfs_inode *inode, u64 start, u64 end,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 unsigned int extr=
a_bits,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct extent_sta=
te **cached_state)
>>>>> =C2=A0=C2=A0=C2=A0 {
>>>>> -=C2=A0=C2=A0=C2=A0 const u32 blocksize =3D inode->root->fs_info->sec=
torsize;
>>>>> +=C2=A0=C2=A0=C2=A0 const u32 blocksize =3D inode->root->fs_info->dat=
a_io_size;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /* Basic alignment check. =
*/
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ASSERT(IS_ALIGNED(start, b=
locksize), "start=3D%llu=20
>>>>> blocksize=3D%u",
>>>>> @@ -2820,7 +2820,7 @@ int btrfs_set_extent_delalloc(struct
>>>>> btrfs_inode *inode, u64 start, u64 end,
>>>>> =C2=A0=C2=A0=C2=A0 int btrfs_reset_extent_delalloc(struct btrfs_inode=
 *inode, u64
>>>>> start, u64 end,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 unsigned int extra_bits, stru=
ct extent_state
>>>>> **cached_state)
>>>>> =C2=A0=C2=A0=C2=A0 {
>>>>> -=C2=A0=C2=A0=C2=A0 const u32 blocksize =3D inode->root->fs_info->sec=
torsize;
>>>>> +=C2=A0=C2=A0=C2=A0 const u32 blocksize =3D inode->root->fs_info->dat=
a_io_size;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /* The @extra_bits can onl=
y be EXTENT_NORESERVE for now. */
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ASSERT(!(extra_bits & ~EXT=
ENT_NORESERVE), "extra_bits=3D0x%x",
>>>>> extra_bits);
>>>>> @@ -2874,7 +2874,7 @@ static int insert_reserved_file_extent(struct
>>>>> btrfs_trans_handle *trans,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 u64 num_bytes =3D btrfs_st=
ack_file_extent_num_bytes(stack_fi);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 u64 ram_bytes =3D btrfs_st=
ack_file_extent_ram_bytes(stack_fi);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct btrfs_drop_extents_=
args drop_args =3D { 0 };
>>>>> -=C2=A0=C2=A0=C2=A0 const u32 sectorsize =3D root->fs_info->sectorsiz=
e;
>>>>> +=C2=A0=C2=A0=C2=A0 const u32 sectorsize =3D root->fs_info->data_io_s=
ize;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 int ret;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 path =3D btrfs_alloc_path(=
);
>>>>> @@ -4040,7 +4040,7 @@ static int btrfs_read_locked_inode(struct
>>>>> btrfs_inode *inode, struct btrfs_path
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (ret)
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 go=
to out;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 btrfs_inode_set_file_exten=
t_range(inode, 0,
>>>>> -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0 round_up(i_size_read(vfs_inode), fs_info->sectorsize));
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0 round_up(i_size_read(vfs_inode), fs_info-=20
>>>>> >data_io_size));
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (!maybe_acls)
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ca=
che_no_acl(vfs_inode);
>>>>> @@ -4879,7 +4879,7 @@ int btrfs_truncate_block(struct btrfs_inode
>>>>> *inode, u64 offset, u64 start, u64 e
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct extent_state *cache=
d_state =3D NULL;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct extent_changeset *d=
ata_reserved =3D NULL;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 bool only_release_metadata=
 =3D false;
>>>>> -=C2=A0=C2=A0=C2=A0 u32 blocksize =3D fs_info->sectorsize;
>>>>> +=C2=A0=C2=A0=C2=A0 u32 blocksize =3D fs_info->data_io_size;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 pgoff_t index =3D (offset =
>> PAGE_SHIFT);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct folio *folio;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 gfp_t mask =3D btrfs_alloc=
_write_mask(mapping);
>>>>> @@ -5117,8 +5117,8 @@ int btrfs_cont_expand(struct btrfs_inode
>>>>> *inode, loff_t oldsize, loff_t size)
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct extent_io_tree *io_=
tree =3D &inode->io_tree;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct extent_map *em =3D =
NULL;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct extent_state *cache=
d_state =3D NULL;
>>>>> -=C2=A0=C2=A0=C2=A0 u64 hole_start =3D ALIGN(oldsize, fs_info->sector=
size);
>>>>> -=C2=A0=C2=A0=C2=A0 u64 block_end =3D ALIGN(size, fs_info->sectorsize=
);
>>>>> +=C2=A0=C2=A0=C2=A0 u64 hole_start =3D ALIGN(oldsize, fs_info->data_i=
o_size);
>>>>> +=C2=A0=C2=A0=C2=A0 u64 block_end =3D ALIGN(size, fs_info->data_io_si=
ze);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 u64 last_byte;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 u64 cur_offset;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 u64 hole_size;
>>>>> @@ -5147,7 +5147,7 @@ int btrfs_cont_expand(struct btrfs_inode
>>>>> *inode, loff_t oldsize, loff_t size)
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 break;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 la=
st_byte =3D min(btrfs_extent_map_end(em), block_end);
>>>>> -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 last_byte =3D ALIGN(last_=
byte, fs_info->sectorsize);
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 last_byte =3D ALIGN(last_=
byte, fs_info->data_io_size);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ho=
le_size =3D last_byte - cur_offset;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if=
 (!(em->flags & EXTENT_FLAG_PREALLOC)) {
>>>>> @@ -5253,7 +5253,7 @@ static int btrfs_setsize(struct inode *inode,
>>>>> struct iattr *attr)
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if=
 (btrfs_is_zoned(fs_info)) {
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 ret =3D btrfs_wait_ordered_range(BTRFS_I(inode),
>>>>> -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ALIGN(newsize, fs_info->se=
ctorsize),
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ALIGN(newsize, fs_info->da=
ta_io_size),
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 (u64)=
-1);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 if (ret)
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 return ret;
>>>>> @@ -7323,7 +7323,7 @@ noinline int can_nocow_extent(struct
>>>>> btrfs_inode *inode, u64 offset, u64 *len,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 u6=
4 range_end;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 ra=
nge_end =3D round_up(offset +
>>>>> nocow_args.file_extent.num_bytes,
>>>>> -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 root->fs_info->secto=
rsize) - 1;
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 root->fs_info->data_=
io_size) - 1;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 re=
t =3D btrfs_test_range_bit_exists(io_tree, offset,=20
>>>>> range_end,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 EXTENT_DELALLOC);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if=
 (ret)
>>>>> @@ -7653,8 +7653,8 @@ static int btrfs_truncate(struct btrfs_inode
>>>>> *inode, bool skip_writeback)
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 int ret;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct btrfs_trans_handle =
*trans;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 const u64 min_size =3D btr=
fs_calc_metadata_size(fs_info, 1);
>>>>> -=C2=A0=C2=A0=C2=A0 const u64 lock_start =3D round_down(inode->vfs_in=
ode.i_size,
>>>>> fs_info->sectorsize);
>>>>> -=C2=A0=C2=A0=C2=A0 const u64 i_size_up =3D round_up(inode->vfs_inode=
.i_size, fs_info-
>>>>>> sectorsize);
>>>>> +=C2=A0=C2=A0=C2=A0 const u64 lock_start =3D round_down(inode->vfs_in=
ode.i_size,
>>>>> fs_info->data_io_size);
>>>>> +=C2=A0=C2=A0=C2=A0 const u64 i_size_up =3D round_up(inode->vfs_inode=
.i_size, fs_info-
>>>>>> data_io_size);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /* Our inode is locked and=
 the i_size can't be changed
>>>>> concurrently. */
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 btrfs_assert_inode_locked(=
inode);
>>>>> @@ -8038,7 +8038,7 @@ static int btrfs_getattr(struct mnt_idmap=20
>>>>> *idmap,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 u64 delalloc_bytes;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 u64 inode_bytes;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct inode *inode =3D d_=
inode(path->dentry);
>>>>> -=C2=A0=C2=A0=C2=A0 u32 blocksize =3D btrfs_sb(inode->i_sb)->sectorsi=
ze;
>>>>> +=C2=A0=C2=A0=C2=A0 u32 blocksize =3D btrfs_sb(inode->i_sb)->data_io_=
size;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 u32 bi_flags =3D BTRFS_I(i=
node)->flags;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 u32 bi_ro_flags =3D BTRFS_=
I(inode)->ro_flags;
>>>>> @@ -9124,8 +9124,8 @@ static int __btrfs_prealloc_file_range(struct
>>>>> inode *inode, int mode,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0 * to truncate disk_i_size to the start of the g=
ap,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0 * making the persisted size smaller than i_size=
.
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0 */
>>>>> -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 r=
ange_start =3D round_down(inode->i_size, fs_info-
>>>>>> sectorsize);
>>>>> -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 r=
ange_end =3D round_up(i_size, fs_info->sectorsize);
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 r=
ange_start =3D round_down(inode->i_size, fs_info-
>>>>>> data_io_size);
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 r=
ange_end =3D round_up(i_size, fs_info->data_io_size);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 ret =3D=20
>>>>> btrfs_inode_set_file_extent_range(BTRFS_I(inode),
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 range=
_start, range_end - range_start);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 if (ret) {
>>>>> @@ -9272,10 +9272,10 @@ int
>>>>> btrfs_encoded_io_compression_from_extent(struct btrfs_fs_info=20
>>>>> *fs_info,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 * The LZO format depends on the sector size. 64K is the
>>>>> maximum
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 * sector size that we support.
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0 */
>>>>> -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (fs_info->sectorsize <=
 SZ_4K || fs_info->sectorsize >
>>>>> SZ_64K)
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (fs_info->data_io_size=
 < SZ_4K || fs_info->data_io_size >
>>>>> SZ_64K)
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 return -EINVAL;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 re=
turn BTRFS_ENCODED_IO_COMPRESSION_LZO_4K +
>>>>> -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0 (fs_info->sectorsize_bits - 12);
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0 (ilog2(fs_info->data_io_size) - 12);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 case BTRFS_COMPRESS_ZSTD:
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 re=
turn BTRFS_ENCODED_IO_COMPRESSION_ZSTD;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 default:
>>>>> @@ -9563,7 +9563,7 @@ ssize_t btrfs_encoded_read(struct kiocb *iocb,
>>>>> struct iov_iter *iter,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 bt=
rfs_inode_unlock(inode, BTRFS_ILOCK_SHARED);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 re=
turn 0;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }
>>>>> -=C2=A0=C2=A0=C2=A0 start =3D ALIGN_DOWN(iocb->ki_pos, fs_info->secto=
rsize);
>>>>> +=C2=A0=C2=A0=C2=A0 start =3D ALIGN_DOWN(iocb->ki_pos, fs_info->data_=
io_size);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /*
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 * We don't know how =
long the extent containing iocb->ki_pos
>>>>> is, but if
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 * it's compressed we=
 know that it won't be longer than this.
>>>>> @@ -9676,7 +9676,7 @@ ssize_t btrfs_encoded_read(struct kiocb *iocb,
>>>>> struct iov_iter *iter,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 co=
unt =3D start + *disk_io_size - iocb->ki_pos;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 en=
coded->len =3D count;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 en=
coded->unencoded_len =3D count;
>>>>> -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 *disk_io_size =3D ALIGN(*=
disk_io_size, fs_info->sectorsize);
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 *disk_io_size =3D ALIGN(*=
disk_io_size, fs_info->data_io_size);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 }
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 btrfs_free_extent_map(em);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 em =3D NULL;
>>>>> @@ -9720,7 +9720,7 @@ ssize_t btrfs_do_encoded_write(struct kiocb
>>>>> *iocb, struct iov_iter *from,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 int compression;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 size_t orig_count;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 const u32 min_folio_size =
=3D btrfs_min_folio_size(fs_info);
>>>>> -=C2=A0=C2=A0=C2=A0 const u32 blocksize =3D fs_info->sectorsize;
>>>>> +=C2=A0=C2=A0=C2=A0 const u32 blocksize =3D fs_info->data_io_size;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 u64 start, end;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 u64 num_bytes, ram_bytes, =
disk_num_bytes;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct btrfs_key ins;
>>>>> @@ -9743,7 +9743,7 @@ ssize_t btrfs_do_encoded_write(struct kiocb
>>>>> *iocb, struct iov_iter *from,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /*=
 The sector size must match for LZO. */
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if=
 (encoded->compression -
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 BTRFS_ENCODED_IO_COMPRESSION_LZO_4K + 12 !=3D
>>>>> -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 f=
s_info->sectorsize_bits)
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 i=
log2(blocksize))
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=
=A0=C2=A0=C2=A0=C2=A0 return -EINVAL;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 co=
mpression =3D BTRFS_COMPRESS_LZO;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 br=
eak;
>>>>> @@ -9785,7 +9785,7 @@ ssize_t btrfs_do_encoded_write(struct kiocb
>>>>> *iocb, struct iov_iter *from,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /* The extent must start o=
n a sector boundary. */
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 start =3D iocb->ki_pos;
>>>>> -=C2=A0=C2=A0=C2=A0 if (!IS_ALIGNED(start, fs_info->sectorsize))
>>>>> +=C2=A0=C2=A0=C2=A0 if (!IS_ALIGNED(start, fs_info->data_io_size))
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 re=
turn -EINVAL;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /*
>>>>> @@ -9794,15 +9794,15 @@ ssize_t btrfs_do_encoded_write(struct kiocb
>>>>> *iocb, struct iov_iter *from,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 * up the extent size=
 and set i_size to the unaligned end.
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 */
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 if (start + encoded->len <=
 inode->vfs_inode.i_size &&
>>>>> -=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 !IS_ALIGNED(start + encod=
ed->len, fs_info->sectorsize))
>>>>> +=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 !IS_ALIGNED(start + encod=
ed->len, fs_info->data_io_size))
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 re=
turn -EINVAL;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /* Finally, the offset in =
the unencoded data must be sector-
>>>>> aligned. */
>>>>> -=C2=A0=C2=A0=C2=A0 if (!IS_ALIGNED(encoded->unencoded_offset, fs_inf=
o->sectorsize))
>>>>> +=C2=A0=C2=A0=C2=A0 if (!IS_ALIGNED(encoded->unencoded_offset, fs_inf=
o-=20
>>>>> >data_io_size))
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 re=
turn -EINVAL;
>>>>> -=C2=A0=C2=A0=C2=A0 num_bytes =3D ALIGN(encoded->len, fs_info->sector=
size);
>>>>> -=C2=A0=C2=A0=C2=A0 ram_bytes =3D ALIGN(encoded->unencoded_len, fs_in=
fo->sectorsize);
>>>>> +=C2=A0=C2=A0=C2=A0 num_bytes =3D ALIGN(encoded->len, fs_info->data_i=
o_size);
>>>>> +=C2=A0=C2=A0=C2=A0 ram_bytes =3D ALIGN(encoded->unencoded_len, fs_in=
fo->data_io_size);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 end =3D start + num_bytes =
- 1;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /*
>>>>> @@ -9810,7 +9810,7 @@ ssize_t btrfs_do_encoded_write(struct kiocb
>>>>> *iocb, struct iov_iter *from,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 * sector-aligned. Fo=
r convenience, we extend it with zeroes
>>>>> if it
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 * isn't.
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 */
>>>>> -=C2=A0=C2=A0=C2=A0 disk_num_bytes =3D ALIGN(orig_count, fs_info->sec=
torsize);
>>>>> +=C2=A0=C2=A0=C2=A0 disk_num_bytes =3D ALIGN(orig_count, fs_info->dat=
a_io_size);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 cb =3D btrfs_alloc_compres=
sed_write(inode, start, num_bytes);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 for (int i =3D 0; i * min_=
folio_size < disk_num_bytes; i++) {
>>>>> @@ -10222,7 +10222,7 @@ static int btrfs_swap_activate(struct
>>>>> swap_info_struct *sis, struct file *file,
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 atomic_inc(&root->nr_swapf=
iles);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 spin_unlock(&root->root_it=
em_lock);
>>>>> -=C2=A0=C2=A0=C2=A0 isize =3D ALIGN_DOWN(inode->i_size, fs_info->sect=
orsize);
>>>>> +=C2=A0=C2=A0=C2=A0 isize =3D ALIGN_DOWN(inode->i_size, fs_info->data=
_io_size);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 btrfs_lock_extent(io_tree,=
 0, isize - 1, &cached_state);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 while (prev_extent_end < i=
size) {
>>>>> diff --git a/fs/btrfs/lzo.c b/fs/btrfs/lzo.c
>>>>> index 1531adb117d1..0235530fd0f8 100644
>>>>> --- a/fs/btrfs/lzo.c
>>>>> +++ b/fs/btrfs/lzo.c
>>>>> @@ -414,7 +414,7 @@ int lzo_decompress_bio(struct list_head *ws,
>>>>> struct compressed_bio *cb)
>>>>> =C2=A0=C2=A0=C2=A0 {
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct workspace *workspac=
e =3D list_entry(ws, struct workspace,
>>>>> list);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct btrfs_fs_info *fs_i=
nfo =3D cb->bbio.inode->root->fs_info;
>>>>> -=C2=A0=C2=A0=C2=A0 const u32 sectorsize =3D fs_info->sectorsize;
>>>>> +=C2=A0=C2=A0=C2=A0 const u32 sectorsize =3D fs_info->data_io_size;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 const u32 compressed_len =
=3D bio_get_size(&cb->bbio.bio);
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct folio_iter fi;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 char *kaddr;
>>>>> diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
>>>>> index 0d14570c8bc2..8ca7b7e304e3 100644
>>>>> --- a/fs/btrfs/sysfs.c
>>>>> +++ b/fs/btrfs/sysfs.c
>>>>> @@ -301,6 +301,7 @@ BTRFS_FEAT_ATTR_INCOMPAT(extent_tree_v2,
>>>>> EXTENT_TREE_V2);
>>>>> =C2=A0=C2=A0=C2=A0 BTRFS_FEAT_ATTR_INCOMPAT(raid_stripe_tree, RAID_ST=
RIPE_TREE);
>>>>> =C2=A0=C2=A0=C2=A0 /* Remove once support for remap tree is feature c=
omplete. */
>>>>> =C2=A0=C2=A0=C2=A0 BTRFS_FEAT_ATTR_INCOMPAT(remap_tree, REMAP_TREE);
>>>>> +BTRFS_FEAT_ATTR_COMPAT_RO(data_io_size, DATA_IO_SIZE);
>>>>> =C2=A0=C2=A0=C2=A0 #endif
>>>>> =C2=A0=C2=A0=C2=A0 #ifdef CONFIG_FS_VERITY
>>>>> =C2=A0=C2=A0=C2=A0 BTRFS_FEAT_ATTR_COMPAT_RO(verity, VERITY);
>>>>> @@ -334,6 +335,7 @@ static struct attribute
>>>>> *btrfs_supported_feature_attrs[] =3D {
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 BTRFS_FEAT_ATTR_PTR(extent=
_tree_v2),
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 BTRFS_FEAT_ATTR_PTR(raid_s=
tripe_tree),
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 BTRFS_FEAT_ATTR_PTR(remap_=
tree),
>>>>> +=C2=A0=C2=A0=C2=A0 BTRFS_FEAT_ATTR_PTR(data_io_size),
>>>>> =C2=A0=C2=A0=C2=A0 #endif
>>>>> =C2=A0=C2=A0=C2=A0 #ifdef CONFIG_FS_VERITY
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 BTRFS_FEAT_ATTR_PTR(verity=
),
>>>>> diff --git a/fs/btrfs/tests/btrfs-tests.c b/fs/btrfs/tests/btrfs-=20
>>>>> tests.c
>>>>> index 6287d940323d..e3e7bbee7cd7 100644
>>>>> --- a/fs/btrfs/tests/btrfs-tests.c
>>>>> +++ b/fs/btrfs/tests/btrfs-tests.c
>>>>> @@ -140,6 +140,7 @@ struct btrfs_fs_info
>>>>> *btrfs_alloc_dummy_fs_info(u32 nodesize, u32 sectorsize)
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 fs_info->nodesize =3D node=
size;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 fs_info->sectorsize =3D se=
ctorsize;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 fs_info->sectorsize_bits =
=3D ilog2(sectorsize);
>>>>> +=C2=A0=C2=A0=C2=A0 fs_info->data_io_size =3D sectorsize;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /* CRC32C csum size. */
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 fs_info->csum_size =3D 4;
>>>>> diff --git a/include/uapi/linux/btrfs.h b/include/uapi/linux/btrfs.h
>>>>> index 0a13baf3d8d1..858a37811586 100644
>>>>> --- a/include/uapi/linux/btrfs.h
>>>>> +++ b/include/uapi/linux/btrfs.h
>>>>> @@ -314,6 +314,13 @@ struct btrfs_ioctl_fs_info_args {
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0 */
>>>>> =C2=A0=C2=A0=C2=A0 #define BTRFS_FEATURE_COMPAT_RO_BLOCK_GROUP_TREE=
=C2=A0=C2=A0=C2=A0 (1ULL << 3)
>>>>> +/*
>>>>> + * Force all IOs (including buffered, direct, compressed) to be=20
>>>>> aligned
>>>>> + * to btrfs_super_block::data_io_size other than sectorsize.
>>>>> + * Meanwhile still data checksum to be calculated based on=20
>>>>> sectorsize.
>>>>> + */
>>>>> +#define BTRFS_FEATURE_COMPAT_RO_DATA_IO_SIZE=C2=A0=C2=A0=C2=A0=C2=A0=
=C2=A0=C2=A0=C2=A0 (1ULL << 4)
>>>>> +
>>>>> =C2=A0=C2=A0=C2=A0 #define BTRFS_FEATURE_INCOMPAT_MIXED_BACKREF=C2=A0=
=C2=A0=C2=A0 (1ULL << 0)
>>>>> =C2=A0=C2=A0=C2=A0 #define BTRFS_FEATURE_INCOMPAT_DEFAULT_SUBVOL=C2=
=A0=C2=A0=C2=A0 (1ULL << 1)
>>>>> =C2=A0=C2=A0=C2=A0 #define BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS=C2=A0=
=C2=A0=C2=A0 (1ULL << 2)
>>>>> diff --git a/include/uapi/linux/btrfs_tree.h b/include/uapi/linux/
>>>>> btrfs_tree.h
>>>>> index cc3b9f7dccaf..3b979ba5a3fc 100644
>>>>> --- a/include/uapi/linux/btrfs_tree.h
>>>>> +++ b/include/uapi/linux/btrfs_tree.h
>>>>> @@ -724,9 +724,10 @@ struct btrfs_super_block {
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 __le64 remap_root;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 __le64 remap_root_generati=
on;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 __u8 remap_root_level;
>>>>> +=C2=A0=C2=A0=C2=A0 __u32 data_io_size;
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 /* Future expansion */
>>>>> -=C2=A0=C2=A0=C2=A0 __u8 reserved[199];
>>>>> +=C2=A0=C2=A0=C2=A0 __u8 reserved[195];
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 __u8 sys_chunk_array[BTRFS=
_SYSTEM_CHUNK_ARRAY_SIZE];
>>>>> =C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0=C2=A0 struct btrfs_root_backup s=
uper_roots[BTRFS_NUM_BACKUP_ROOTS];
>>>
>=20
>