|
@@ -1842,29 +1842,18 @@ xfs_swap_extent_forks(
|
|
|
}
|
|
|
|
|
|
/*
|
|
|
- * Before we've swapped the forks, lets set the owners of the forks
|
|
|
- * appropriately. We have to do this as we are demand paging the btree
|
|
|
- * buffers, and so the validation done on read will expect the owner
|
|
|
- * field to be correctly set. Once we change the owners, we can swap the
|
|
|
- * inode forks.
|
|
|
+ * Btree format (v3) inodes have the inode number stamped in the bmbt
|
|
|
+ * block headers. We can't start changing the bmbt blocks until the
|
|
|
+ * inode owner change is logged so recovery does the right thing in the
|
|
|
+ * event of a crash. Set the owner change log flags now and leave the
|
|
|
+ * bmbt scan as the last step.
|
|
|
*/
|
|
|
if (ip->i_d.di_version == 3 &&
|
|
|
- ip->i_d.di_format == XFS_DINODE_FMT_BTREE) {
|
|
|
+ ip->i_d.di_format == XFS_DINODE_FMT_BTREE)
|
|
|
(*target_log_flags) |= XFS_ILOG_DOWNER;
|
|
|
- error = xfs_bmbt_change_owner(tp, ip, XFS_DATA_FORK,
|
|
|
- tip->i_ino, NULL);
|
|
|
- if (error)
|
|
|
- return error;
|
|
|
- }
|
|
|
-
|
|
|
if (tip->i_d.di_version == 3 &&
|
|
|
- tip->i_d.di_format == XFS_DINODE_FMT_BTREE) {
|
|
|
+ tip->i_d.di_format == XFS_DINODE_FMT_BTREE)
|
|
|
(*src_log_flags) |= XFS_ILOG_DOWNER;
|
|
|
- error = xfs_bmbt_change_owner(tp, tip, XFS_DATA_FORK,
|
|
|
- ip->i_ino, NULL);
|
|
|
- if (error)
|
|
|
- return error;
|
|
|
- }
|
|
|
|
|
|
/*
|
|
|
* Swap the data forks of the inodes
|
|
@@ -2093,6 +2082,25 @@ xfs_swap_extents(
|
|
|
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_bmbt_change_owner(tp, ip, XFS_DATA_FORK,
|
|
|
+ ip->i_ino, NULL);
|
|
|
+ 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);
|
|
|
+ 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.
|