Commit 13f9e267 authored by Shiyang Ruan's avatar Shiyang Ruan Committed by Andrew Morton
Browse files

xfs: add dax dedupe support

Introduce xfs_mmaplock_two_inodes_and_break_dax_layout() for dax files who
are going to be deduped.  After that, call compare range function only
when files are both DAX or not.

Link: https://lkml.kernel.org/r/20220603053738.1218681-15-ruansy.fnst@fujitsu.com


Signed-off-by: default avatarShiyang Ruan <ruansy.fnst@fujitsu.com>
Reviewed-by: default avatarDarrick J. Wong <djwong@kernel.org>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Dan Williams <dan.j.wiliams@intel.com>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Goldwyn Rodrigues <rgoldwyn@suse.com>
Cc: Goldwyn Rodrigues <rgoldwyn@suse.de>
Cc: Jane Chu <jane.chu@oracle.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Miaohe Lin <linmiaohe@huawei.com>
Cc: Naoya Horiguchi <naoya.horiguchi@nec.com>
Cc: Ritesh Harjani <riteshh@linux.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent ea6c49b7
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -808,7 +808,7 @@ xfs_wait_dax_page(
	xfs_ilock(ip, XFS_MMAPLOCK_EXCL);
}

static int
int
xfs_break_dax_layouts(
	struct inode		*inode,
	bool			*retry)
+65 −4
Original line number Diff line number Diff line
@@ -3767,6 +3767,50 @@ xfs_iolock_two_inodes_and_break_layout(
	return 0;
}

static int
xfs_mmaplock_two_inodes_and_break_dax_layout(
	struct xfs_inode	*ip1,
	struct xfs_inode	*ip2)
{
	int			error;
	bool			retry;
	struct page		*page;

	if (ip1->i_ino > ip2->i_ino)
		swap(ip1, ip2);

again:
	retry = false;
	/* Lock the first inode */
	xfs_ilock(ip1, XFS_MMAPLOCK_EXCL);
	error = xfs_break_dax_layouts(VFS_I(ip1), &retry);
	if (error || retry) {
		xfs_iunlock(ip1, XFS_MMAPLOCK_EXCL);
		if (error == 0 && retry)
			goto again;
		return error;
	}

	if (ip1 == ip2)
		return 0;

	/* Nested lock the second inode */
	xfs_ilock(ip2, xfs_lock_inumorder(XFS_MMAPLOCK_EXCL, 1));
	/*
	 * We cannot use xfs_break_dax_layouts() directly here because it may
	 * need to unlock & lock the XFS_MMAPLOCK_EXCL which is not suitable
	 * for this nested lock case.
	 */
	page = dax_layout_busy_page(VFS_I(ip2)->i_mapping);
	if (page && page_ref_count(page) != 1) {
		xfs_iunlock(ip2, XFS_MMAPLOCK_EXCL);
		xfs_iunlock(ip1, XFS_MMAPLOCK_EXCL);
		goto again;
	}

	return 0;
}

/*
 * Lock two inodes so that userspace cannot initiate I/O via file syscalls or
 * mmap activity.
@@ -3781,8 +3825,19 @@ xfs_ilock2_io_mmap(
	ret = xfs_iolock_two_inodes_and_break_layout(VFS_I(ip1), VFS_I(ip2));
	if (ret)
		return ret;

	if (IS_DAX(VFS_I(ip1)) && IS_DAX(VFS_I(ip2))) {
		ret = xfs_mmaplock_two_inodes_and_break_dax_layout(ip1, ip2);
		if (ret) {
			inode_unlock(VFS_I(ip2));
			if (ip1 != ip2)
				inode_unlock(VFS_I(ip1));
			return ret;
		}
	} else
		filemap_invalidate_lock_two(VFS_I(ip1)->i_mapping,
					    VFS_I(ip2)->i_mapping);

	return 0;
}

@@ -3792,8 +3847,14 @@ xfs_iunlock2_io_mmap(
	struct xfs_inode	*ip1,
	struct xfs_inode	*ip2)
{
	if (IS_DAX(VFS_I(ip1)) && IS_DAX(VFS_I(ip2))) {
		xfs_iunlock(ip2, XFS_MMAPLOCK_EXCL);
		if (ip1 != ip2)
			xfs_iunlock(ip1, XFS_MMAPLOCK_EXCL);
	} else
		filemap_invalidate_unlock_two(VFS_I(ip1)->i_mapping,
					      VFS_I(ip2)->i_mapping);

	inode_unlock(VFS_I(ip2));
	if (ip1 != ip2)
		inode_unlock(VFS_I(ip1));
+1 −0
Original line number Diff line number Diff line
@@ -467,6 +467,7 @@ xfs_itruncate_extents(
}

/* from xfs_file.c */
int	xfs_break_dax_layouts(struct inode *inode, bool *retry);
int	xfs_break_layouts(struct inode *inode, uint *iolock,
		enum layout_break_reason reason);

+2 −2
Original line number Diff line number Diff line
@@ -1363,8 +1363,8 @@ xfs_reflink_remap_prep(
	if (XFS_IS_REALTIME_INODE(src) || XFS_IS_REALTIME_INODE(dest))
		goto out_unlock;

	/* Don't share DAX file data for now. */
	if (IS_DAX(inode_in) || IS_DAX(inode_out))
	/* Don't share DAX file data with non-DAX file. */
	if (IS_DAX(inode_in) != IS_DAX(inode_out))
		goto out_unlock;

	if (!IS_DAX(inode_in))