@@ -977,6 +977,146 @@ xfs_file_fallocate(
977
977
return error ;
978
978
}
979
979
980
+ /*
981
+ * Flush all file writes out to disk.
982
+ */
983
+ static int
984
+ xfs_file_wait_for_io (
985
+ struct inode * inode ,
986
+ loff_t offset ,
987
+ size_t len )
988
+ {
989
+ loff_t rounding ;
990
+ loff_t ioffset ;
991
+ loff_t iendoffset ;
992
+ loff_t bs ;
993
+ int ret ;
994
+
995
+ bs = inode -> i_sb -> s_blocksize ;
996
+ inode_dio_wait (inode );
997
+
998
+ rounding = max_t (xfs_off_t , bs , PAGE_SIZE );
999
+ ioffset = round_down (offset , rounding );
1000
+ iendoffset = round_up (offset + len , rounding ) - 1 ;
1001
+ ret = filemap_write_and_wait_range (inode -> i_mapping , ioffset ,
1002
+ iendoffset );
1003
+ return ret ;
1004
+ }
1005
+
1006
+ /* Hook up to the VFS reflink function */
1007
+ STATIC int
1008
+ xfs_file_share_range (
1009
+ struct file * file_in ,
1010
+ loff_t pos_in ,
1011
+ struct file * file_out ,
1012
+ loff_t pos_out ,
1013
+ u64 len )
1014
+ {
1015
+ struct inode * inode_in ;
1016
+ struct inode * inode_out ;
1017
+ ssize_t ret ;
1018
+ loff_t bs ;
1019
+ loff_t isize ;
1020
+ int same_inode ;
1021
+ loff_t blen ;
1022
+
1023
+ inode_in = file_inode (file_in );
1024
+ inode_out = file_inode (file_out );
1025
+ bs = inode_out -> i_sb -> s_blocksize ;
1026
+
1027
+ /* Don't touch certain kinds of inodes */
1028
+ if (IS_IMMUTABLE (inode_out ))
1029
+ return - EPERM ;
1030
+ if (IS_SWAPFILE (inode_in ) ||
1031
+ IS_SWAPFILE (inode_out ))
1032
+ return - ETXTBSY ;
1033
+
1034
+ /* Reflink only works within this filesystem. */
1035
+ if (inode_in -> i_sb != inode_out -> i_sb )
1036
+ return - EXDEV ;
1037
+ same_inode = (inode_in -> i_ino == inode_out -> i_ino );
1038
+
1039
+ /* Don't reflink dirs, pipes, sockets... */
1040
+ if (S_ISDIR (inode_in -> i_mode ) || S_ISDIR (inode_out -> i_mode ))
1041
+ return - EISDIR ;
1042
+ if (S_ISFIFO (inode_in -> i_mode ) || S_ISFIFO (inode_out -> i_mode ))
1043
+ return - EINVAL ;
1044
+ if (!S_ISREG (inode_in -> i_mode ) || !S_ISREG (inode_out -> i_mode ))
1045
+ return - EINVAL ;
1046
+
1047
+ /* Are we going all the way to the end? */
1048
+ isize = i_size_read (inode_in );
1049
+ if (isize == 0 )
1050
+ return 0 ;
1051
+ if (len == 0 )
1052
+ len = isize - pos_in ;
1053
+
1054
+ /* Ensure offsets don't wrap and the input is inside i_size */
1055
+ if (pos_in + len < pos_in || pos_out + len < pos_out ||
1056
+ pos_in + len > isize )
1057
+ return - EINVAL ;
1058
+
1059
+ /* If we're linking to EOF, continue to the block boundary. */
1060
+ if (pos_in + len == isize )
1061
+ blen = ALIGN (isize , bs ) - pos_in ;
1062
+ else
1063
+ blen = len ;
1064
+
1065
+ /* Only reflink if we're aligned to block boundaries */
1066
+ if (!IS_ALIGNED (pos_in , bs ) || !IS_ALIGNED (pos_in + blen , bs ) ||
1067
+ !IS_ALIGNED (pos_out , bs ) || !IS_ALIGNED (pos_out + blen , bs ))
1068
+ return - EINVAL ;
1069
+
1070
+ /* Don't allow overlapped reflink within the same file */
1071
+ if (same_inode && pos_out + blen > pos_in && pos_out < pos_in + blen )
1072
+ return - EINVAL ;
1073
+
1074
+ /* Wait for the completion of any pending IOs on srcfile */
1075
+ ret = xfs_file_wait_for_io (inode_in , pos_in , len );
1076
+ if (ret )
1077
+ goto out_unlock ;
1078
+ ret = xfs_file_wait_for_io (inode_out , pos_out , len );
1079
+ if (ret )
1080
+ goto out_unlock ;
1081
+
1082
+ ret = xfs_reflink_remap_range (XFS_I (inode_in ), pos_in , XFS_I (inode_out ),
1083
+ pos_out , len );
1084
+ if (ret < 0 )
1085
+ goto out_unlock ;
1086
+
1087
+ out_unlock :
1088
+ return ret ;
1089
+ }
1090
+
1091
+ STATIC ssize_t
1092
+ xfs_file_copy_range (
1093
+ struct file * file_in ,
1094
+ loff_t pos_in ,
1095
+ struct file * file_out ,
1096
+ loff_t pos_out ,
1097
+ size_t len ,
1098
+ unsigned int flags )
1099
+ {
1100
+ int error ;
1101
+
1102
+ error = xfs_file_share_range (file_in , pos_in , file_out , pos_out ,
1103
+ len );
1104
+ if (error )
1105
+ return error ;
1106
+ return len ;
1107
+ }
1108
+
1109
+ STATIC int
1110
+ xfs_file_clone_range (
1111
+ struct file * file_in ,
1112
+ loff_t pos_in ,
1113
+ struct file * file_out ,
1114
+ loff_t pos_out ,
1115
+ u64 len )
1116
+ {
1117
+ return xfs_file_share_range (file_in , pos_in , file_out , pos_out ,
1118
+ len );
1119
+ }
980
1120
981
1121
STATIC int
982
1122
xfs_file_open (
@@ -1637,6 +1777,8 @@ const struct file_operations xfs_file_operations = {
1637
1777
.release = xfs_file_release ,
1638
1778
.fsync = xfs_file_fsync ,
1639
1779
.fallocate = xfs_file_fallocate ,
1780
+ .copy_file_range = xfs_file_copy_range ,
1781
+ .clone_file_range = xfs_file_clone_range ,
1640
1782
};
1641
1783
1642
1784
const struct file_operations xfs_dir_file_operations = {
0 commit comments