@@ -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);
@@ -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
@@ -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 */
@@ -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