* Re: [PATCH] fs: report direct io constraints through file_getattr [not found] <20260708011843.1036846-1-kbusch@meta.com> @ 2026-07-09 7:13 ` Christoph Hellwig 2026-07-09 8:51 ` Andrey Albershteyn ` (2 more replies) 0 siblings, 3 replies; 5+ messages in thread From: Christoph Hellwig @ 2026-07-09 7:13 UTC (permalink / raw) To: Keith Busch Cc: linux-block, linux-ext4, linux-f2fs-devel, linux-fsdevel, linux-xfs, axboe, jack, brauner, cem, jaegeuk, aalbersh, tytso, Keith Busch, Christoph Hellwig On Tue, Jul 07, 2026 at 06:18:43PM -0700, Keith Busch wrote: > From: Keith Busch <kbusch@kernel.org> > > Memory alignment constraints for direct io can vary depending on the > backing storage hardware. Provide support through file_getattr to report > the attributes necessary for applications to know how to construct valid > read and write requests. This probably wants to be split in one patch for the new UAPI, one for the helper and one for each user. And especially the UAPI one needs a much more detailed commit log explaining it, including why this duplicates some of the informastion already in statx and documenting the semantics for all the fields. Andrey, is there a man page or other official documentation for file_setattr/file_getattr? > +/* > + * Handle DIO alignment for block devices via fileattr. > + */ Maybe note that this purely about the block device constraints, and file systems may expose additional ones? > +void bdev_fileattr(const struct inode *inode, struct file_kattr *fa) > +{ > + struct block_device *bdev; > + > + memset(fa, 0, sizeof(*fa)); > + fa->fsx_valid = true; > + fa->flags_valid = true; Doing the basic file_kattr initialization here feels dangerous if we want to be able to call this from file system implementations. I'd rather leave the initialization to the caller. > + > + bdev = blkdev_get_no_open(inode->i_rdev, false); > + if (!bdev) > + return; .. and explicitly pass in the block device. ->i_rdev always is i_sb->s_dev, which might not be the relevant backing device, e.g. for XFS it could be that or the block device in m_rtdev_targp. If i_rdev is i_sb->s_dev we can just use sb->s_bdev without needing a new open. > + fa->fsx_dio_mem_align = bdev_dma_alignment(bdev) + 1; > + fa->fsx_dio_offset_align = bdev_logical_block_size(bdev); > + fa->fsx_dio_read_offset_align = bdev_logical_block_size(bdev); > + fa->fsx_dio_virt_boundary_align = bdev_virt_boundary_alignment(bdev); > + fa->fsx_max_segments = bdev_max_segments(bdev); How is the max_segments value defined in a way that is meaningful to userspace? > @@ -1005,6 +1006,27 @@ int ext4_fileattr_get(struct dentry *dentry, struct file_kattr *fa) > if (ext4_has_feature_project(inode->i_sb)) > fa->fsx_projid = from_kprojid(&init_user_ns, ei->i_projid); > > + if (S_ISREG(inode->i_mode)) { You'll probably want to split this into a helper to keep it easily readable. > + u32 dio_align = ext4_dio_alignment(inode); > + > + if (dio_align != 0) { > + struct block_device *bdev = inode->i_sb->s_bdev; > + > + if (dio_align == 1) { > + fa->fsx_dio_mem_align = bdev_dma_alignment(bdev) + 1; > + fa->fsx_dio_offset_align = bdev_logical_block_size(bdev); > + fa->fsx_dio_read_offset_align = bdev_logical_block_size(bdev); > + } else { > + fa->fsx_dio_mem_align = dio_align; > + fa->fsx_dio_offset_align = dio_align; > + fa->fsx_dio_read_offset_align = dio_align; > + } Call bdev_fileattr and override the relevant field as needed? Question to the ext4 maintainers: why does ext4_dio_alignment affect the in-memory alignment? If it does so, it should probably also affect the virt boundry alignment.. > + if (S_ISREG(inode->i_mode)) { > + unsigned int bsize = i_blocksize(inode); > + struct block_device *bdev = inode->i_sb->s_bdev; > + > + if (!f2fs_force_buffered_io(inode, WRITE)) { Same comments as for ext4. Also f2fs does support multiple devices, but I'm not sure how data is placed on them, or if a file can be on multiple devices. We'll need input from the f2fs maintainers/contributors here. > @@ -88,8 +89,12 @@ int vfs_fileattr_get(struct dentry *dentry, struct file_kattr *fa) > struct inode *inode = d_inode(dentry); > int error; > > - if (!inode->i_op->fileattr_get) > - return -ENOIOCTLCMD; > + if (!inode->i_op->fileattr_get) { > + if (!S_ISBLK(inode->i_mode)) > + return -ENOIOCTLCMD; > + bdev_fileattr(inode, fa); > + return 0; Don't we also want to fill out the attributes for block devices on file systems that provide a ->fileattr_get?. Also if we fill out something, we need the security_inode_file_getattr as well. > /** > @@ -145,6 +155,8 @@ static int file_attr_to_fileattr(const struct file_attr *fattr, > > if (fattr->fa_xflags & ~mask) > return -EINVAL; > + if (fattr->fa_pad) > + return -EINVAL; How is this related? > + if (whichfork == XFS_DATA_FORK && S_ISREG(VFS_I(ip)->i_mode)) { This probably wants a separate helper. > + struct xfs_buftarg *target = xfs_inode_buftarg(ip); > + struct block_device *bdev = target->bt_bdev; .. and if the generic helpers gets an explicitl bdev we can use it here and just override one value for for xfs_is_cow_inode(). > +static inline unsigned int bdev_virt_boundary_alignment(struct block_device *bdev) Overly long line. ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fs: report direct io constraints through file_getattr 2026-07-09 7:13 ` [PATCH] fs: report direct io constraints through file_getattr Christoph Hellwig @ 2026-07-09 8:51 ` Andrey Albershteyn 2026-07-09 9:14 ` Jan Kara 2026-07-09 13:46 ` Keith Busch 2 siblings, 0 replies; 5+ messages in thread From: Andrey Albershteyn @ 2026-07-09 8:51 UTC (permalink / raw) To: Christoph Hellwig Cc: Keith Busch, linux-block, linux-ext4, linux-f2fs-devel, linux-fsdevel, linux-xfs, axboe, jack, brauner, cem, jaegeuk, aalbersh, tytso, Keith Busch On 2026-07-09 09:13:52, Christoph Hellwig wrote: > On Tue, Jul 07, 2026 at 06:18:43PM -0700, Keith Busch wrote: > > From: Keith Busch <kbusch@kernel.org> > > > > Memory alignment constraints for direct io can vary depending on the > > backing storage hardware. Provide support through file_getattr to report > > the attributes necessary for applications to know how to construct valid > > read and write requests. > > This probably wants to be split in one patch for the new UAPI, > one for the helper and one for each user. > > And especially the UAPI one needs a much more detailed commit log > explaining it, including why this duplicates some of the informastion > already in statx and documenting the semantics for all the fields. > > Andrey, is there a man page or other official documentation for > file_setattr/file_getattr? No, I had a draft in cover letter but haven't got to sending it to man-pages. I will prepare a man page. -- - Andrey ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fs: report direct io constraints through file_getattr 2026-07-09 7:13 ` [PATCH] fs: report direct io constraints through file_getattr Christoph Hellwig 2026-07-09 8:51 ` Andrey Albershteyn @ 2026-07-09 9:14 ` Jan Kara 2026-07-09 13:46 ` Keith Busch 2 siblings, 0 replies; 5+ messages in thread From: Jan Kara @ 2026-07-09 9:14 UTC (permalink / raw) To: Christoph Hellwig Cc: Keith Busch, linux-block, linux-ext4, linux-f2fs-devel, linux-fsdevel, linux-xfs, axboe, jack, brauner, cem, jaegeuk, aalbersh, tytso, Keith Busch, Eric Biggers On Thu 09-07-26 09:13:52, Christoph Hellwig wrote: > On Tue, Jul 07, 2026 at 06:18:43PM -0700, Keith Busch wrote: > > + u32 dio_align = ext4_dio_alignment(inode); > > + > > + if (dio_align != 0) { > > > > + struct block_device *bdev = inode->i_sb->s_bdev; > > + > > + if (dio_align == 1) { > > + fa->fsx_dio_mem_align = bdev_dma_alignment(bdev) + 1; > > + fa->fsx_dio_offset_align = bdev_logical_block_size(bdev); > > + fa->fsx_dio_read_offset_align = bdev_logical_block_size(bdev); > > + } else { > > + fa->fsx_dio_mem_align = dio_align; > > + fa->fsx_dio_offset_align = dio_align; > > + fa->fsx_dio_read_offset_align = dio_align; > > + } > > Call bdev_fileattr and override the relevant field as needed? > > Question to the ext4 maintainers: why does ext4_dio_alignment > affect the in-memory alignment? If it does so, it should probably > also affect the virt boundry alignment.. I guess that is mostly a historical accident. ext4_dio_alignment() returns 1 (iomap alignment is used and that's different for memory and file offset alignment), 0 (dio not supported, memory and file offset alignment is indeed the same), and blocksize (a special case which can happen for fscrypt if it supports dio and where I believe memory alignment requirements may be in fact different). I'm adding Eric to CC to answer what actual requirements fscrypt has for memory buffers for direct IO. I'd expect with inline encryption we would have the same requirements as ordinary iomap direct IO and for other code paths I'm not sure... Eric? Honza -- Jan Kara <jack@suse.com> SUSE Labs, CR ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fs: report direct io constraints through file_getattr 2026-07-09 7:13 ` [PATCH] fs: report direct io constraints through file_getattr Christoph Hellwig 2026-07-09 8:51 ` Andrey Albershteyn 2026-07-09 9:14 ` Jan Kara @ 2026-07-09 13:46 ` Keith Busch 2026-07-10 4:35 ` Christoph Hellwig 2 siblings, 1 reply; 5+ messages in thread From: Keith Busch @ 2026-07-09 13:46 UTC (permalink / raw) To: Christoph Hellwig Cc: Keith Busch, linux-block, linux-ext4, linux-f2fs-devel, linux-fsdevel, linux-xfs, axboe, jack, brauner, cem, jaegeuk, aalbersh, tytso On Thu, Jul 09, 2026 at 09:13:52AM +0200, Christoph Hellwig wrote: > On Tue, Jul 07, 2026 at 06:18:43PM -0700, Keith Busch wrote: > > > + fa->fsx_dio_mem_align = bdev_dma_alignment(bdev) + 1; > > + fa->fsx_dio_offset_align = bdev_logical_block_size(bdev); > > + fa->fsx_dio_read_offset_align = bdev_logical_block_size(bdev); > > + fa->fsx_dio_virt_boundary_align = bdev_virt_boundary_alignment(bdev); > > + fa->fsx_max_segments = bdev_max_segments(bdev); > > How is the max_segments value defined in a way that is meaningful to > userspace? It tells you how many sub-sector vectors you can submit in your readv/writev before it needs to add up to a logical block size. Ex: 4k logical block size, 4 byte DMA, 256 max segments. You can define 4-byte iov's in your command, but you'll hit the max segment count before you have a valid IO if they're all that small. > > @@ -145,6 +155,8 @@ static int file_attr_to_fileattr(const struct file_attr *fattr, > > > > if (fattr->fa_xflags & ~mask) > > return -EINVAL; > > + if (fattr->fa_pad) > > + return -EINVAL; > > How is this related? I had to add a padding field to the struct to account for the implicit hole in 64-bit and to ensure the struct is the same size for 32-bit. It's a reserved field, so we have to ensure the current kernel doesn't support any value here in case we define this field for something else in the future. ^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] fs: report direct io constraints through file_getattr 2026-07-09 13:46 ` Keith Busch @ 2026-07-10 4:35 ` Christoph Hellwig 0 siblings, 0 replies; 5+ messages in thread From: Christoph Hellwig @ 2026-07-10 4:35 UTC (permalink / raw) To: Keith Busch Cc: Christoph Hellwig, Keith Busch, linux-block, linux-ext4, linux-f2fs-devel, linux-fsdevel, linux-xfs, axboe, jack, brauner, cem, jaegeuk, aalbersh, tytso On Thu, Jul 09, 2026 at 07:46:42AM -0600, Keith Busch wrote: > On Thu, Jul 09, 2026 at 09:13:52AM +0200, Christoph Hellwig wrote: > > On Tue, Jul 07, 2026 at 06:18:43PM -0700, Keith Busch wrote: > > > > > + fa->fsx_dio_mem_align = bdev_dma_alignment(bdev) + 1; > > > + fa->fsx_dio_offset_align = bdev_logical_block_size(bdev); > > > + fa->fsx_dio_read_offset_align = bdev_logical_block_size(bdev); > > > + fa->fsx_dio_virt_boundary_align = bdev_virt_boundary_alignment(bdev); > > > + fa->fsx_max_segments = bdev_max_segments(bdev); > > > > How is the max_segments value defined in a way that is meaningful to > > userspace? > > It tells you how many sub-sector vectors you can submit in your > readv/writev before it needs to add up to a logical block size. > > Ex: 4k logical block size, 4 byte DMA, 256 max segments. You can define > 4-byte iov's in your command, but you'll hit the max segment count > before you have a valid IO if they're all that small. Ah, makes sense. But besides the missing documentation I think max_segments is a bit of a misleading name for that. Something like max_vecs_per_block (although we don't expose blocks in the UAPI) or max_vecs_per_granularity (I think grammar wants a word with me for that, though...) might be a bit more suitable. > > > @@ -145,6 +155,8 @@ static int file_attr_to_fileattr(const struct file_attr *fattr, > > > > > > if (fattr->fa_xflags & ~mask) > > > return -EINVAL; > > > + if (fattr->fa_pad) > > > + return -EINVAL; > > > > How is this related? > > I had to add a padding field to the struct to account for the implicit > hole in 64-bit and to ensure the struct is the same size for 32-bit. > It's a reserved field, so we have to ensure the current kernel doesn't > support any value here in case we define this field for something else > in the future. Ah, right. ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-07-10 4:35 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20260708011843.1036846-1-kbusch@meta.com>
2026-07-09 7:13 ` [PATCH] fs: report direct io constraints through file_getattr Christoph Hellwig
2026-07-09 8:51 ` Andrey Albershteyn
2026-07-09 9:14 ` Jan Kara
2026-07-09 13:46 ` Keith Busch
2026-07-10 4:35 ` Christoph Hellwig
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox