]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
xfs: implement XFS_IOC_DIOINFO in terms of vfs_getattr
authorChristoph Hellwig <hch@lst.de>
Mon, 25 Aug 2025 11:15:00 +0000 (13:15 +0200)
committerCarlos Maiolino <cem@kernel.org>
Thu, 28 Aug 2025 12:20:03 +0000 (14:20 +0200)
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>
fs/xfs/xfs_ioctl.c

index 10a3a5160f4eb047d738da1292c8049ed7e4cbb1..a6bb7ee7a27ad5215fdfee6147057da263058f64 100644 (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;