aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_reflink.c
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2018-01-18 17:07:53 -0500
committerDarrick J. Wong <darrick.wong@oracle.com>2018-01-29 10:27:23 -0500
commit01c2e13dcae9757ea987af8933f9fcc6e33f2d7c (patch)
tree369b006ec50bc6d70de8a3085482e9bc49655068 /fs/xfs/xfs_reflink.c
parent7c2d238ac6c435c07780a54719760da2beb46a43 (diff)
xfs: only grab shared inode locks for source file during reflink
Reflink and dedupe operations remap blocks from a source file into a destination file. The destination file needs exclusive locks on all levels because we're updating its block map, but the source file isn't undergoing any block map changes so we can use a shared lock. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
Diffstat (limited to 'fs/xfs/xfs_reflink.c')
-rw-r--r--fs/xfs/xfs_reflink.c25
1 files changed, 15 insertions, 10 deletions
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index bcc58c24287c..85a119e1463b 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -1202,13 +1202,16 @@ xfs_reflink_remap_blocks(
1202 1202
1203 /* drange = (destoff, destoff + len); srange = (srcoff, srcoff + len) */ 1203 /* drange = (destoff, destoff + len); srange = (srcoff, srcoff + len) */
1204 while (len) { 1204 while (len) {
1205 uint lock_mode;
1206
1205 trace_xfs_reflink_remap_blocks_loop(src, srcoff, len, 1207 trace_xfs_reflink_remap_blocks_loop(src, srcoff, len,
1206 dest, destoff); 1208 dest, destoff);
1209
1207 /* Read extent from the source file */ 1210 /* Read extent from the source file */
1208 nimaps = 1; 1211 nimaps = 1;
1209 xfs_ilock(src, XFS_ILOCK_EXCL); 1212 lock_mode = xfs_ilock_data_map_shared(src);
1210 error = xfs_bmapi_read(src, srcoff, len, &imap, &nimaps, 0); 1213 error = xfs_bmapi_read(src, srcoff, len, &imap, &nimaps, 0);
1211 xfs_iunlock(src, XFS_ILOCK_EXCL); 1214 xfs_iunlock(src, lock_mode);
1212 if (error) 1215 if (error)
1213 goto err; 1216 goto err;
1214 ASSERT(nimaps == 1); 1217 ASSERT(nimaps == 1);
@@ -1260,7 +1263,7 @@ xfs_iolock_two_inodes_and_break_layout(
1260 1263
1261retry: 1264retry:
1262 if (src < dest) { 1265 if (src < dest) {
1263 inode_lock(src); 1266 inode_lock_shared(src);
1264 inode_lock_nested(dest, I_MUTEX_NONDIR2); 1267 inode_lock_nested(dest, I_MUTEX_NONDIR2);
1265 } else { 1268 } else {
1266 /* src >= dest */ 1269 /* src >= dest */
@@ -1271,7 +1274,7 @@ retry:
1271 if (error == -EWOULDBLOCK) { 1274 if (error == -EWOULDBLOCK) {
1272 inode_unlock(dest); 1275 inode_unlock(dest);
1273 if (src < dest) 1276 if (src < dest)
1274 inode_unlock(src); 1277 inode_unlock_shared(src);
1275 error = break_layout(dest, true); 1278 error = break_layout(dest, true);
1276 if (error) 1279 if (error)
1277 return error; 1280 return error;
@@ -1280,11 +1283,11 @@ retry:
1280 if (error) { 1283 if (error) {
1281 inode_unlock(dest); 1284 inode_unlock(dest);
1282 if (src < dest) 1285 if (src < dest)
1283 inode_unlock(src); 1286 inode_unlock_shared(src);
1284 return error; 1287 return error;
1285 } 1288 }
1286 if (src > dest) 1289 if (src > dest)
1287 inode_lock_nested(src, I_MUTEX_NONDIR2); 1290 inode_lock_shared_nested(src, I_MUTEX_NONDIR2);
1288 return 0; 1291 return 0;
1289} 1292}
1290 1293
@@ -1324,7 +1327,7 @@ xfs_reflink_remap_range(
1324 if (same_inode) 1327 if (same_inode)
1325 xfs_ilock(src, XFS_MMAPLOCK_EXCL); 1328 xfs_ilock(src, XFS_MMAPLOCK_EXCL);
1326 else 1329 else
1327 xfs_lock_two_inodes(src, XFS_MMAPLOCK_EXCL, dest, 1330 xfs_lock_two_inodes(src, XFS_MMAPLOCK_SHARED, dest,
1328 XFS_MMAPLOCK_EXCL); 1331 XFS_MMAPLOCK_EXCL);
1329 1332
1330 /* Check file eligibility and prepare for block sharing. */ 1333 /* Check file eligibility and prepare for block sharing. */
@@ -1393,10 +1396,12 @@ xfs_reflink_remap_range(
1393 is_dedupe); 1396 is_dedupe);
1394 1397
1395out_unlock: 1398out_unlock:
1396 xfs_iunlock(src, XFS_MMAPLOCK_EXCL); 1399 xfs_iunlock(dest, XFS_MMAPLOCK_EXCL);
1400 if (!same_inode)
1401 xfs_iunlock(src, XFS_MMAPLOCK_SHARED);
1402 inode_unlock(inode_out);
1397 if (!same_inode) 1403 if (!same_inode)
1398 xfs_iunlock(dest, XFS_MMAPLOCK_EXCL); 1404 inode_unlock_shared(inode_in);
1399 unlock_two_nondirectories(inode_in, inode_out);
1400 if (ret) 1405 if (ret)
1401 trace_xfs_reflink_remap_range_error(dest, ret, _RET_IP_); 1406 trace_xfs_reflink_remap_range_error(dest, ret, _RET_IP_);
1402 return ret; 1407 return ret;