aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDarrick J. Wong <darrick.wong@oracle.com>2018-01-18 16:55:20 -0500
committerDarrick J. Wong <darrick.wong@oracle.com>2018-01-29 10:27:23 -0500
commit1364b1d4b5df31a05b6a3e6fdeb5371dbd4bd8ac (patch)
tree369c911b5143351fbc4ae7585673c07a0c1e4b72
parentc47b74fb2dba46642fc9c2581a28893b42a42815 (diff)
xfs: reflink should break pnfs leases before sharing blocks
Before we share blocks between files, we need to break the pnfs leases on the layout before we start slicing and dicing the block map. The structure of this function sets us up for the lock contention reduction in the next patch. Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
-rw-r--r--fs/xfs/xfs_reflink.c48
1 files changed, 47 insertions, 1 deletions
diff --git a/fs/xfs/xfs_reflink.c b/fs/xfs/xfs_reflink.c
index bcc2ad4f0899..bac464f0bc59 100644
--- a/fs/xfs/xfs_reflink.c
+++ b/fs/xfs/xfs_reflink.c
@@ -1245,6 +1245,50 @@ err:
1245} 1245}
1246 1246
1247/* 1247/*
1248 * Grab the exclusive iolock for a data copy from src to dest, making
1249 * sure to abide vfs locking order (lowest pointer value goes first) and
1250 * breaking the pnfs layout leases on dest before proceeding. The loop
1251 * is needed because we cannot call the blocking break_layout() with the
1252 * src iolock held, and therefore have to back out both locks.
1253 */
1254static int
1255xfs_iolock_two_inodes_and_break_layout(
1256 struct inode *src,
1257 struct inode *dest)
1258{
1259 int error;
1260
1261retry:
1262 if (src < dest) {
1263 inode_lock(src);
1264 inode_lock_nested(dest, I_MUTEX_NONDIR2);
1265 } else {
1266 /* src >= dest */
1267 inode_lock(dest);
1268 }
1269
1270 error = break_layout(dest, false);
1271 if (error == -EWOULDBLOCK) {
1272 inode_unlock(dest);
1273 if (src < dest)
1274 inode_unlock(src);
1275 error = break_layout(dest, true);
1276 if (error)
1277 return error;
1278 goto retry;
1279 }
1280 if (error) {
1281 inode_unlock(dest);
1282 if (src < dest)
1283 inode_unlock(src);
1284 return error;
1285 }
1286 if (src > dest)
1287 inode_lock_nested(src, I_MUTEX_NONDIR2);
1288 return 0;
1289}
1290
1291/*
1248 * Link a range of blocks from one file to another. 1292 * Link a range of blocks from one file to another.
1249 */ 1293 */
1250int 1294int
@@ -1274,7 +1318,9 @@ xfs_reflink_remap_range(
1274 return -EIO; 1318 return -EIO;
1275 1319
1276 /* Lock both files against IO */ 1320 /* Lock both files against IO */
1277 lock_two_nondirectories(inode_in, inode_out); 1321 ret = xfs_iolock_two_inodes_and_break_layout(inode_in, inode_out);
1322 if (ret)
1323 return ret;
1278 if (same_inode) 1324 if (same_inode)
1279 xfs_ilock(src, XFS_MMAPLOCK_EXCL); 1325 xfs_ilock(src, XFS_MMAPLOCK_EXCL);
1280 else 1326 else