diff options
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/xfs_file.c | 5 | ||||
-rw-r--r-- | fs/xfs/xfs_reflink.c | 17 | ||||
-rw-r--r-- | fs/xfs/xfs_reflink.h | 2 |
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 | ||
941 | STATIC int | 938 | STATIC 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 | */ |
1390 | int | 1395 | loff_t |
1391 | xfs_reflink_remap_range( | 1396 | xfs_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, | |||
27 | extern int xfs_reflink_end_cow(struct xfs_inode *ip, xfs_off_t offset, | 27 | extern int xfs_reflink_end_cow(struct xfs_inode *ip, xfs_off_t offset, |
28 | xfs_off_t count); | 28 | xfs_off_t count); |
29 | extern int xfs_reflink_recover_cow(struct xfs_mount *mp); | 29 | extern int xfs_reflink_recover_cow(struct xfs_mount *mp); |
30 | extern int xfs_reflink_remap_range(struct file *file_in, loff_t pos_in, | 30 | extern 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); |
33 | extern int xfs_reflink_inode_has_shared_extents(struct xfs_trans *tp, | 33 | extern int xfs_reflink_inode_has_shared_extents(struct xfs_trans *tp, |