Commit 851c4c96 authored by Christoph Hellwig's avatar Christoph Hellwig Committed by Carlos Maiolino
Browse files

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: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarCarlos Maiolino <cmaiolino@redhat.com>
Signed-off-by: default avatarCarlos Maiolino <cem@kernel.org>
parent 0239bd9f
Loading
Loading
Loading
Loading
+9 −9
Original line number Diff line number Diff line
@@ -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;