xfs: use ->t_dfops for recovery of [b|c]ui log items
authorBrian Foster <bfoster@redhat.com>
Thu, 12 Jul 2018 05:26:09 +0000 (22:26 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Thu, 12 Jul 2018 05:26:09 +0000 (22:26 -0700)
Log recovery passes down a central dfops structure to recovery
handlers for bui and cui log items. Each of these handlers allocates
and commits a transaction and defers any remaining operations to be
completed by the main recovery sequence.

Since dfops outlives the transaction in this context, set and clear
->t_dfops appropriately such that the *_finish_item() paths and
below (i.e., xfs_bmapi*()) can expect to find the dfops in the
transaction without it being committed with the dfops attached. This
is required because transaction commit expects that an associated
dfops is finished and in this context the dfops may be populated at
commit time.

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
fs/xfs/xfs_bmap_item.c
fs/xfs/xfs_refcount_item.c

index 956ebd583e27d8911ba979896cf92a401bb64162..478bfc7988612f337c9451a4bac0179152f68910 100644 (file)
@@ -441,6 +441,7 @@ xfs_bui_recover(
                        XFS_EXTENTADD_SPACE_RES(mp, XFS_DATA_FORK), 0, 0, &tp);
        if (error)
                return error;
+       tp->t_dfops = dfops;
        budp = xfs_trans_get_bud(tp, buip);
 
        /* Grab the inode. */
@@ -487,6 +488,12 @@ xfs_bui_recover(
        }
 
        set_bit(XFS_BUI_RECOVERED, &buip->bui_flags);
+       /*
+        * Recovery finishes all deferred ops once intent processing is
+        * complete. Reset the trans reference because commit expects a finished
+        * dfops or none at all.
+        */
+       tp->t_dfops = NULL;
        error = xfs_trans_commit(tp);
        xfs_iunlock(ip, XFS_ILOCK_EXCL);
        IRELE(ip);
@@ -494,6 +501,7 @@ xfs_bui_recover(
        return error;
 
 err_inode:
+       tp->t_dfops = NULL;
        xfs_trans_cancel(tp);
        if (ip) {
                xfs_iunlock(ip, XFS_ILOCK_EXCL);
index 472a73e9d331b0e044179b98e92c0c226139777c..2064c689bc72038182176f28688ebfaa20ab043b 100644 (file)
@@ -452,6 +452,7 @@ xfs_cui_recover(
                        mp->m_refc_maxlevels * 2, 0, XFS_TRANS_RESERVE, &tp);
        if (error)
                return error;
+       tp->t_dfops = dfops;
        cudp = xfs_trans_get_cud(tp, cuip);
 
        for (i = 0; i < cuip->cui_format.cui_nextents; i++) {
@@ -514,11 +515,18 @@ xfs_cui_recover(
 
        xfs_refcount_finish_one_cleanup(tp, rcur, error);
        set_bit(XFS_CUI_RECOVERED, &cuip->cui_flags);
+       /*
+        * Recovery finishes all deferred ops once intent processing is
+        * complete. Reset the trans reference because commit expects a finished
+        * dfops or none at all.
+        */
+       tp->t_dfops = NULL;
        error = xfs_trans_commit(tp);
        return error;
 
 abort_error:
        xfs_refcount_finish_one_cleanup(tp, rcur, error);
+       tp->t_dfops = NULL;
        xfs_trans_cancel(tp);
        return error;
 }