diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-17 21:44:00 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-17 21:44:00 -0500 |
commit | 0110c350c86d511be2130cb2a30dcbb76c4af750 (patch) | |
tree | d343a9e0fcb586a7110b13d411b314d33d404c08 /fs/xfs/xfs_reflink.c | |
parent | d9cb5bfcc3339f1a63df8fe0af8cece33c83c3af (diff) | |
parent | 9763f7a4a5f7b1a7c480fa06d01b2bad25163c0a (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull more vfs updates from Al Viro:
"In this pile:
- autofs-namespace series
- dedupe stuff
- more struct path constification"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: (40 commits)
ocfs2: implement the VFS clone_range, copy_range, and dedupe_range features
ocfs2: charge quota for reflinked blocks
ocfs2: fix bad pointer cast
ocfs2: always unlock when completing dio writes
ocfs2: don't eat io errors during _dio_end_io_write
ocfs2: budget for extent tree splits when adding refcount flag
ocfs2: prohibit refcounted swapfiles
ocfs2: add newlines to some error messages
ocfs2: convert inode refcount test to a helper
simple_write_end(): don't zero in short copy into uptodate
exofs: don't mess with simple_write_{begin,end}
9p: saner ->write_end() on failing copy into non-uptodate page
fix gfs2_stuffed_write_end() on short copies
fix ceph_write_end()
nfs_write_end(): fix handling of short copies
vfs: refactor clone/dedupe_file_range common functions
fs: try to clone files first in vfs_copy_file_range
vfs: misc struct path constification
namespace.c: constify struct path passed to a bunch of primitives
quota: constify struct path in quota_on
...
Diffstat (limited to 'fs/xfs/xfs_reflink.c')
-rw-r--r-- | fs/xfs/xfs_reflink.c | 219 |
1 files changed, 9 insertions, 210 deletions
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c index 88fd03c66e99..aca2d4bd4303 100644 --- a/fs/xfs/xfs_reflink.c +++ b/fs/xfs/xfs_reflink.c | |||
@@ -1114,111 +1114,6 @@ err: | |||
1114 | } | 1114 | } |
1115 | 1115 | ||
1116 | /* | 1116 | /* |
1117 | * Read a page's worth of file data into the page cache. Return the page | ||
1118 | * locked. | ||
1119 | */ | ||
1120 | static struct page * | ||
1121 | xfs_get_page( | ||
1122 | struct inode *inode, | ||
1123 | xfs_off_t offset) | ||
1124 | { | ||
1125 | struct address_space *mapping; | ||
1126 | struct page *page; | ||
1127 | pgoff_t n; | ||
1128 | |||
1129 | n = offset >> PAGE_SHIFT; | ||
1130 | mapping = inode->i_mapping; | ||
1131 | page = read_mapping_page(mapping, n, NULL); | ||
1132 | if (IS_ERR(page)) | ||
1133 | return page; | ||
1134 | if (!PageUptodate(page)) { | ||
1135 | put_page(page); | ||
1136 | return ERR_PTR(-EIO); | ||
1137 | } | ||
1138 | lock_page(page); | ||
1139 | return page; | ||
1140 | } | ||
1141 | |||
1142 | /* | ||
1143 | * Compare extents of two files to see if they are the same. | ||
1144 | */ | ||
1145 | static int | ||
1146 | xfs_compare_extents( | ||
1147 | struct inode *src, | ||
1148 | xfs_off_t srcoff, | ||
1149 | struct inode *dest, | ||
1150 | xfs_off_t destoff, | ||
1151 | xfs_off_t len, | ||
1152 | bool *is_same) | ||
1153 | { | ||
1154 | xfs_off_t src_poff; | ||
1155 | xfs_off_t dest_poff; | ||
1156 | void *src_addr; | ||
1157 | void *dest_addr; | ||
1158 | struct page *src_page; | ||
1159 | struct page *dest_page; | ||
1160 | xfs_off_t cmp_len; | ||
1161 | bool same; | ||
1162 | int error; | ||
1163 | |||
1164 | error = -EINVAL; | ||
1165 | same = true; | ||
1166 | while (len) { | ||
1167 | src_poff = srcoff & (PAGE_SIZE - 1); | ||
1168 | dest_poff = destoff & (PAGE_SIZE - 1); | ||
1169 | cmp_len = min(PAGE_SIZE - src_poff, | ||
1170 | PAGE_SIZE - dest_poff); | ||
1171 | cmp_len = min(cmp_len, len); | ||
1172 | ASSERT(cmp_len > 0); | ||
1173 | |||
1174 | trace_xfs_reflink_compare_extents(XFS_I(src), srcoff, cmp_len, | ||
1175 | XFS_I(dest), destoff); | ||
1176 | |||
1177 | src_page = xfs_get_page(src, srcoff); | ||
1178 | if (IS_ERR(src_page)) { | ||
1179 | error = PTR_ERR(src_page); | ||
1180 | goto out_error; | ||
1181 | } | ||
1182 | dest_page = xfs_get_page(dest, destoff); | ||
1183 | if (IS_ERR(dest_page)) { | ||
1184 | error = PTR_ERR(dest_page); | ||
1185 | unlock_page(src_page); | ||
1186 | put_page(src_page); | ||
1187 | goto out_error; | ||
1188 | } | ||
1189 | src_addr = kmap_atomic(src_page); | ||
1190 | dest_addr = kmap_atomic(dest_page); | ||
1191 | |||
1192 | flush_dcache_page(src_page); | ||
1193 | flush_dcache_page(dest_page); | ||
1194 | |||
1195 | if (memcmp(src_addr + src_poff, dest_addr + dest_poff, cmp_len)) | ||
1196 | same = false; | ||
1197 | |||
1198 | kunmap_atomic(dest_addr); | ||
1199 | kunmap_atomic(src_addr); | ||
1200 | unlock_page(dest_page); | ||
1201 | unlock_page(src_page); | ||
1202 | put_page(dest_page); | ||
1203 | put_page(src_page); | ||
1204 | |||
1205 | if (!same) | ||
1206 | break; | ||
1207 | |||
1208 | srcoff += cmp_len; | ||
1209 | destoff += cmp_len; | ||
1210 | len -= cmp_len; | ||
1211 | } | ||
1212 | |||
1213 | *is_same = same; | ||
1214 | return 0; | ||
1215 | |||
1216 | out_error: | ||
1217 | trace_xfs_reflink_compare_extents_error(XFS_I(dest), error, _RET_IP_); | ||
1218 | return error; | ||
1219 | } | ||
1220 | |||
1221 | /* | ||
1222 | * Link a range of blocks from one file to another. | 1117 | * Link a range of blocks from one file to another. |
1223 | */ | 1118 | */ |
1224 | int | 1119 | int |
@@ -1235,14 +1130,11 @@ xfs_reflink_remap_range( | |||
1235 | struct inode *inode_out = file_inode(file_out); | 1130 | struct inode *inode_out = file_inode(file_out); |
1236 | struct xfs_inode *dest = XFS_I(inode_out); | 1131 | struct xfs_inode *dest = XFS_I(inode_out); |
1237 | struct xfs_mount *mp = src->i_mount; | 1132 | struct xfs_mount *mp = src->i_mount; |
1238 | loff_t bs = inode_out->i_sb->s_blocksize; | ||
1239 | bool same_inode = (inode_in == inode_out); | 1133 | bool same_inode = (inode_in == inode_out); |
1240 | xfs_fileoff_t sfsbno, dfsbno; | 1134 | xfs_fileoff_t sfsbno, dfsbno; |
1241 | xfs_filblks_t fsblen; | 1135 | xfs_filblks_t fsblen; |
1242 | xfs_extlen_t cowextsize; | 1136 | xfs_extlen_t cowextsize; |
1243 | loff_t isize; | ||
1244 | ssize_t ret; | 1137 | ssize_t ret; |
1245 | loff_t blen; | ||
1246 | 1138 | ||
1247 | if (!xfs_sb_version_hasreflink(&mp->m_sb)) | 1139 | if (!xfs_sb_version_hasreflink(&mp->m_sb)) |
1248 | return -EOPNOTSUPP; | 1140 | return -EOPNOTSUPP; |
@@ -1257,26 +1149,8 @@ xfs_reflink_remap_range( | |||
1257 | else | 1149 | else |
1258 | xfs_lock_two_inodes(src, dest, XFS_MMAPLOCK_EXCL); | 1150 | xfs_lock_two_inodes(src, dest, XFS_MMAPLOCK_EXCL); |
1259 | 1151 | ||
1260 | /* Don't touch certain kinds of inodes */ | 1152 | /* Check file eligibility and prepare for block sharing. */ |
1261 | ret = -EPERM; | ||
1262 | if (IS_IMMUTABLE(inode_out)) | ||
1263 | goto out_unlock; | ||
1264 | |||
1265 | ret = -ETXTBSY; | ||
1266 | if (IS_SWAPFILE(inode_in) || IS_SWAPFILE(inode_out)) | ||
1267 | goto out_unlock; | ||
1268 | |||
1269 | |||
1270 | /* Don't reflink dirs, pipes, sockets... */ | ||
1271 | ret = -EISDIR; | ||
1272 | if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode)) | ||
1273 | goto out_unlock; | ||
1274 | ret = -EINVAL; | 1153 | ret = -EINVAL; |
1275 | if (S_ISFIFO(inode_in->i_mode) || S_ISFIFO(inode_out->i_mode)) | ||
1276 | goto out_unlock; | ||
1277 | if (!S_ISREG(inode_in->i_mode) || !S_ISREG(inode_out->i_mode)) | ||
1278 | goto out_unlock; | ||
1279 | |||
1280 | /* Don't reflink realtime inodes */ | 1154 | /* Don't reflink realtime inodes */ |
1281 | if (XFS_IS_REALTIME_INODE(src) || XFS_IS_REALTIME_INODE(dest)) | 1155 | if (XFS_IS_REALTIME_INODE(src) || XFS_IS_REALTIME_INODE(dest)) |
1282 | goto out_unlock; | 1156 | goto out_unlock; |
@@ -1285,97 +1159,18 @@ xfs_reflink_remap_range( | |||
1285 | if (IS_DAX(inode_in) || IS_DAX(inode_out)) | 1159 | if (IS_DAX(inode_in) || IS_DAX(inode_out)) |
1286 | goto out_unlock; | 1160 | goto out_unlock; |
1287 | 1161 | ||
1288 | /* Are we going all the way to the end? */ | 1162 | ret = vfs_clone_file_prep_inodes(inode_in, pos_in, inode_out, pos_out, |
1289 | isize = i_size_read(inode_in); | 1163 | &len, is_dedupe); |
1290 | if (isize == 0) { | 1164 | if (ret || len == 0) |
1291 | ret = 0; | ||
1292 | goto out_unlock; | ||
1293 | } | ||
1294 | |||
1295 | /* Zero length dedupe exits immediately; reflink goes to EOF. */ | ||
1296 | if (len == 0) { | ||
1297 | if (is_dedupe) { | ||
1298 | ret = 0; | ||
1299 | goto out_unlock; | ||
1300 | } | ||
1301 | len = isize - pos_in; | ||
1302 | } | ||
1303 | |||
1304 | /* Ensure offsets don't wrap and the input is inside i_size */ | ||
1305 | if (pos_in + len < pos_in || pos_out + len < pos_out || | ||
1306 | pos_in + len > isize) | ||
1307 | goto out_unlock; | ||
1308 | |||
1309 | /* Don't allow dedupe past EOF in the dest file */ | ||
1310 | if (is_dedupe) { | ||
1311 | loff_t disize; | ||
1312 | |||
1313 | disize = i_size_read(inode_out); | ||
1314 | if (pos_out >= disize || pos_out + len > disize) | ||
1315 | goto out_unlock; | ||
1316 | } | ||
1317 | |||
1318 | /* If we're linking to EOF, continue to the block boundary. */ | ||
1319 | if (pos_in + len == isize) | ||
1320 | blen = ALIGN(isize, bs) - pos_in; | ||
1321 | else | ||
1322 | blen = len; | ||
1323 | |||
1324 | /* Only reflink if we're aligned to block boundaries */ | ||
1325 | if (!IS_ALIGNED(pos_in, bs) || !IS_ALIGNED(pos_in + blen, bs) || | ||
1326 | !IS_ALIGNED(pos_out, bs) || !IS_ALIGNED(pos_out + blen, bs)) | ||
1327 | goto out_unlock; | ||
1328 | |||
1329 | /* Don't allow overlapped reflink within the same file */ | ||
1330 | if (same_inode) { | ||
1331 | if (pos_out + blen > pos_in && pos_out < pos_in + blen) | ||
1332 | goto out_unlock; | ||
1333 | } | ||
1334 | |||
1335 | /* Wait for the completion of any pending IOs on both files */ | ||
1336 | inode_dio_wait(inode_in); | ||
1337 | if (!same_inode) | ||
1338 | inode_dio_wait(inode_out); | ||
1339 | |||
1340 | ret = filemap_write_and_wait_range(inode_in->i_mapping, | ||
1341 | pos_in, pos_in + len - 1); | ||
1342 | if (ret) | ||
1343 | goto out_unlock; | ||
1344 | |||
1345 | ret = filemap_write_and_wait_range(inode_out->i_mapping, | ||
1346 | pos_out, pos_out + len - 1); | ||
1347 | if (ret) | ||
1348 | goto out_unlock; | 1165 | goto out_unlock; |
1349 | 1166 | ||
1350 | trace_xfs_reflink_remap_range(src, pos_in, len, dest, pos_out); | 1167 | trace_xfs_reflink_remap_range(src, pos_in, len, dest, pos_out); |
1351 | 1168 | ||
1352 | /* | 1169 | /* Set flags and remap blocks. */ |
1353 | * Check that the extents are the same. | ||
1354 | */ | ||
1355 | if (is_dedupe) { | ||
1356 | bool is_same = false; | ||
1357 | |||
1358 | ret = xfs_compare_extents(inode_in, pos_in, inode_out, pos_out, | ||
1359 | len, &is_same); | ||
1360 | if (ret) | ||
1361 | goto out_unlock; | ||
1362 | if (!is_same) { | ||
1363 | ret = -EBADE; | ||
1364 | goto out_unlock; | ||
1365 | } | ||
1366 | } | ||
1367 | |||
1368 | ret = xfs_reflink_set_inode_flag(src, dest); | 1170 | ret = xfs_reflink_set_inode_flag(src, dest); |
1369 | if (ret) | 1171 | if (ret) |
1370 | goto out_unlock; | 1172 | goto out_unlock; |
1371 | 1173 | ||
1372 | /* | ||
1373 | * Invalidate the page cache so that we can clear any CoW mappings | ||
1374 | * in the destination file. | ||
1375 | */ | ||
1376 | truncate_inode_pages_range(&inode_out->i_data, pos_out, | ||
1377 | PAGE_ALIGN(pos_out + len) - 1); | ||
1378 | |||
1379 | dfsbno = XFS_B_TO_FSBT(mp, pos_out); | 1174 | dfsbno = XFS_B_TO_FSBT(mp, pos_out); |
1380 | sfsbno = XFS_B_TO_FSBT(mp, pos_in); | 1175 | sfsbno = XFS_B_TO_FSBT(mp, pos_in); |
1381 | fsblen = XFS_B_TO_FSB(mp, len); | 1176 | fsblen = XFS_B_TO_FSB(mp, len); |
@@ -1384,6 +1179,10 @@ xfs_reflink_remap_range( | |||
1384 | if (ret) | 1179 | if (ret) |
1385 | goto out_unlock; | 1180 | goto out_unlock; |
1386 | 1181 | ||
1182 | /* Zap any page cache for the destination file's range. */ | ||
1183 | truncate_inode_pages_range(&inode_out->i_data, pos_out, | ||
1184 | PAGE_ALIGN(pos_out + len) - 1); | ||
1185 | |||
1387 | /* | 1186 | /* |
1388 | * Carry the cowextsize hint from src to dest if we're sharing the | 1187 | * Carry the cowextsize hint from src to dest if we're sharing the |
1389 | * entire source file to the entire destination file, the source file | 1188 | * entire source file to the entire destination file, the source file |