Re: [PATCH] nilfs2: fix block-offset handling in iomap reads
Ryusuke Konishi <[email protected]> Fri, 31 Jul 2026 21:05:35 +0900
| Newsgroups | org.kernel.vger.linux-nilfs,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <CAKFNMokGmCHO65JVxFwuETFiKE6k10xs4bqfdgu4Gkq1PS9iSg@mail.gmail.com> |
On Fri, Jul 31, 2026 at 5:38=E2=80=AFPM Linmao Li wrote:
>
> nilfs_iomap_begin() looks up the filesystem block containing the requeste=
d
> offset and returns the physical address of that block. However, it sets
> iomap->offset to the original, possibly sub-block, offset while leaving
> iomap->addr at the start of the physical block.
>
> iomap_sector() adds the difference between the I/O position and
> iomap->offset to iomap->addr. For an O_DIRECT read at offset 512 on a
> filesystem with 4 KiB blocks, the two file offsets are equal and the I/O =
is
> therefore submitted at the start of the physical block instead of 512 byt=
es
> into it. iomap direct I/O permits this alignment when the device logical
> block size is 512 bytes.
>
> Describe mapped and hole extents from the filesystem-block-aligned file
> offset. This makes the physical and file offsets refer to the same byte.
> It also prevents a one-block hole mapping from extending into the followi=
ng
> block.
>
> Fixes: b924d8d4e54f ("nilfs2: switch O_DIRECT reads to iomap")
> Signed-off-by: Linmao Li <[email protected]>
> ---
> fs/nilfs2/iomap.c | 9 +++++----
> 1 file changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/fs/nilfs2/iomap.c b/fs/nilfs2/iomap.c
> index 3ae3bf6ed3686..e130ed63abd9a 100644
> --- a/fs/nilfs2/iomap.c
> +++ b/fs/nilfs2/iomap.c
> @@ -18,6 +18,7 @@ static int nilfs_iomap_begin(struct inode *inode, loff_=
t offset,
> struct the_nilfs *nilfs =3D inode->i_sb->s_fs_info;
> struct nilfs_inode_info *ii =3D NILFS_I(inode);
> sector_t blkoff =3D offset >> inode->i_blkbits;
> + loff_t iomap_offset =3D (loff_t)blkoff << inode->i_blkbits;
> unsigned int maxblocks;
> __u64 blknum =3D 0;
> int ret;
> @@ -50,15 +51,15 @@ static int nilfs_iomap_begin(struct inode *inode, lof=
f_t offset,
> if (ret =3D=3D -ENOENT) {
> iomap->type =3D IOMAP_HOLE;
> iomap->addr =3D IOMAP_NULL_ADDR;
> - iomap->offset =3D offset;
> - iomap->length =3D min_t(loff_t, length, i_blocksize(inode=
));
> + iomap->offset =3D iomap_offset;
> + iomap->length =3D i_blocksize(inode);
> return 0;
> } else if (ret < 0)
> return ret;
>
> iomap->bdev =3D inode->i_sb->s_bdev;
> - iomap->offset =3D offset;
> - iomap->length =3D min_t(loff_t, length, (loff_t)ret << inode->i_b=
lkbits);
> + iomap->offset =3D iomap_offset;
> + iomap->length =3D (loff_t)ret << inode->i_blkbits;
> iomap->addr =3D (loff_t)blknum << inode->i_blkbits;
> iomap->type =3D IOMAP_MAPPED;
> iomap->flags =3D IOMAP_F_MERGED;
>
> base-commit: d5c57d9bf03516d625521cd6cf5acfd93e3e63c7
> --
> 2.25.1
Hi Linmao,
Since the O_DIRECT iomap conversion patch series is currently under
review and subject to revision, please post your finding as comments
on the original patch thread in the future, rather than sending a
standalone patch with a premature Fixes tag.
Hi Viacheslav,
I believe the point being made is that a misalignment occurs because
iomap->addr is adjusted to the block boundary, whereas iomap->offset
is not. Could you take a look at his points ?
Thanks,
Ryusuke Konishi