aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_file.c5
-rw-r--r--fs/xfs/xfs_reflink.c17
-rw-r--r--fs/xfs/xfs_reflink.h2
3 files changed, 14 insertions, 10 deletions
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 38fde4e11714..7d42ab8fe6e1 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -928,14 +928,11 @@ xfs_file_remap_range(
928 loff_t len, 928 loff_t len,
929 unsigned int remap_flags) 929 unsigned int remap_flags)
930{ 930{
931 int ret;
932
933 if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY)) 931 if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY))
934 return -EINVAL; 932 return -EINVAL;
935 933
936 ret = xfs_reflink_remap_range(file_in, pos_in, file_out, pos_out, 934 return xfs_reflink_remap_range(file_in, pos_in, file_out, pos_out,
937 len, remap_flags); 935 len, remap_flags);
938 return ret < 0 ? ret : len;
939} 936}
940 937
941STATIC int 938STATIC int
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index 79dec457f7fb..4abb2aea8f31 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -1122,13 +1122,15 @@ xfs_reflink_remap_blocks(
1122 loff_t pos_in, 1122 loff_t pos_in,
1123 struct xfs_inode *dest, 1123 struct xfs_inode *dest,
1124 loff_t pos_out, 1124 loff_t pos_out,
1125 loff_t remap_len) 1125 loff_t remap_len,
1126 loff_t *remapped)
1126{ 1127{
1127 struct xfs_bmbt_irec imap; 1128 struct xfs_bmbt_irec imap;
1128 xfs_fileoff_t srcoff; 1129 xfs_fileoff_t srcoff;
1129 xfs_fileoff_t destoff; 1130 xfs_fileoff_t destoff;
1130 xfs_filblks_t len; 1131 xfs_filblks_t len;
1131 xfs_filblks_t range_len; 1132 xfs_filblks_t range_len;
1133 xfs_filblks_t remapped_len = 0;
1132 xfs_off_t new_isize = pos_out + remap_len; 1134 xfs_off_t new_isize = pos_out + remap_len;
1133 int nimaps; 1135 int nimaps;
1134 int error = 0; 1136 int error = 0;
@@ -1175,10 +1177,13 @@ xfs_reflink_remap_blocks(
1175 srcoff += range_len; 1177 srcoff += range_len;
1176 destoff += range_len; 1178 destoff += range_len;
1177 len -= range_len; 1179 len -= range_len;
1180 remapped_len += range_len;
1178 } 1181 }
1179 1182
1180 if (error) 1183 if (error)
1181 trace_xfs_reflink_remap_blocks_error(dest, error, _RET_IP_); 1184 trace_xfs_reflink_remap_blocks_error(dest, error, _RET_IP_);
1185 *remapped = min_t(loff_t, remap_len,
1186 XFS_FSB_TO_B(src->i_mount, remapped_len));
1182 return error; 1187 return error;
1183} 1188}
1184 1189
@@ -1387,7 +1392,7 @@ out_unlock:
1387/* 1392/*
1388 * Link a range of blocks from one file to another. 1393 * Link a range of blocks from one file to another.
1389 */ 1394 */
1390int 1395loff_t
1391xfs_reflink_remap_range( 1396xfs_reflink_remap_range(
1392 struct file *file_in, 1397 struct file *file_in,
1393 loff_t pos_in, 1398 loff_t pos_in,
@@ -1401,8 +1406,9 @@ xfs_reflink_remap_range(
1401 struct inode *inode_out = file_inode(file_out); 1406 struct inode *inode_out = file_inode(file_out);
1402 struct xfs_inode *dest = XFS_I(inode_out); 1407 struct xfs_inode *dest = XFS_I(inode_out);
1403 struct xfs_mount *mp = src->i_mount; 1408 struct xfs_mount *mp = src->i_mount;
1409 loff_t remapped = 0;
1404 xfs_extlen_t cowextsize; 1410 xfs_extlen_t cowextsize;
1405 ssize_t ret; 1411 int ret;
1406 1412
1407 if (!xfs_sb_version_hasreflink(&mp->m_sb)) 1413 if (!xfs_sb_version_hasreflink(&mp->m_sb))
1408 return -EOPNOTSUPP; 1414 return -EOPNOTSUPP;
@@ -1418,7 +1424,8 @@ xfs_reflink_remap_range(
1418 1424
1419 trace_xfs_reflink_remap_range(src, pos_in, len, dest, pos_out); 1425 trace_xfs_reflink_remap_range(src, pos_in, len, dest, pos_out);
1420 1426
1421 ret = xfs_reflink_remap_blocks(src, pos_in, dest, pos_out, len); 1427 ret = xfs_reflink_remap_blocks(src, pos_in, dest, pos_out, len,
1428 &remapped);
1422 if (ret) 1429 if (ret)
1423 goto out_unlock; 1430 goto out_unlock;
1424 1431
@@ -1441,7 +1448,7 @@ out_unlock:
1441 xfs_reflink_remap_unlock(file_in, file_out); 1448 xfs_reflink_remap_unlock(file_in, file_out);
1442 if (ret) 1449 if (ret)
1443 trace_xfs_reflink_remap_range_error(dest, ret, _RET_IP_); 1450 trace_xfs_reflink_remap_range_error(dest, ret, _RET_IP_);
1444 return ret; 1451 return remapped > 0 ? remapped : ret;
1445} 1452}
1446 1453
1447/* 1454/*
diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h
index c3c46c276fe1..cbc26ff79a8f 100644
--- a/fs/xfs/xfs_reflink.h
+++ b/fs/xfs/xfs_reflink.h
@@ -27,7 +27,7 @@ extern int xfs_reflink_cancel_cow_range(struct xfs_inode *ip, xfs_off_t offset,
27extern int xfs_reflink_end_cow(struct xfs_inode *ip, xfs_off_t offset, 27extern int xfs_reflink_end_cow(struct xfs_inode *ip, xfs_off_t offset,
28 xfs_off_t count); 28 xfs_off_t count);
29extern int xfs_reflink_recover_cow(struct xfs_mount *mp); 29extern int xfs_reflink_recover_cow(struct xfs_mount *mp);
30extern int xfs_reflink_remap_range(struct file *file_in, loff_t pos_in, 30extern loff_t xfs_reflink_remap_range(struct file *file_in, loff_t pos_in,
31 struct file *file_out, loff_t pos_out, loff_t len, 31 struct file *file_out, loff_t pos_out, loff_t len,
32 unsigned int remap_flags); 32 unsigned int remap_flags);
33extern int xfs_reflink_inode_has_shared_extents(struct xfs_trans *tp, 33extern int xfs_reflink_inode_has_shared_extents(struct xfs_trans *tp,