mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] nilfs2: fix block-offset handling in iomap reads
@ 2026-07-31  8:38 Linmao Li
  2026-07-31 12:05 ` Ryusuke Konishi
  0 siblings, 1 reply; 3+ messages in thread
From: Linmao Li @ 2026-07-31  8:38 UTC (permalink / raw)
  To: Ryusuke Konishi, Viacheslav Dubeyko
  Cc: Christian Brauner, linux-nilfs, linux-kernel, Linmao Li

nilfs_iomap_begin() looks up the filesystem block containing the requested
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 bytes
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 following
block.

Fixes: b924d8d4e54f ("nilfs2: switch O_DIRECT reads to iomap")
Signed-off-by: Linmao Li <lilinmao@kylinos.cn>
---
 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 = inode->i_sb->s_fs_info;
 	struct nilfs_inode_info *ii = NILFS_I(inode);
 	sector_t blkoff = offset >> inode->i_blkbits;
+	loff_t iomap_offset = (loff_t)blkoff << inode->i_blkbits;
 	unsigned int maxblocks;
 	__u64 blknum = 0;
 	int ret;
@@ -50,15 +51,15 @@ static int nilfs_iomap_begin(struct inode *inode, loff_t offset,
 	if (ret == -ENOENT) {
 		iomap->type = IOMAP_HOLE;
 		iomap->addr = IOMAP_NULL_ADDR;
-		iomap->offset = offset;
-		iomap->length = min_t(loff_t, length, i_blocksize(inode));
+		iomap->offset = iomap_offset;
+		iomap->length = i_blocksize(inode);
 		return 0;
 	} else if (ret < 0)
 		return ret;
 
 	iomap->bdev = inode->i_sb->s_bdev;
-	iomap->offset = offset;
-	iomap->length = min_t(loff_t, length, (loff_t)ret << inode->i_blkbits);
+	iomap->offset = iomap_offset;
+	iomap->length = (loff_t)ret << inode->i_blkbits;
 	iomap->addr = (loff_t)blknum << inode->i_blkbits;
 	iomap->type = IOMAP_MAPPED;
 	iomap->flags = IOMAP_F_MERGED;

base-commit: d5c57d9bf03516d625521cd6cf5acfd93e3e63c7
-- 
2.25.1


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] nilfs2: fix block-offset handling in iomap reads
  2026-07-31  8:38 [PATCH] nilfs2: fix block-offset handling in iomap reads Linmao Li
@ 2026-07-31 12:05 ` Ryusuke Konishi
  2026-08-03  0:33   ` Viacheslav Dubeyko
  0 siblings, 1 reply; 3+ messages in thread
From: Ryusuke Konishi @ 2026-07-31 12:05 UTC (permalink / raw)
  To: Linmao Li, Viacheslav Dubeyko
  Cc: Christian Brauner, linux-nilfs, linux-kernel

On Fri, Jul 31, 2026 at 5:38 PM Linmao Li wrote:
>
> nilfs_iomap_begin() looks up the filesystem block containing the requested
> 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 bytes
> 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 following
> block.
>
> Fixes: b924d8d4e54f ("nilfs2: switch O_DIRECT reads to iomap")
> Signed-off-by: Linmao Li <lilinmao@kylinos.cn>
> ---
>  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 = inode->i_sb->s_fs_info;
>         struct nilfs_inode_info *ii = NILFS_I(inode);
>         sector_t blkoff = offset >> inode->i_blkbits;
> +       loff_t iomap_offset = (loff_t)blkoff << inode->i_blkbits;
>         unsigned int maxblocks;
>         __u64 blknum = 0;
>         int ret;
> @@ -50,15 +51,15 @@ static int nilfs_iomap_begin(struct inode *inode, loff_t offset,
>         if (ret == -ENOENT) {
>                 iomap->type = IOMAP_HOLE;
>                 iomap->addr = IOMAP_NULL_ADDR;
> -               iomap->offset = offset;
> -               iomap->length = min_t(loff_t, length, i_blocksize(inode));
> +               iomap->offset = iomap_offset;
> +               iomap->length = i_blocksize(inode);
>                 return 0;
>         } else if (ret < 0)
>                 return ret;
>
>         iomap->bdev = inode->i_sb->s_bdev;
> -       iomap->offset = offset;
> -       iomap->length = min_t(loff_t, length, (loff_t)ret << inode->i_blkbits);
> +       iomap->offset = iomap_offset;
> +       iomap->length = (loff_t)ret << inode->i_blkbits;
>         iomap->addr = (loff_t)blknum << inode->i_blkbits;
>         iomap->type = IOMAP_MAPPED;
>         iomap->flags = 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

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] nilfs2: fix block-offset handling in iomap reads
  2026-07-31 12:05 ` Ryusuke Konishi
@ 2026-08-03  0:33   ` Viacheslav Dubeyko
  0 siblings, 0 replies; 3+ messages in thread
From: Viacheslav Dubeyko @ 2026-08-03  0:33 UTC (permalink / raw)
  To: Ryusuke Konishi, Linmao Li; +Cc: Christian Brauner, linux-nilfs, linux-kernel

On Fri, 2026-07-31 at 21:05 +0900, Ryusuke Konishi wrote:
> On Fri, Jul 31, 2026 at 5:38 PM Linmao Li wrote:
> > 
> > nilfs_iomap_begin() looks up the filesystem block containing the
> > requested
> > 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 bytes
> > 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
> > following
> > block.
> > 
> > Fixes: b924d8d4e54f ("nilfs2: switch O_DIRECT reads to iomap")
> > Signed-off-by: Linmao Li <lilinmao@kylinos.cn>
> > ---
> >  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 = inode->i_sb->s_fs_info;
> >         struct nilfs_inode_info *ii = NILFS_I(inode);
> >         sector_t blkoff = offset >> inode->i_blkbits;
> > +       loff_t iomap_offset = (loff_t)blkoff << inode->i_blkbits;
> >         unsigned int maxblocks;
> >         __u64 blknum = 0;
> >         int ret;
> > @@ -50,15 +51,15 @@ static int nilfs_iomap_begin(struct inode
> > *inode, loff_t offset,
> >         if (ret == -ENOENT) {
> >                 iomap->type = IOMAP_HOLE;
> >                 iomap->addr = IOMAP_NULL_ADDR;
> > -               iomap->offset = offset;
> > -               iomap->length = min_t(loff_t, length,
> > i_blocksize(inode));
> > +               iomap->offset = iomap_offset;
> > +               iomap->length = i_blocksize(inode);
> >                 return 0;
> >         } else if (ret < 0)
> >                 return ret;
> > 
> >         iomap->bdev = inode->i_sb->s_bdev;
> > -       iomap->offset = offset;
> > -       iomap->length = min_t(loff_t, length, (loff_t)ret << inode-
> > >i_blkbits);
> > +       iomap->offset = iomap_offset;
> > +       iomap->length = (loff_t)ret << inode->i_blkbits;
> >         iomap->addr = (loff_t)blknum << inode->i_blkbits;
> >         iomap->type = IOMAP_MAPPED;
> >         iomap->flags = 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 ?
> 

Hi Ryusuke,

The fix makes sense to me. I am attending FMS 2026 (August 4th - 6th).
So, I don't have time for preparing v2 of the patchset with adding
Linmao's fix during this week. Let me try to find the time for pathset
reworking around the end of this week.

Thanks,
Slava.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-08-03  0:33 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-07-31  8:38 [PATCH] nilfs2: fix block-offset handling in iomap reads Linmao Li
2026-07-31 12:05 ` Ryusuke Konishi
2026-08-03  0:33   ` Viacheslav Dubeyko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®