@@ -2745,27 +2745,40 @@ xfs_finish_rename(
*/
STATIC int
xfs_cross_rename(
- struct xfs_trans *tp,
- struct xfs_inode *dp1,
- struct xfs_name *name1,
- struct xfs_inode *ip1,
- struct xfs_inode *dp2,
- struct xfs_name *name2,
- struct xfs_inode *ip2,
- int spaceres)
-{
- int error = 0;
- int ip1_flags = 0;
- int ip2_flags = 0;
- int dp2_flags = 0;
+ struct xfs_trans *tp,
+ struct xfs_inode *dp1,
+ struct xfs_name *name1,
+ struct xfs_inode *ip1,
+ struct xfs_inode *dp2,
+ struct xfs_name *name2,
+ struct xfs_inode *ip2,
+ int spaceres)
+{
+ struct xfs_mount *mp = dp1->i_mount;
+ int error = 0;
+ int ip1_flags = 0;
+ int ip2_flags = 0;
+ int dp2_flags = 0;
+ int new_diroffset, old_diroffset;
+ struct xfs_parent_defer *parent_ptr = NULL;
+ struct xfs_parent_defer *parent_ptr2 = NULL;
+
+ if (xfs_has_parent(mp)) {
+ error = xfs_parent_init(mp, &parent_ptr);
+ if (error)
+ goto out_trans_abort;
+ error = xfs_parent_init(mp, &parent_ptr2);
+ if (error)
+ goto out_trans_abort;
+ }
/* Swap inode number for dirent in first parent */
- error = xfs_dir_replace(tp, dp1, name1, ip2->i_ino, spaceres, NULL);
+ error = xfs_dir_replace(tp, dp1, name1, ip2->i_ino, spaceres, &old_diroffset);
if (error)
goto out_trans_abort;
/* Swap inode number for dirent in second parent */
- error = xfs_dir_replace(tp, dp2, name2, ip1->i_ino, spaceres, NULL);
+ error = xfs_dir_replace(tp, dp2, name2, ip1->i_ino, spaceres, &new_diroffset);
if (error)
goto out_trans_abort;
@@ -2826,6 +2839,18 @@ xfs_cross_rename(
}
}
+ if (xfs_has_parent(mp)) {
+ error = xfs_parent_defer_replace(tp, parent_ptr, dp1,
+ old_diroffset, name2, dp2, new_diroffset, ip1);
+ if (error)
+ goto out_trans_abort;
+
+ error = xfs_parent_defer_replace(tp, parent_ptr2, dp2,
+ new_diroffset, name1, dp1, old_diroffset, ip2);
+ if (error)
+ goto out_trans_abort;
+ }
+
if (ip1_flags) {
xfs_trans_ichgtime(tp, ip1, ip1_flags);
xfs_trans_log_inode(tp, ip1, XFS_ILOG_CORE);
@@ -2840,10 +2865,17 @@ xfs_cross_rename(
}
xfs_trans_ichgtime(tp, dp1, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG);
xfs_trans_log_inode(tp, dp1, XFS_ILOG_CORE);
- return xfs_finish_rename(tp);
+ error = xfs_finish_rename(tp);
+ goto out;
out_trans_abort:
xfs_trans_cancel(tp);
+out:
+ if (parent_ptr)
+ xfs_parent_cancel(mp, parent_ptr);
+ if (parent_ptr2)
+ xfs_parent_cancel(mp, parent_ptr2);
+
return error;
}