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