[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20191030041358.14450-8-ruansy.fnst@cn.fujitsu.com>
Date: Wed, 30 Oct 2019 12:13:58 +0800
From: Shiyang Ruan <ruansy.fnst@...fujitsu.com>
To: <linux-xfs@...r.kernel.org>, <linux-nvdimm@...ts.01.org>,
<darrick.wong@...cle.com>, <rgoldwyn@...e.de>, <hch@...radead.org>,
<david@...morbit.com>
CC: <linux-kernel@...r.kernel.org>, <gujx@...fujitsu.com>,
<qi.fuli@...itsu.com>, <caoj.fnst@...fujitsu.com>,
<ruansy.fnst@...fujitsu.com>
Subject: [RFC PATCH v2 7/7] xfs: support dedupe for fsdax.
Use xfs_break_layouts() to break files' layouts when locking them. And
call dax_file_range_compare() function to compare range for DAX files.
Signed-off-by: Shiyang Ruan <ruansy.fnst@...fujitsu.com>
---
fs/xfs/xfs_reflink.c | 77 ++++++++++++++++++++++++++------------------
1 file changed, 45 insertions(+), 32 deletions(-)
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index e3620bc794a2..3d8d1d2f0ac0 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -1186,47 +1186,41 @@ xfs_reflink_remap_blocks(
* back out both locks.
*/
static int
-xfs_iolock_two_inodes_and_break_layout(
- struct inode *src,
- struct inode *dest)
+xfs_reflink_remap_lock_and_break_layouts(
+ struct file *file_in,
+ struct file *file_out)
{
int error;
+ struct inode *inode_in = file_inode(file_in);
+ struct xfs_inode *src = XFS_I(inode_in);
+ struct inode *inode_out = file_inode(file_out);
+ struct xfs_inode *dest = XFS_I(inode_out);
+ uint iolock = XFS_IOLOCK_EXCL | XFS_MMAPLOCK_EXCL;
- if (src > dest)
+ if (inode_in > inode_out) {
+ swap(inode_in, inode_out);
swap(src, dest);
-
-retry:
- /* Wait to break both inodes' layouts before we start locking. */
- error = break_layout(src, true);
- if (error)
- return error;
- if (src != dest) {
- error = break_layout(dest, true);
- if (error)
- return error;
}
- /* Lock one inode and make sure nobody got in and leased it. */
- inode_lock(src);
- error = break_layout(src, false);
+ inode_lock(inode_in);
+ xfs_ilock(src, XFS_MMAPLOCK_EXCL);
+ error = xfs_break_layouts(inode_in, &iolock, BREAK_UNMAP);
+ xfs_iunlock(src, XFS_MMAPLOCK_EXCL);
if (error) {
- inode_unlock(src);
- if (error == -EWOULDBLOCK)
- goto retry;
+ inode_unlock(inode_in);
return error;
}
- if (src == dest)
+ if (inode_in == inode_out)
return 0;
- /* Lock the other inode and make sure nobody got in and leased it. */
- inode_lock_nested(dest, I_MUTEX_NONDIR2);
- error = break_layout(dest, false);
+ inode_lock_nested(inode_out, I_MUTEX_NONDIR2);
+ xfs_ilock(dest, XFS_MMAPLOCK_EXCL);
+ error = xfs_break_layouts(inode_out, &iolock, BREAK_UNMAP);
+ xfs_iunlock(dest, XFS_MMAPLOCK_EXCL);
if (error) {
- inode_unlock(src);
- inode_unlock(dest);
- if (error == -EWOULDBLOCK)
- goto retry;
+ inode_unlock(inode_in);
+ inode_unlock(inode_out);
return error;
}
@@ -1245,6 +1239,11 @@ xfs_reflink_remap_unlock(
struct xfs_inode *dest = XFS_I(inode_out);
bool same_inode = (inode_in == inode_out);
+ if (inode_in > inode_out) {
+ swap(inode_in, inode_out);
+ swap(src, dest);
+ }
+
xfs_iunlock(dest, XFS_MMAPLOCK_EXCL);
if (!same_inode)
xfs_iunlock(src, XFS_MMAPLOCK_EXCL);
@@ -1275,6 +1274,14 @@ xfs_reflink_zero_posteof(
&xfs_buffered_write_iomap_ops);
}
+int xfs_reflink_dedupe_file_range_compare(struct inode *src, loff_t srcoff,
+ struct inode *dest, loff_t destoff,
+ loff_t len, bool *is_same)
+{
+ return dax_file_range_compare(src, srcoff, dest, destoff, len, is_same,
+ &xfs_read_iomap_ops);
+}
+
/*
* Prepare two files for range cloning. Upon a successful return both inodes
* will have the iolock and mmaplock held, the page cache of the out file will
@@ -1319,9 +1326,10 @@ xfs_reflink_remap_prep(
struct xfs_inode *dest = XFS_I(inode_out);
bool same_inode = (inode_in == inode_out);
ssize_t ret;
+ compare_range_t cmp;
/* Lock both files against IO */
- ret = xfs_iolock_two_inodes_and_break_layout(inode_in, inode_out);
+ ret = xfs_reflink_remap_lock_and_break_layouts(file_in, file_out);
if (ret)
return ret;
if (same_inode)
@@ -1336,12 +1344,17 @@ 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))
+ cmp = xfs_reflink_dedupe_file_range_compare;
+ else
+ cmp = vfs_dedupe_file_range_compare;
+
ret = generic_remap_file_range_prep(file_in, pos_in, file_out, pos_out,
- len, remap_flags, vfs_dedupe_file_range_compare);
+ len, remap_flags, cmp);
if (ret < 0 || *len == 0)
goto out_unlock;
--
2.23.0
Powered by blists - more mailing lists