[f2fs-dev] [PATCHv2 2/5] block: report direct io attributes through file_getattr
Keith Busch via Linux-f2fs-devel <[email protected]> Fri, 10 Jul 2026 14:06:43 -0700
| Newsgroups | net.sourceforge.lists.linux-f2fs-devel,org.kernel.vger.linux-block |
|---|---|
| Message-ID | <[email protected]> |
From: Keith Busch <[email protected]> Add bdev_fill_dio_attr() to fill the file_attr direct io alignment fields from a block device's queue limits, so filesystems can share the derivation. Use it to report the attributes for block devices opened directly. Signed-off-by: Keith Busch <[email protected]> --- block/bdev.c | 37 +++++++++++++++++++++++++++++++++++++ fs/file_attr.c | 6 +++++- include/linux/blkdev.h | 14 ++++++++++++++ 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/block/bdev.c b/block/bdev.c index 85ce57bd2ae4f..3b56f6696d3a3 100644 --- a/block/bdev.c +++ b/block/bdev.c @@ -28,6 +28,7 @@ #include <linux/part_stat.h> #include <linux/uaccess.h> #include <linux/stat.h> +#include <linux/fileattr.h> #include "../fs/internal.h" #include "blk.h" @@ -1353,6 +1354,42 @@ void bdev_statx(const struct path *path, struct kstat *stat, u32 request_mask) blkdev_put_no_open(bdev); } +/* + * Fill the direct I/O alignment attributes derived from a block device's + * queue limits. Filesystems override the offset alignments as needed and + * set FS_XFLAG_DIO once they have decided direct I/O is supported. + */ +void bdev_fill_dio_attr(struct block_device *bdev, struct file_kattr *fa) +{ + 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_dio_offset_align_max_vecs = bdev_max_segments(bdev); +} +EXPORT_SYMBOL_GPL(bdev_fill_dio_attr); + +/* + * Handle DIO alignment for block devices via fileattr. + */ +int bdev_fileattr(const struct inode *inode, struct file_kattr *fa) +{ + struct block_device *bdev; + + bdev = blkdev_get_no_open(inode->i_rdev, false); + if (!bdev) + return -ENODEV; + + memset(fa, 0, sizeof(*fa)); + bdev_fill_dio_attr(bdev, fa); + fa->fsx_valid = true; + fa->flags_valid = true; + fa->fsx_xflags |= FS_XFLAG_DIO; + + blkdev_put_no_open(bdev); + return 0; +} + bool disk_live(struct gendisk *disk) { return !inode_unhashed(BD_INODE(disk->part0)); diff --git a/fs/file_attr.c b/fs/file_attr.c index b37a55f54a449..b637eff9081aa 100644 --- a/fs/file_attr.c +++ b/fs/file_attr.c @@ -7,6 +7,7 @@ #include <linux/export.h> #include <linux/syscalls.h> #include <linux/namei.h> +#include <linux/blkdev.h> #include "internal.h" @@ -88,13 +89,16 @@ 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) + if (!inode->i_op->fileattr_get && !S_ISBLK(inode->i_mode)) return -ENOIOCTLCMD; error = security_inode_file_getattr(dentry, fa); if (error) return error; + if (!inode->i_op->fileattr_get) + return bdev_fileattr(inode, fa); + return inode->i_op->fileattr_get(dentry, fa); } EXPORT_SYMBOL(vfs_fileattr_get); diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 9213a5716f95a..2d435fadfdcb9 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -1607,6 +1607,17 @@ static inline unsigned int bdev_dma_alignment(struct block_device *bdev) return queue_dma_alignment(bdev_get_queue(bdev)); } +static inline unsigned long bdev_virt_boundary_mask(struct block_device *bdev) +{ + return bdev_get_queue(bdev)->limits.virt_boundary_mask; +} + +static inline unsigned int +bdev_virt_boundary_alignment(struct block_device *bdev) +{ + return bdev_virt_boundary_mask(bdev) + 1; +} + static inline unsigned int blk_lim_dma_alignment_and_pad(struct queue_limits *lim) { @@ -1805,6 +1816,9 @@ int sync_blockdev_range(struct block_device *bdev, loff_t lstart, loff_t lend); int sync_blockdev_nowait(struct block_device *bdev); void sync_bdevs(bool wait); void bdev_statx(const struct path *path, struct kstat *stat, u32 request_mask); +struct file_kattr; +void bdev_fill_dio_attr(struct block_device *bdev, struct file_kattr *fa); +int bdev_fileattr(const struct inode *inode, struct file_kattr *fa); void printk_all_partitions(void); int __init early_lookup_bdev(const char *pathname, dev_t *dev); #else -- 2.53.0-Meta _______________________________________________ Linux-f2fs-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/linux-f2fs-devel