Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xfs: track the iunlink list pointer in the xfs_inode

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>

authored by

Dave Chinner and committed by
Dave Chinner
4fcc94d6 a4454cd6

+10 -18
+2 -1
fs/xfs/libxfs/xfs_inode_buf.c
··· 229 229 ip->i_nblocks = be64_to_cpu(from->di_nblocks); 230 230 ip->i_extsize = be32_to_cpu(from->di_extsize); 231 231 ip->i_forkoff = from->di_forkoff; 232 - ip->i_diflags = be16_to_cpu(from->di_flags); 232 + ip->i_diflags = be16_to_cpu(from->di_flags); 233 + ip->i_next_unlinked = be32_to_cpu(from->di_next_unlinked); 233 234 234 235 if (from->di_dmevmask || from->di_dmstate) 235 236 xfs_iflags_set(ip, XFS_IPRESERVE_DM_FIELDS);
+4 -1
fs/xfs/xfs_inode.c
··· 2084 2084 2085 2085 /* Make sure the old pointer isn't garbage. */ 2086 2086 old_value = be32_to_cpu(dip->di_next_unlinked); 2087 - if (!xfs_verify_agino_or_null(pag, old_value)) { 2087 + if (old_value != ip->i_next_unlinked || 2088 + !xfs_verify_agino_or_null(pag, old_value)) { 2088 2089 xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, dip, 2089 2090 sizeof(*dip), __this_address); 2090 2091 error = -EFSCORRUPTED; ··· 2154 2153 if (error) 2155 2154 return error; 2156 2155 ASSERT(old_agino == NULLAGINO); 2156 + ip->i_next_unlinked = next_agino; 2157 2157 2158 2158 /* 2159 2159 * agino has been unlinked, add a backref from the next inode ··· 2356 2354 error = xfs_iunlink_update_inode(tp, ip, pag, NULLAGINO, &next_agino); 2357 2355 if (error) 2358 2356 return error; 2357 + ip->i_next_unlinked = NULLAGINO; 2359 2358 2360 2359 /* 2361 2360 * If there was a backref pointing from the next inode back to this
+3
fs/xfs/xfs_inode.h
··· 68 68 uint64_t i_diflags2; /* XFS_DIFLAG2_... */ 69 69 struct timespec64 i_crtime; /* time created */ 70 70 71 + /* unlinked list pointers */ 72 + xfs_agino_t i_next_unlinked; 73 + 71 74 /* VFS inode */ 72 75 struct inode i_vnode; /* embedded VFS inode */ 73 76
+1 -16
fs/xfs/xfs_log_recover.c
··· 2673 2673 xfs_agino_t agino, 2674 2674 int bucket) 2675 2675 { 2676 - struct xfs_buf *ibp; 2677 - struct xfs_dinode *dip; 2678 2676 struct xfs_inode *ip; 2679 2677 xfs_ino_t ino; 2680 2678 int error; ··· 2682 2684 if (error) 2683 2685 goto fail; 2684 2686 2685 - /* 2686 - * Get the on disk inode to find the next inode in the bucket. 2687 - */ 2688 - error = xfs_imap_to_bp(pag->pag_mount, NULL, &ip->i_imap, &ibp); 2689 - if (error) 2690 - goto fail_iput; 2691 - dip = xfs_buf_offset(ibp, ip->i_imap.im_boffset); 2692 - 2693 2687 xfs_iflags_clear(ip, XFS_IRECOVERY); 2694 2688 ASSERT(VFS_I(ip)->i_nlink == 0); 2695 2689 ASSERT(VFS_I(ip)->i_mode != 0); 2696 2690 2697 - /* setup for the next pass */ 2698 - agino = be32_to_cpu(dip->di_next_unlinked); 2699 - xfs_buf_relse(ibp); 2700 - 2691 + agino = ip->i_next_unlinked; 2701 2692 xfs_irele(ip); 2702 2693 return agino; 2703 2694 2704 - fail_iput: 2705 - xfs_irele(ip); 2706 2695 fail: 2707 2696 /* 2708 2697 * We can't read in the inode this bucket points to, or this inode