From: Allison Henderson <allison.henderson@xxxxxxxxxx> This patch removes the old parent pointer attribute during the rename operation, and re-adds the updated parent pointer. In the case of xfs_cross_rename, we modify the routine not to roll the transaction just yet. We will do this after the parent pointer is added in the calling xfs_rename function. Source kernel commit: d00721b30fd1923f6e9e9c1ca6f2a74cfc4ed5d3 Signed-off-by: Allison Henderson <allison.henderson@xxxxxxxxxx> --- libxfs/xfs_attr.c | 2 +- libxfs/xfs_attr.h | 1 + libxfs/xfs_parent.c | 31 +++++++++++++++++++++++++++++++ libxfs/xfs_parent.h | 6 ++++++ libxfs/xfs_trans_space.h | 2 -- 5 files changed, 39 insertions(+), 3 deletions(-) diff --git a/libxfs/xfs_attr.c b/libxfs/xfs_attr.c index 04cafc5f447b..0cb76f8f37b7 100644 --- a/libxfs/xfs_attr.c +++ b/libxfs/xfs_attr.c @@ -921,7 +921,7 @@ xfs_attr_defer_add( } /* Sets an attribute for an inode as a deferred operation */ -static int +int xfs_attr_defer_replace( struct xfs_da_args *args) { diff --git a/libxfs/xfs_attr.h b/libxfs/xfs_attr.h index 033005542b9e..985761264d1f 100644 --- a/libxfs/xfs_attr.h +++ b/libxfs/xfs_attr.h @@ -546,6 +546,7 @@ int xfs_attr_get_ilocked(struct xfs_da_args *args); int xfs_attr_get(struct xfs_da_args *args); int xfs_attr_defer_add(struct xfs_da_args *args); int xfs_attr_defer_remove(struct xfs_da_args *args); +int xfs_attr_defer_replace(struct xfs_da_args *args); int xfs_attr_set(struct xfs_da_args *args); int xfs_attr_set_iter(struct xfs_attr_intent *attr); int xfs_attr_remove_iter(struct xfs_attr_intent *attr); diff --git a/libxfs/xfs_parent.c b/libxfs/xfs_parent.c index 4da2e1b1a1d2..f9513cde3b01 100644 --- a/libxfs/xfs_parent.c +++ b/libxfs/xfs_parent.c @@ -143,6 +143,37 @@ xfs_parent_defer_remove( return xfs_attr_defer_remove(args); } + +int +xfs_parent_defer_replace( + struct xfs_trans *tp, + struct xfs_parent_defer *new_parent, + struct xfs_inode *old_dp, + xfs_dir2_dataptr_t old_diroffset, + struct xfs_name *parent_name, + struct xfs_inode *new_dp, + xfs_dir2_dataptr_t new_diroffset, + struct xfs_inode *child) +{ + struct xfs_da_args *args = &new_parent->args; + + xfs_init_parent_name_rec(&new_parent->old_rec, old_dp, old_diroffset); + xfs_init_parent_name_rec(&new_parent->rec, new_dp, new_diroffset); + new_parent->args.name = (const uint8_t *)&new_parent->old_rec; + new_parent->args.namelen = sizeof(struct xfs_parent_name_rec); + new_parent->args.new_name = (const uint8_t *)&new_parent->rec; + new_parent->args.new_namelen = sizeof(struct xfs_parent_name_rec); + args->trans = tp; + args->dp = child; + + ASSERT(parent_name != NULL); + new_parent->args.value = (void *)parent_name->name; + new_parent->args.valuelen = parent_name->len; + + args->hashval = xfs_da_hashname(args->name, args->namelen); + return xfs_attr_defer_replace(args); +} + void xfs_parent_cancel( xfs_mount_t *mp, diff --git a/libxfs/xfs_parent.h b/libxfs/xfs_parent.h index 1c506532c624..9021241ad65b 100644 --- a/libxfs/xfs_parent.h +++ b/libxfs/xfs_parent.h @@ -12,6 +12,7 @@ */ struct xfs_parent_defer { struct xfs_parent_name_rec rec; + struct xfs_parent_name_rec old_rec; struct xfs_da_args args; }; @@ -27,6 +28,11 @@ int xfs_parent_init(xfs_mount_t *mp, struct xfs_parent_defer **parentp); int xfs_parent_defer_add(struct xfs_trans *tp, struct xfs_parent_defer *parent, struct xfs_inode *dp, struct xfs_name *parent_name, xfs_dir2_dataptr_t diroffset, struct xfs_inode *child); +int xfs_parent_defer_replace(struct xfs_trans *tp, + struct xfs_parent_defer *new_parent, struct xfs_inode *old_dp, + xfs_dir2_dataptr_t old_diroffset, struct xfs_name *parent_name, + struct xfs_inode *new_ip, xfs_dir2_dataptr_t new_diroffset, + struct xfs_inode *child); int xfs_parent_defer_remove(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_parent_defer *parent, xfs_dir2_dataptr_t diroffset, diff --git a/libxfs/xfs_trans_space.h b/libxfs/xfs_trans_space.h index 25a55650baf4..ab2a07b70e3e 100644 --- a/libxfs/xfs_trans_space.h +++ b/libxfs/xfs_trans_space.h @@ -93,8 +93,6 @@ XFS_IALLOC_SPACE_RES(mp) #define XFS_REMOVE_SPACE_RES(mp) \ XFS_DIRREMOVE_SPACE_RES(mp) -#define XFS_RENAME_SPACE_RES(mp,nl) \ - (XFS_DIRREMOVE_SPACE_RES(mp) + XFS_DIRENTER_SPACE_RES(mp,nl)) #define XFS_IFREE_SPACE_RES(mp) \ (xfs_has_finobt(mp) ? M_IGEO(mp)->inobt_maxlevels : 0) -- 2.25.1