xfs: implement XFS_IOC_DIOINFO in terms of vfs_getattr

Use the direct I/O alignment reporting from ->getattr instead of
reimplementing it.  This exposes the relaxation of the memory
alignment in the XFS_IOC_DIOINFO info and ensure the information will
stay in sync.  Note that randholes.c in xfstests has a bug where it
incorrectly fails when the required memory alignment is smaller than the
pointer size.  Round up the reported value as there is a fair chance that
this code got copied into various applications.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Carlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: Carlos Maiolino <cem@kernel.org>
This commit is contained in:
Christoph Hellwig 2025-08-25 13:15:00 +02:00 committed by Carlos Maiolino
parent 0239bd9fa4
commit 851c4c96db
1 changed files with 9 additions and 9 deletions

View File

@ -1203,21 +1203,21 @@ xfs_file_ioctl(
current->comm);
return -ENOTTY;
case XFS_IOC_DIOINFO: {
struct xfs_buftarg *target = xfs_inode_buftarg(ip);
struct kstat st;
struct dioattr da;
da.d_mem = target->bt_logical_sectorsize;
error = vfs_getattr(&filp->f_path, &st, STATX_DIOALIGN, 0);
if (error)
return error;
/*
* See xfs_report_dioalign() for an explanation about why this
* reports a value larger than the sector size for COW inodes.
* Some userspace directly feeds the return value to
* posix_memalign, which fails for values that are smaller than
* the pointer size. Round up the value to not break userspace.
*/
if (xfs_is_cow_inode(ip))
da.d_miniosz = xfs_inode_alloc_unitsize(ip);
else
da.d_miniosz = target->bt_logical_sectorsize;
da.d_mem = roundup(st.dio_mem_align, sizeof(void *));
da.d_miniosz = st.dio_offset_align;
da.d_maxiosz = INT_MAX & ~(da.d_miniosz - 1);
if (copy_to_user(arg, &da, sizeof(da)))
return -EFAULT;
return 0;