xfs: track the iunlink list pointer in the xfs_inode
authorDave Chinner <dchinner@redhat.com>
Thu, 14 Jul 2022 01:38:54 +0000 (11:38 +1000)
committerDave Chinner <david@fromorbit.com>
Thu, 14 Jul 2022 01:38:54 +0000 (11:38 +1000)
Having direct access to the i_next_unlinked pointer in unlinked
inodes greatly simplifies the processing of inodes on the unlinked
list. We no longer need to look up the inode buffer just to find
next inode in the list if the xfs_inode is in memory. These
improvements will be realised over upcoming patches as other
dependencies on the inode buffer for unlinked list processing are
removed.

Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Darrick J. Wong <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/libxfs/xfs_inode_buf.c
fs/xfs/xfs_inode.c
fs/xfs/xfs_inode.h
fs/xfs/xfs_log_recover.c

index 3a12bd3c7c97d46329a1ea4f4b345b39b83068b1..806f209defed5dc2d9244fdb5e24c092ecacfeb3 100644 (file)
@@ -229,7 +229,8 @@ xfs_inode_from_disk(
        ip->i_nblocks = be64_to_cpu(from->di_nblocks);
        ip->i_extsize = be32_to_cpu(from->di_extsize);
        ip->i_forkoff = from->di_forkoff;
-       ip->i_diflags   = be16_to_cpu(from->di_flags);
+       ip->i_diflags = be16_to_cpu(from->di_flags);
+       ip->i_next_unlinked = be32_to_cpu(from->di_next_unlinked);
 
        if (from->di_dmevmask || from->di_dmstate)
                xfs_iflags_set(ip, XFS_IPRESERVE_DM_FIELDS);
index 69bca88fc8ed79fcc85bc1553f2931b4c4e6233b..4055fb4aa9689525ed996e4fb2fe1083adc0445a 100644 (file)
@@ -2084,7 +2084,8 @@ xfs_iunlink_update_inode(
 
        /* Make sure the old pointer isn't garbage. */
        old_value = be32_to_cpu(dip->di_next_unlinked);
-       if (!xfs_verify_agino_or_null(pag, old_value)) {
+       if (old_value != ip->i_next_unlinked ||
+           !xfs_verify_agino_or_null(pag, old_value)) {
                xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, dip,
                                sizeof(*dip), __this_address);
                error = -EFSCORRUPTED;
@@ -2153,6 +2154,7 @@ xfs_iunlink_insert_inode(
                if (error)
                        return error;
                ASSERT(old_agino == NULLAGINO);
+               ip->i_next_unlinked = next_agino;
 
                /*
                 * agino has been unlinked, add a backref from the next inode
@@ -2354,6 +2356,7 @@ xfs_iunlink_remove_inode(
        error = xfs_iunlink_update_inode(tp, ip, pag, NULLAGINO, &next_agino);
        if (error)
                return error;
+       ip->i_next_unlinked = NULLAGINO;
 
        /*
         * If there was a backref pointing from the next inode back to this
index 7be6f8e705ab4cd5201d1fa2001943ccff773cec..8e2a33c6cbe2c66871c320bd150b1cef5ea8691a 100644 (file)
@@ -68,6 +68,9 @@ typedef struct xfs_inode {
        uint64_t                i_diflags2;     /* XFS_DIFLAG2_... */
        struct timespec64       i_crtime;       /* time created */
 
+       /* unlinked list pointers */
+       xfs_agino_t             i_next_unlinked;
+
        /* VFS inode */
        struct inode            i_vnode;        /* embedded VFS inode */
 
index bc687459951b36a5744b1904b798ce145cdb0628..d76e54cbb400c108c658fc7d46de388d93c95331 100644 (file)
@@ -2673,8 +2673,6 @@ xlog_recover_process_one_iunlink(
        xfs_agino_t                     agino,
        int                             bucket)
 {
-       struct xfs_buf                  *ibp;
-       struct xfs_dinode               *dip;
        struct xfs_inode                *ip;
        xfs_ino_t                       ino;
        int                             error;
@@ -2684,27 +2682,14 @@ xlog_recover_process_one_iunlink(
        if (error)
                goto fail;
 
-       /*
-        * Get the on disk inode to find the next inode in the bucket.
-        */
-       error = xfs_imap_to_bp(pag->pag_mount, NULL, &ip->i_imap, &ibp);
-       if (error)
-               goto fail_iput;
-       dip = xfs_buf_offset(ibp, ip->i_imap.im_boffset);
-
        xfs_iflags_clear(ip, XFS_IRECOVERY);
        ASSERT(VFS_I(ip)->i_nlink == 0);
        ASSERT(VFS_I(ip)->i_mode != 0);
 
-       /* setup for the next pass */
-       agino = be32_to_cpu(dip->di_next_unlinked);
-       xfs_buf_relse(ibp);
-
+       agino = ip->i_next_unlinked;
        xfs_irele(ip);
        return agino;
 
- fail_iput:
-       xfs_irele(ip);
  fail:
        /*
         * We can't read in the inode this bucket points to, or this inode