diff options
| author | Darrick J. Wong <darrick.wong@oracle.com> | 2018-10-29 19:47:26 -0400 |
|---|---|---|
| committer | Dave Chinner <david@fromorbit.com> | 2018-10-29 19:47:26 -0400 |
| commit | 3fc9f5e409319e994d113cf1327ba6ab147423c2 (patch) | |
| tree | c4829da4dca97ee610fb059363fef6362ab65bd2 /fs/xfs | |
| parent | 7a6ccf004e234c01fb2a11771de9837c9ff3d56d (diff) | |
xfs: remove xfs_reflink_remap_range
Since xfs_file_remap_range is a thin wrapper, move the contents of
xfs_reflink_remap_range into the shell. This cuts down on the vfs
calls being made from internal xfs code.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs')
| -rw-r--r-- | fs/xfs/xfs_file.c | 65 | ||||
| -rw-r--r-- | fs/xfs/xfs_reflink.c | 70 | ||||
| -rw-r--r-- | fs/xfs/xfs_reflink.h | 10 |
3 files changed, 70 insertions, 75 deletions
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c index 7d42ab8fe6e1..53c9ab8fb777 100644 --- a/fs/xfs/xfs_file.c +++ b/fs/xfs/xfs_file.c | |||
| @@ -919,20 +919,67 @@ out_unlock: | |||
| 919 | return error; | 919 | return error; |
| 920 | } | 920 | } |
| 921 | 921 | ||
| 922 | STATIC loff_t | 922 | |
| 923 | loff_t | ||
| 923 | xfs_file_remap_range( | 924 | xfs_file_remap_range( |
| 924 | struct file *file_in, | 925 | struct file *file_in, |
| 925 | loff_t pos_in, | 926 | loff_t pos_in, |
| 926 | struct file *file_out, | 927 | struct file *file_out, |
| 927 | loff_t pos_out, | 928 | loff_t pos_out, |
| 928 | loff_t len, | 929 | loff_t len, |
| 929 | unsigned int remap_flags) | 930 | unsigned int remap_flags) |
| 930 | { | 931 | { |
| 932 | struct inode *inode_in = file_inode(file_in); | ||
| 933 | struct xfs_inode *src = XFS_I(inode_in); | ||
| 934 | struct inode *inode_out = file_inode(file_out); | ||
| 935 | struct xfs_inode *dest = XFS_I(inode_out); | ||
| 936 | struct xfs_mount *mp = src->i_mount; | ||
| 937 | loff_t remapped = 0; | ||
| 938 | xfs_extlen_t cowextsize; | ||
| 939 | int ret; | ||
| 940 | |||
| 931 | if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY)) | 941 | if (remap_flags & ~(REMAP_FILE_DEDUP | REMAP_FILE_ADVISORY)) |
| 932 | return -EINVAL; | 942 | return -EINVAL; |
| 933 | 943 | ||
| 934 | return xfs_reflink_remap_range(file_in, pos_in, file_out, pos_out, | 944 | if (!xfs_sb_version_hasreflink(&mp->m_sb)) |
| 935 | len, remap_flags); | 945 | return -EOPNOTSUPP; |
| 946 | |||
| 947 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
| 948 | return -EIO; | ||
| 949 | |||
| 950 | /* Prepare and then clone file data. */ | ||
| 951 | ret = xfs_reflink_remap_prep(file_in, pos_in, file_out, pos_out, | ||
| 952 | &len, remap_flags); | ||
| 953 | if (ret < 0 || len == 0) | ||
| 954 | return ret; | ||
| 955 | |||
| 956 | trace_xfs_reflink_remap_range(src, pos_in, len, dest, pos_out); | ||
| 957 | |||
| 958 | ret = xfs_reflink_remap_blocks(src, pos_in, dest, pos_out, len, | ||
| 959 | &remapped); | ||
| 960 | if (ret) | ||
| 961 | goto out_unlock; | ||
| 962 | |||
| 963 | /* | ||
| 964 | * Carry the cowextsize hint from src to dest if we're sharing the | ||
| 965 | * entire source file to the entire destination file, the source file | ||
| 966 | * has a cowextsize hint, and the destination file does not. | ||
| 967 | */ | ||
| 968 | cowextsize = 0; | ||
| 969 | if (pos_in == 0 && len == i_size_read(inode_in) && | ||
| 970 | (src->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE) && | ||
| 971 | pos_out == 0 && len >= i_size_read(inode_out) && | ||
| 972 | !(dest->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE)) | ||
| 973 | cowextsize = src->i_d.di_cowextsize; | ||
| 974 | |||
| 975 | ret = xfs_reflink_update_dest(dest, pos_out + len, cowextsize, | ||
| 976 | remap_flags); | ||
| 977 | |||
| 978 | out_unlock: | ||
| 979 | xfs_reflink_remap_unlock(file_in, file_out); | ||
| 980 | if (ret) | ||
| 981 | trace_xfs_reflink_remap_range_error(dest, ret, _RET_IP_); | ||
| 982 | return remapped > 0 ? remapped : ret; | ||
| 936 | } | 983 | } |
| 937 | 984 | ||
| 938 | STATIC int | 985 | STATIC int |
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index bccc66316cc4..84f372f7ea04 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c | |||
| @@ -916,7 +916,7 @@ out_error: | |||
| 916 | /* | 916 | /* |
| 917 | * Update destination inode size & cowextsize hint, if necessary. | 917 | * Update destination inode size & cowextsize hint, if necessary. |
| 918 | */ | 918 | */ |
| 919 | STATIC int | 919 | int |
| 920 | xfs_reflink_update_dest( | 920 | xfs_reflink_update_dest( |
| 921 | struct xfs_inode *dest, | 921 | struct xfs_inode *dest, |
| 922 | xfs_off_t newlen, | 922 | xfs_off_t newlen, |
| @@ -1116,7 +1116,7 @@ out: | |||
| 1116 | /* | 1116 | /* |
| 1117 | * Iteratively remap one file's extents (and holes) to another's. | 1117 | * Iteratively remap one file's extents (and holes) to another's. |
| 1118 | */ | 1118 | */ |
| 1119 | STATIC int | 1119 | int |
| 1120 | xfs_reflink_remap_blocks( | 1120 | xfs_reflink_remap_blocks( |
| 1121 | struct xfs_inode *src, | 1121 | struct xfs_inode *src, |
| 1122 | loff_t pos_in, | 1122 | loff_t pos_in, |
| @@ -1232,7 +1232,7 @@ retry: | |||
| 1232 | } | 1232 | } |
| 1233 | 1233 | ||
| 1234 | /* Unlock both inodes after they've been prepped for a range clone. */ | 1234 | /* Unlock both inodes after they've been prepped for a range clone. */ |
| 1235 | STATIC void | 1235 | void |
| 1236 | xfs_reflink_remap_unlock( | 1236 | xfs_reflink_remap_unlock( |
| 1237 | struct file *file_in, | 1237 | struct file *file_in, |
| 1238 | struct file *file_out) | 1238 | struct file *file_out) |
| @@ -1300,7 +1300,7 @@ xfs_reflink_zero_posteof( | |||
| 1300 | * stale data in the destination file. Hence we reject these clone attempts with | 1300 | * stale data in the destination file. Hence we reject these clone attempts with |
| 1301 | * -EINVAL in this case. | 1301 | * -EINVAL in this case. |
| 1302 | */ | 1302 | */ |
| 1303 | STATIC int | 1303 | int |
| 1304 | xfs_reflink_remap_prep( | 1304 | xfs_reflink_remap_prep( |
| 1305 | struct file *file_in, | 1305 | struct file *file_in, |
| 1306 | loff_t pos_in, | 1306 | loff_t pos_in, |
| @@ -1371,68 +1371,6 @@ out_unlock: | |||
| 1371 | } | 1371 | } |
| 1372 | 1372 | ||
| 1373 | /* | 1373 | /* |
| 1374 | * Link a range of blocks from one file to another. | ||
| 1375 | */ | ||
| 1376 | loff_t | ||
| 1377 | xfs_reflink_remap_range( | ||
| 1378 | struct file *file_in, | ||
| 1379 | loff_t pos_in, | ||
| 1380 | struct file *file_out, | ||
| 1381 | loff_t pos_out, | ||
| 1382 | loff_t len, | ||
| 1383 | unsigned int remap_flags) | ||
| 1384 | { | ||
| 1385 | struct inode *inode_in = file_inode(file_in); | ||
| 1386 | struct xfs_inode *src = XFS_I(inode_in); | ||
| 1387 | struct inode *inode_out = file_inode(file_out); | ||
| 1388 | struct xfs_inode *dest = XFS_I(inode_out); | ||
| 1389 | struct xfs_mount *mp = src->i_mount; | ||
| 1390 | loff_t remapped = 0; | ||
| 1391 | xfs_extlen_t cowextsize; | ||
| 1392 | int ret; | ||
| 1393 | |||
| 1394 | if (!xfs_sb_version_hasreflink(&mp->m_sb)) | ||
| 1395 | return -EOPNOTSUPP; | ||
| 1396 | |||
| 1397 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
| 1398 | return -EIO; | ||
| 1399 | |||
| 1400 | /* Prepare and then clone file data. */ | ||
| 1401 | ret = xfs_reflink_remap_prep(file_in, pos_in, file_out, pos_out, | ||
| 1402 | &len, remap_flags); | ||
| 1403 | if (ret < 0 || len == 0) | ||
| 1404 | return ret; | ||
| 1405 | |||
| 1406 | trace_xfs_reflink_remap_range(src, pos_in, len, dest, pos_out); | ||
| 1407 | |||
| 1408 | ret = xfs_reflink_remap_blocks(src, pos_in, dest, pos_out, len, | ||
| 1409 | &remapped); | ||
| 1410 | if (ret) | ||
| 1411 | goto out_unlock; | ||
| 1412 | |||
| 1413 | /* | ||
| 1414 | * Carry the cowextsize hint from src to dest if we're sharing the | ||
| 1415 | * entire source file to the entire destination file, the source file | ||
| 1416 | * has a cowextsize hint, and the destination file does not. | ||
| 1417 | */ | ||
| 1418 | cowextsize = 0; | ||
| 1419 | if (pos_in == 0 && len == i_size_read(inode_in) && | ||
| 1420 | (src->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE) && | ||
| 1421 | pos_out == 0 && len >= i_size_read(inode_out) && | ||
| 1422 | !(dest->i_d.di_flags2 & XFS_DIFLAG2_COWEXTSIZE)) | ||
| 1423 | cowextsize = src->i_d.di_cowextsize; | ||
| 1424 | |||
| 1425 | ret = xfs_reflink_update_dest(dest, pos_out + len, cowextsize, | ||
| 1426 | remap_flags); | ||
| 1427 | |||
| 1428 | out_unlock: | ||
| 1429 | xfs_reflink_remap_unlock(file_in, file_out); | ||
| 1430 | if (ret) | ||
| 1431 | trace_xfs_reflink_remap_range_error(dest, ret, _RET_IP_); | ||
| 1432 | return remapped > 0 ? remapped : ret; | ||
| 1433 | } | ||
| 1434 | |||
| 1435 | /* | ||
| 1436 | * The user wants to preemptively CoW all shared blocks in this file, | 1374 | * The user wants to preemptively CoW all shared blocks in this file, |
| 1437 | * which enables us to turn off the reflink flag. Iterate all | 1375 | * which enables us to turn off the reflink flag. Iterate all |
| 1438 | * extents which are not prealloc/delalloc to see which ranges are | 1376 | * extents which are not prealloc/delalloc to see which ranges are |
diff --git a/fs/xfs/xfs_reflink.h b/fs/xfs/xfs_reflink.h index cbc26ff79a8f..28a84edda889 100644 --- a/fs/xfs/xfs_reflink.h +++ b/fs/xfs/xfs_reflink.h | |||
| @@ -36,5 +36,15 @@ extern int xfs_reflink_clear_inode_flag(struct xfs_inode *ip, | |||
| 36 | struct xfs_trans **tpp); | 36 | struct xfs_trans **tpp); |
| 37 | extern int xfs_reflink_unshare(struct xfs_inode *ip, xfs_off_t offset, | 37 | extern int xfs_reflink_unshare(struct xfs_inode *ip, xfs_off_t offset, |
| 38 | xfs_off_t len); | 38 | xfs_off_t len); |
| 39 | extern int xfs_reflink_remap_prep(struct file *file_in, loff_t pos_in, | ||
| 40 | struct file *file_out, loff_t pos_out, loff_t *len, | ||
| 41 | unsigned int remap_flags); | ||
| 42 | extern int xfs_reflink_remap_blocks(struct xfs_inode *src, loff_t pos_in, | ||
| 43 | struct xfs_inode *dest, loff_t pos_out, loff_t remap_len, | ||
| 44 | loff_t *remapped); | ||
| 45 | extern int xfs_reflink_update_dest(struct xfs_inode *dest, xfs_off_t newlen, | ||
| 46 | xfs_extlen_t cowextsize, unsigned int remap_flags); | ||
| 47 | extern void xfs_reflink_remap_unlock(struct file *file_in, | ||
| 48 | struct file *file_out); | ||
| 39 | 49 | ||
| 40 | #endif /* __XFS_REFLINK_H */ | 50 | #endif /* __XFS_REFLINK_H */ |
