|
@@ -1931,6 +1931,48 @@ xfs_swap_extent_forks(
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * Fix up the owners of the bmbt blocks to refer to the current inode. The
|
|
|
+ * change owner scan attempts to order all modified buffers in the current
|
|
|
+ * transaction. In the event of ordered buffer failure, the offending buffer is
|
|
|
+ * physically logged as a fallback and the scan returns -EAGAIN. We must roll
|
|
|
+ * the transaction in this case to replenish the fallback log reservation and
|
|
|
+ * restart the scan. This process repeats until the scan completes.
|
|
|
+ */
|
|
|
+static int
|
|
|
+xfs_swap_change_owner(
|
|
|
+ struct xfs_trans **tpp,
|
|
|
+ struct xfs_inode *ip,
|
|
|
+ struct xfs_inode *tmpip)
|
|
|
+{
|
|
|
+ int error;
|
|
|
+ struct xfs_trans *tp = *tpp;
|
|
|
+
|
|
|
+ do {
|
|
|
+ error = xfs_bmbt_change_owner(tp, ip, XFS_DATA_FORK, ip->i_ino,
|
|
|
+ NULL);
|
|
|
+ /* success or fatal error */
|
|
|
+ if (error != -EAGAIN)
|
|
|
+ break;
|
|
|
+
|
|
|
+ error = xfs_trans_roll(tpp);
|
|
|
+ if (error)
|
|
|
+ break;
|
|
|
+ tp = *tpp;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Redirty both inodes so they can relog and keep the log tail
|
|
|
+ * moving forward.
|
|
|
+ */
|
|
|
+ xfs_trans_ijoin(tp, ip, 0);
|
|
|
+ xfs_trans_ijoin(tp, tmpip, 0);
|
|
|
+ xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
|
|
|
+ xfs_trans_log_inode(tp, tmpip, XFS_ILOG_CORE);
|
|
|
+ } while (true);
|
|
|
+
|
|
|
+ return error;
|
|
|
+}
|
|
|
+
|
|
|
int
|
|
|
xfs_swap_extents(
|
|
|
struct xfs_inode *ip, /* target inode */
|
|
@@ -1945,7 +1987,7 @@ xfs_swap_extents(
|
|
|
int lock_flags;
|
|
|
struct xfs_ifork *cowfp;
|
|
|
uint64_t f;
|
|
|
- int resblks;
|
|
|
+ int resblks = 0;
|
|
|
|
|
|
/*
|
|
|
* Lock the inodes against other IO, page faults and truncate to
|
|
@@ -1993,11 +2035,8 @@ xfs_swap_extents(
|
|
|
XFS_SWAP_RMAP_SPACE_RES(mp,
|
|
|
XFS_IFORK_NEXTENTS(tip, XFS_DATA_FORK),
|
|
|
XFS_DATA_FORK);
|
|
|
- error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks,
|
|
|
- 0, 0, &tp);
|
|
|
- } else
|
|
|
- error = xfs_trans_alloc(mp, &M_RES(mp)->tr_ichange, 0,
|
|
|
- 0, 0, &tp);
|
|
|
+ }
|
|
|
+ error = xfs_trans_alloc(mp, &M_RES(mp)->tr_write, resblks, 0, 0, &tp);
|
|
|
if (error)
|
|
|
goto out_unlock;
|
|
|
|
|
@@ -2089,14 +2128,12 @@ xfs_swap_extents(
|
|
|
* inode number of the current inode.
|
|
|
*/
|
|
|
if (src_log_flags & XFS_ILOG_DOWNER) {
|
|
|
- error = xfs_bmbt_change_owner(tp, ip, XFS_DATA_FORK,
|
|
|
- ip->i_ino, NULL);
|
|
|
+ error = xfs_swap_change_owner(&tp, ip, tip);
|
|
|
if (error)
|
|
|
goto out_trans_cancel;
|
|
|
}
|
|
|
if (target_log_flags & XFS_ILOG_DOWNER) {
|
|
|
- error = xfs_bmbt_change_owner(tp, tip, XFS_DATA_FORK,
|
|
|
- tip->i_ino, NULL);
|
|
|
+ error = xfs_swap_change_owner(&tp, tip, ip);
|
|
|
if (error)
|
|
|
goto out_trans_cancel;
|
|
|
}
|