summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2021-01-05 17:45:11 -0800
committerDarrick J. Wong <djwong@kernel.org>2021-03-25 17:08:28 -0700
commite67aad9ffe8e60fab2f94bbb2734e45ed99c324b (patch)
tree1785b6cb26833e902cdd684120570075cb5f5d34
parentdd1f35706fb26f1cff92cb7c1cbebb209f6b71d3 (diff)
xfs: consolidate all of the xfs_swap_extent_forks code
Consolidate the bmbt owner change scan code in xfs_swap_extent_forks, since it's not needed for the deferred bmap log item swapext implementation. The goal is to package up all three implementations into functions that have the same preconditions and leave the system in the same state. Signed-off-by: Darrick J. Wong <djwong@kernel.org>
-rw-r--r--fs/xfs/xfs_bmap_util.c212
1 files changed, 104 insertions, 108 deletions
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index 51d32e23885e..21a65ed63b20 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -1355,19 +1355,61 @@ xfs_swap_extent_flush(
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;
+}
+
/* Swap the extents of two files by swapping data forks. */
STATIC int
xfs_swap_extent_forks(
- struct xfs_trans *tp,
+ struct xfs_trans **tpp,
struct xfs_inode *ip,
- struct xfs_inode *tip,
- int *src_log_flags,
- int *target_log_flags)
+ struct xfs_inode *tip)
{
xfs_filblks_t aforkblks = 0;
xfs_filblks_t taforkblks = 0;
xfs_extnum_t junk;
uint64_t tmp;
+ int src_log_flags = XFS_ILOG_CORE;
+ int target_log_flags = XFS_ILOG_CORE;
int error;
/*
@@ -1375,14 +1417,14 @@ xfs_swap_extent_forks(
*/
if (XFS_IFORK_Q(ip) && ip->i_afp->if_nextents > 0 &&
ip->i_afp->if_format != XFS_DINODE_FMT_LOCAL) {
- error = xfs_bmap_count_blocks(tp, ip, XFS_ATTR_FORK, &junk,
+ error = xfs_bmap_count_blocks(*tpp, ip, XFS_ATTR_FORK, &junk,
&aforkblks);
if (error)
return error;
}
if (XFS_IFORK_Q(tip) && tip->i_afp->if_nextents > 0 &&
tip->i_afp->if_format != XFS_DINODE_FMT_LOCAL) {
- error = xfs_bmap_count_blocks(tp, tip, XFS_ATTR_FORK, &junk,
+ error = xfs_bmap_count_blocks(*tpp, tip, XFS_ATTR_FORK, &junk,
&taforkblks);
if (error)
return error;
@@ -1397,9 +1439,9 @@ xfs_swap_extent_forks(
*/
if (xfs_sb_version_has_v3inode(&ip->i_mount->m_sb)) {
if (ip->i_df.if_format == XFS_DINODE_FMT_BTREE)
- (*target_log_flags) |= XFS_ILOG_DOWNER;
+ target_log_flags |= XFS_ILOG_DOWNER;
if (tip->i_df.if_format == XFS_DINODE_FMT_BTREE)
- (*src_log_flags) |= XFS_ILOG_DOWNER;
+ src_log_flags |= XFS_ILOG_DOWNER;
}
/*
@@ -1429,69 +1471,78 @@ xfs_swap_extent_forks(
switch (ip->i_df.if_format) {
case XFS_DINODE_FMT_EXTENTS:
- (*src_log_flags) |= XFS_ILOG_DEXT;
+ src_log_flags |= XFS_ILOG_DEXT;
break;
case XFS_DINODE_FMT_BTREE:
ASSERT(!xfs_sb_version_has_v3inode(&ip->i_mount->m_sb) ||
- (*src_log_flags & XFS_ILOG_DOWNER));
- (*src_log_flags) |= XFS_ILOG_DBROOT;
+ (src_log_flags & XFS_ILOG_DOWNER));
+ src_log_flags |= XFS_ILOG_DBROOT;
break;
}
switch (tip->i_df.if_format) {
case XFS_DINODE_FMT_EXTENTS:
- (*target_log_flags) |= XFS_ILOG_DEXT;
+ target_log_flags |= XFS_ILOG_DEXT;
break;
case XFS_DINODE_FMT_BTREE:
- (*target_log_flags) |= XFS_ILOG_DBROOT;
+ target_log_flags |= XFS_ILOG_DBROOT;
ASSERT(!xfs_sb_version_has_v3inode(&ip->i_mount->m_sb) ||
- (*target_log_flags & XFS_ILOG_DOWNER));
+ (target_log_flags & XFS_ILOG_DOWNER));
break;
}
- return 0;
-}
+ /* Do we have to swap reflink flags? */
+ if ((ip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK) ^
+ (tip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK)) {
+ uint64_t f;
-/*
- * 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;
+ f = ip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK;
+ ip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK;
+ ip->i_d.di_flags2 |= tip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK;
+ tip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK;
+ tip->i_d.di_flags2 |= f & XFS_DIFLAG2_REFLINK;
+ }
- do {
- error = xfs_bmbt_change_owner(tp, ip, XFS_DATA_FORK, ip->i_ino,
- NULL);
- /* success or fatal error */
- if (error != -EAGAIN)
- break;
+ /* Swap the cow forks. */
+ if (xfs_sb_version_hasreflink(&ip->i_mount->m_sb)) {
+ ASSERT(!ip->i_cowfp ||
+ ip->i_cowfp->if_format == XFS_DINODE_FMT_EXTENTS);
+ ASSERT(!tip->i_cowfp ||
+ tip->i_cowfp->if_format == XFS_DINODE_FMT_EXTENTS);
- error = xfs_trans_roll(tpp);
- if (error)
- break;
- tp = *tpp;
+ swap(ip->i_cowfp, tip->i_cowfp);
- /*
- * 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);
+ if (ip->i_cowfp && ip->i_cowfp->if_bytes)
+ xfs_inode_set_cowblocks_tag(ip);
+ else
+ xfs_inode_clear_cowblocks_tag(ip);
+ if (tip->i_cowfp && tip->i_cowfp->if_bytes)
+ xfs_inode_set_cowblocks_tag(tip);
+ else
+ xfs_inode_clear_cowblocks_tag(tip);
+ }
- return error;
+ xfs_trans_log_inode(*tpp, ip, src_log_flags);
+ xfs_trans_log_inode(*tpp, tip, target_log_flags);
+
+ /*
+ * The extent forks have been swapped, but crc=1,rmapbt=0 filesystems
+ * have inode number owner values in the bmbt blocks that still refer to
+ * the old inode. Scan each bmbt to fix up the owner values with the
+ * inode number of the current inode.
+ */
+ if (src_log_flags & XFS_ILOG_DOWNER) {
+ error = xfs_swap_change_owner(tpp, ip, tip);
+ if (error)
+ return error;
+ }
+ if (target_log_flags & XFS_ILOG_DOWNER) {
+ error = xfs_swap_change_owner(tpp, tip, ip);
+ if (error)
+ return error;
+ }
+
+ return 0;
}
int
@@ -1503,10 +1554,8 @@ xfs_swap_extents(
struct xfs_mount *mp = ip->i_mount;
struct xfs_trans *tp;
struct xfs_bstat *sbp = &sxp->sx_stat;
- int src_log_flags, target_log_flags;
int error = 0;
int lock_flags;
- uint64_t f;
int resblks = 0;
unsigned int flags = 0;
@@ -1637,9 +1686,6 @@ xfs_swap_extents(
* recovery is going to see the fork as owned by the swapped inode,
* not the pre-swapped inodes.
*/
- src_log_flags = XFS_ILOG_CORE;
- target_log_flags = XFS_ILOG_CORE;
-
if (xfs_sb_version_hasrmapbt(&mp->m_sb)) {
struct xfs_swapext_req req = {
.ip1 = ip,
@@ -1650,62 +1696,12 @@ xfs_swap_extents(
};
error = xfs_swapext(&tp, &req);
} else
- error = xfs_swap_extent_forks(tp, ip, tip, &src_log_flags,
- &target_log_flags);
+ error = xfs_swap_extent_forks(&tp, ip, tip);
if (error) {
trace_xfs_swap_extent_error(ip, error, _THIS_IP_);
goto out_trans_cancel;
}
- /* Do we have to swap reflink flags? */
- if ((ip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK) ^
- (tip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK)) {
- f = ip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK;
- ip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK;
- ip->i_d.di_flags2 |= tip->i_d.di_flags2 & XFS_DIFLAG2_REFLINK;
- tip->i_d.di_flags2 &= ~XFS_DIFLAG2_REFLINK;
- tip->i_d.di_flags2 |= f & XFS_DIFLAG2_REFLINK;
- }
-
- /* Swap the cow forks. */
- if (xfs_sb_version_hasreflink(&mp->m_sb)) {
- ASSERT(!ip->i_cowfp ||
- ip->i_cowfp->if_format == XFS_DINODE_FMT_EXTENTS);
- ASSERT(!tip->i_cowfp ||
- tip->i_cowfp->if_format == XFS_DINODE_FMT_EXTENTS);
-
- swap(ip->i_cowfp, tip->i_cowfp);
-
- if (ip->i_cowfp && ip->i_cowfp->if_bytes)
- xfs_inode_set_cowblocks_tag(ip);
- else
- xfs_inode_clear_cowblocks_tag(ip);
- if (tip->i_cowfp && tip->i_cowfp->if_bytes)
- xfs_inode_set_cowblocks_tag(tip);
- else
- xfs_inode_clear_cowblocks_tag(tip);
- }
-
- xfs_trans_log_inode(tp, ip, src_log_flags);
- xfs_trans_log_inode(tp, tip, target_log_flags);
-
- /*
- * The extent forks have been swapped, but crc=1,rmapbt=0 filesystems
- * have inode number owner values in the bmbt blocks that still refer to
- * the old inode. Scan each bmbt to fix up the owner values with the
- * inode number of the current inode.
- */
- if (src_log_flags & XFS_ILOG_DOWNER) {
- error = xfs_swap_change_owner(&tp, ip, tip);
- if (error)
- goto out_trans_cancel;
- }
- if (target_log_flags & XFS_ILOG_DOWNER) {
- error = xfs_swap_change_owner(&tp, tip, ip);
- if (error)
- goto out_trans_cancel;
- }
-
/*
* If this is a synchronous mount, make sure that the
* transaction goes to disk before returning to the user.