xfs: remove parent pointers in unlink
authorAllison Henderson <allison.henderson@oracle.com>
Mon, 22 Apr 2024 16:47:49 +0000 (09:47 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 23 Apr 2024 14:46:59 +0000 (07:46 -0700)
This patch removes the parent pointer attribute during unlink

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Allison Henderson <allison.henderson@oracle.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
[djwong: adjust to new ondisk format, minor rebase fixes]
Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/libxfs/xfs_parent.c
fs/xfs/libxfs/xfs_parent.h
fs/xfs/libxfs/xfs_trans_space.c
fs/xfs/libxfs/xfs_trans_space.h
fs/xfs/xfs_inode.c

index 65616cfc1a2bfa01084c22342e1960322340c631..6142e68f2338c7c3a6275532c22be71a684b069e 100644 (file)
@@ -205,3 +205,25 @@ xfs_parent_addname(
        xfs_attr_defer_add(&ppargs->args, XFS_ATTR_DEFER_SET);
        return 0;
 }
+
+/* Remove a parent pointer to reflect a dirent removal. */
+int
+xfs_parent_removename(
+       struct xfs_trans        *tp,
+       struct xfs_parent_args  *ppargs,
+       struct xfs_inode        *dp,
+       const struct xfs_name   *parent_name,
+       struct xfs_inode        *child)
+{
+       int                     error;
+
+       error = xfs_parent_iread_extents(tp, child);
+       if (error)
+               return error;
+
+       xfs_inode_to_parent_rec(&ppargs->rec, dp);
+       xfs_parent_da_args_init(&ppargs->args, tp, &ppargs->rec, child,
+                       child->i_ino, parent_name);
+       xfs_attr_defer_add(&ppargs->args, XFS_ATTR_DEFER_REMOVE);
+       return 0;
+}
index 6de24e3ef318ca5614732ea913d3b7a2d6b1b73c..4a7fd48c226a4345d959ef80e9ce7a1c7c45aa73 100644 (file)
@@ -81,5 +81,8 @@ xfs_parent_finish(
 int xfs_parent_addname(struct xfs_trans *tp, struct xfs_parent_args *ppargs,
                struct xfs_inode *dp, const struct xfs_name *parent_name,
                struct xfs_inode *child);
+int xfs_parent_removename(struct xfs_trans *tp, struct xfs_parent_args *ppargs,
+               struct xfs_inode *dp, const struct xfs_name *parent_name,
+               struct xfs_inode *child);
 
 #endif /* __XFS_PARENT_H__ */
index c8adda82debe08eed957c682e9cb1ddd18c36672..df729e4f1a4c97a5caf203310db395c7c5834c99 100644 (file)
@@ -81,3 +81,16 @@ xfs_symlink_space_res(
 
        return ret;
 }
+
+unsigned int
+xfs_remove_space_res(
+       struct xfs_mount        *mp,
+       unsigned int            namelen)
+{
+       unsigned int            ret = XFS_DIRREMOVE_SPACE_RES(mp);
+
+       if (xfs_has_parent(mp))
+               ret += xfs_parent_calc_space_res(mp, namelen);
+
+       return ret;
+}
index 354ad1d6e18d6c584d927eb0ae1edf35434cf677..a4490813c56f132183159680686c9bb106f94836 100644 (file)
@@ -91,8 +91,6 @@
         XFS_DQUOT_CLUSTER_SIZE_FSB)
 #define        XFS_QM_QINOCREATE_SPACE_RES(mp) \
        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)                \
@@ -106,5 +104,6 @@ unsigned int xfs_mkdir_space_res(struct xfs_mount *mp, unsigned int namelen);
 unsigned int xfs_link_space_res(struct xfs_mount *mp, unsigned int namelen);
 unsigned int xfs_symlink_space_res(struct xfs_mount *mp, unsigned int namelen,
                unsigned int fsblocks);
+unsigned int xfs_remove_space_res(struct xfs_mount *mp, unsigned int namelen);
 
 #endif /* __XFS_TRANS_SPACE_H__ */
index 61a390f5e2ae69040db7a39e4210dc457f20d839..c4a1c2dd5261d539f0afdc1a5160f9e00fb57a20 100644 (file)
@@ -2721,16 +2721,17 @@ xfs_iunpin_wait(
  */
 int
 xfs_remove(
-       xfs_inode_t             *dp,
+       struct xfs_inode        *dp,
        struct xfs_name         *name,
-       xfs_inode_t             *ip)
+       struct xfs_inode        *ip)
 {
-       xfs_mount_t             *mp = dp->i_mount;
-       xfs_trans_t             *tp = NULL;
+       struct xfs_mount        *mp = dp->i_mount;
+       struct xfs_trans        *tp = NULL;
        int                     is_dir = S_ISDIR(VFS_I(ip)->i_mode);
        int                     dontcare;
        int                     error = 0;
        uint                    resblks;
+       struct xfs_parent_args  *ppargs;
 
        trace_xfs_remove(dp, name);
 
@@ -2747,6 +2748,10 @@ xfs_remove(
        if (error)
                goto std_return;
 
+       error = xfs_parent_start(mp, &ppargs);
+       if (error)
+               goto std_return;
+
        /*
         * We try to get the real space reservation first, allowing for
         * directory btree deletion(s) implying possible bmap insert(s).  If we
@@ -2758,12 +2763,12 @@ xfs_remove(
         * the directory code can handle a reservationless update and we don't
         * want to prevent a user from trying to free space by deleting things.
         */
-       resblks = XFS_REMOVE_SPACE_RES(mp);
+       resblks = xfs_remove_space_res(mp, name->len);
        error = xfs_trans_alloc_dir(dp, &M_RES(mp)->tr_remove, ip, &resblks,
                        &tp, &dontcare);
        if (error) {
                ASSERT(error != -ENOSPC);
-               goto std_return;
+               goto out_parent;
        }
 
        /*
@@ -2823,6 +2828,13 @@ xfs_remove(
                goto out_trans_cancel;
        }
 
+       /* Remove parent pointer. */
+       if (ppargs) {
+               error = xfs_parent_removename(tp, ppargs, dp, name, ip);
+               if (error)
+                       goto out_trans_cancel;
+       }
+
        /*
         * Drop the link from dp to ip, and if ip was a directory, remove the
         * '.' and '..' references since we freed the directory.
@@ -2846,6 +2858,7 @@ xfs_remove(
 
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
        xfs_iunlock(dp, XFS_ILOCK_EXCL);
+       xfs_parent_finish(mp, ppargs);
        return 0;
 
  out_trans_cancel:
@@ -2853,6 +2866,8 @@ xfs_remove(
  out_unlock:
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
        xfs_iunlock(dp, XFS_ILOCK_EXCL);
+ out_parent:
+       xfs_parent_finish(mp, ppargs);
  std_return:
        return error;
 }