]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
xfs: refactor releasing finished intents during log recovery
authorDarrick J. Wong <darrick.wong@oracle.com>
Fri, 1 May 2020 23:00:54 +0000 (16:00 -0700)
committerDarrick J. Wong <darrick.wong@oracle.com>
Fri, 8 May 2020 15:50:00 +0000 (08:50 -0700)
Replace the open-coded AIL item walking with a proper helper when we're
trying to release an intent item that has been finished.  We add a new
->iop_match method to decide if an intent item matches a supplied ID.

Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Chandan Babu R <chandanrlinux@gmail.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
fs/xfs/libxfs/xfs_log_recover.h
fs/xfs/xfs_bmap_item.c
fs/xfs/xfs_extfree_item.c
fs/xfs/xfs_log_recover.c
fs/xfs/xfs_refcount_item.c
fs/xfs/xfs_rmap_item.c
fs/xfs/xfs_trans.h

index 91fe954a796cf8ac49c31735911044007ce81e68..929366d58c3566c9a840db5ae9ba62aa3ecdbeef 100644 (file)
@@ -125,4 +125,7 @@ bool xlog_is_buffer_cancelled(struct xlog *log, xfs_daddr_t blkno, uint len);
 bool xlog_put_buffer_cancelled(struct xlog *log, xfs_daddr_t blkno, uint len);
 void xlog_recover_iodone(struct xfs_buf *bp);
 
+void xlog_recover_release_intent(struct xlog *log, unsigned short intent_type,
+               uint64_t intent_id);
+
 #endif /* __XFS_LOG_RECOVER_H__ */
index b08015caed32476935dd9f1819aeb5d99bb8469e..b3996f361b87c5cd8c733eaee324f4de1c5c0d95 100644 (file)
@@ -578,12 +578,21 @@ xfs_bui_item_recover(
        return error;
 }
 
+STATIC bool
+xfs_bui_item_match(
+       struct xfs_log_item     *lip,
+       uint64_t                intent_id)
+{
+       return BUI_ITEM(lip)->bui_format.bui_id == intent_id;
+}
+
 static const struct xfs_item_ops xfs_bui_item_ops = {
        .iop_size       = xfs_bui_item_size,
        .iop_format     = xfs_bui_item_format,
        .iop_unpin      = xfs_bui_item_unpin,
        .iop_release    = xfs_bui_item_release,
        .iop_recover    = xfs_bui_item_recover,
+       .iop_match      = xfs_bui_item_match,
 };
 
 /*
@@ -675,45 +684,14 @@ xlog_recover_bud_commit_pass2(
        xfs_lsn_t                       lsn)
 {
        struct xfs_bud_log_format       *bud_formatp;
-       struct xfs_bui_log_item         *buip = NULL;
-       struct xfs_log_item             *lip;
-       uint64_t                        bui_id;
-       struct xfs_ail_cursor           cur;
-       struct xfs_ail                  *ailp = log->l_ailp;
 
        bud_formatp = item->ri_buf[0].i_addr;
        if (item->ri_buf[0].i_len != sizeof(struct xfs_bud_log_format)) {
                XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp);
                return -EFSCORRUPTED;
        }
-       bui_id = bud_formatp->bud_bui_id;
-
-       /*
-        * Search for the BUI with the id in the BUD format structure in the
-        * AIL.
-        */
-       spin_lock(&ailp->ail_lock);
-       lip = xfs_trans_ail_cursor_first(ailp, &cur, 0);
-       while (lip != NULL) {
-               if (lip->li_type == XFS_LI_BUI) {
-                       buip = (struct xfs_bui_log_item *)lip;
-                       if (buip->bui_format.bui_id == bui_id) {
-                               /*
-                                * Drop the BUD reference to the BUI. This
-                                * removes the BUI from the AIL and frees it.
-                                */
-                               spin_unlock(&ailp->ail_lock);
-                               xfs_bui_release(buip);
-                               spin_lock(&ailp->ail_lock);
-                               break;
-                       }
-               }
-               lip = xfs_trans_ail_cursor_next(ailp, &cur);
-       }
-
-       xfs_trans_ail_cursor_done(&cur);
-       spin_unlock(&ailp->ail_lock);
 
+       xlog_recover_release_intent(log, XFS_LI_BUI, bud_formatp->bud_bui_id);
        return 0;
 }
 
index 307f71bdd398390e8387e9f6898edce28f33045c..3855e30109bfceec13f329535e0f7b0bc85ffcc2 100644 (file)
@@ -665,12 +665,21 @@ xfs_efi_item_recover(
        return error;
 }
 
+STATIC bool
+xfs_efi_item_match(
+       struct xfs_log_item     *lip,
+       uint64_t                intent_id)
+{
+       return EFI_ITEM(lip)->efi_format.efi_id == intent_id;
+}
+
 static const struct xfs_item_ops xfs_efi_item_ops = {
        .iop_size       = xfs_efi_item_size,
        .iop_format     = xfs_efi_item_format,
        .iop_unpin      = xfs_efi_item_unpin,
        .iop_release    = xfs_efi_item_release,
        .iop_recover    = xfs_efi_item_recover,
+       .iop_match      = xfs_efi_item_match,
 };
 
 /*
@@ -733,46 +742,15 @@ xlog_recover_efd_commit_pass2(
        struct xlog_recover_item        *item,
        xfs_lsn_t                       lsn)
 {
-       struct xfs_ail_cursor           cur;
        struct xfs_efd_log_format       *efd_formatp;
-       struct xfs_efi_log_item         *efip = NULL;
-       struct xfs_log_item             *lip;
-       struct xfs_ail                  *ailp = log->l_ailp;
-       uint64_t                        efi_id;
 
        efd_formatp = item->ri_buf[0].i_addr;
        ASSERT((item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_32_t) +
                ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_32_t)))) ||
               (item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_64_t) +
                ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_64_t)))));
-       efi_id = efd_formatp->efd_efi_id;
-
-       /*
-        * Search for the EFI with the id in the EFD format structure in the
-        * AIL.
-        */
-       spin_lock(&ailp->ail_lock);
-       lip = xfs_trans_ail_cursor_first(ailp, &cur, 0);
-       while (lip != NULL) {
-               if (lip->li_type == XFS_LI_EFI) {
-                       efip = (struct xfs_efi_log_item *)lip;
-                       if (efip->efi_format.efi_id == efi_id) {
-                               /*
-                                * Drop the EFD reference to the EFI. This
-                                * removes the EFI from the AIL and frees it.
-                                */
-                               spin_unlock(&ailp->ail_lock);
-                               xfs_efi_release(efip);
-                               spin_lock(&ailp->ail_lock);
-                               break;
-                       }
-               }
-               lip = xfs_trans_ail_cursor_next(ailp, &cur);
-       }
-
-       xfs_trans_ail_cursor_done(&cur);
-       spin_unlock(&ailp->ail_lock);
 
+       xlog_recover_release_intent(log, XFS_LI_EFI, efd_formatp->efd_efi_id);
        return 0;
 }
 
index e21cb9c33faa7f3b02483938c0a3392ee8feaa52..8a397566b7bb73c193eac7b0d399b068265deb8b 100644 (file)
@@ -1779,6 +1779,38 @@ xlog_clear_stale_blocks(
        return 0;
 }
 
+/*
+ * Release the recovered intent item in the AIL that matches the given intent
+ * type and intent id.
+ */
+void
+xlog_recover_release_intent(
+       struct xlog             *log,
+       unsigned short          intent_type,
+       uint64_t                intent_id)
+{
+       struct xfs_ail_cursor   cur;
+       struct xfs_log_item     *lip;
+       struct xfs_ail          *ailp = log->l_ailp;
+
+       spin_lock(&ailp->ail_lock);
+       for (lip = xfs_trans_ail_cursor_first(ailp, &cur, 0); lip != NULL;
+            lip = xfs_trans_ail_cursor_next(ailp, &cur)) {
+               if (lip->li_type != intent_type)
+                       continue;
+               if (!lip->li_ops->iop_match(lip, intent_id))
+                       continue;
+
+               spin_unlock(&ailp->ail_lock);
+               lip->li_ops->iop_release(lip);
+               spin_lock(&ailp->ail_lock);
+               break;
+       }
+
+       xfs_trans_ail_cursor_done(&cur);
+       spin_unlock(&ailp->ail_lock);
+}
+
 /******************************************************************************
  *
  *             Log recover routines
@@ -2583,7 +2615,8 @@ xlog_finish_defer_ops(
 /* Is this log item a deferred action intent? */
 static inline bool xlog_item_is_intent(struct xfs_log_item *lip)
 {
-       return lip->li_ops->iop_recover != NULL;
+       return lip->li_ops->iop_recover != NULL &&
+              lip->li_ops->iop_match != NULL;
 }
 
 /*
index 4eee8add4cd58471aa481bc58c8aeb250c995c9b..c03836e1a6d7c4fdfa1f83cd116ef58b86f587a8 100644 (file)
@@ -591,12 +591,21 @@ xfs_cui_item_recover(
        return error;
 }
 
+STATIC bool
+xfs_cui_item_match(
+       struct xfs_log_item     *lip,
+       uint64_t                intent_id)
+{
+       return CUI_ITEM(lip)->cui_format.cui_id == intent_id;
+}
+
 static const struct xfs_item_ops xfs_cui_item_ops = {
        .iop_size       = xfs_cui_item_size,
        .iop_format     = xfs_cui_item_format,
        .iop_unpin      = xfs_cui_item_unpin,
        .iop_release    = xfs_cui_item_release,
        .iop_recover    = xfs_cui_item_recover,
+       .iop_match      = xfs_cui_item_match,
 };
 
 /*
@@ -684,45 +693,14 @@ xlog_recover_cud_commit_pass2(
        xfs_lsn_t                       lsn)
 {
        struct xfs_cud_log_format       *cud_formatp;
-       struct xfs_cui_log_item         *cuip = NULL;
-       struct xfs_log_item             *lip;
-       uint64_t                        cui_id;
-       struct xfs_ail_cursor           cur;
-       struct xfs_ail                  *ailp = log->l_ailp;
 
        cud_formatp = item->ri_buf[0].i_addr;
        if (item->ri_buf[0].i_len != sizeof(struct xfs_cud_log_format)) {
                XFS_ERROR_REPORT(__func__, XFS_ERRLEVEL_LOW, log->l_mp);
                return -EFSCORRUPTED;
        }
-       cui_id = cud_formatp->cud_cui_id;
-
-       /*
-        * Search for the CUI with the id in the CUD format structure in the
-        * AIL.
-        */
-       spin_lock(&ailp->ail_lock);
-       lip = xfs_trans_ail_cursor_first(ailp, &cur, 0);
-       while (lip != NULL) {
-               if (lip->li_type == XFS_LI_CUI) {
-                       cuip = (struct xfs_cui_log_item *)lip;
-                       if (cuip->cui_format.cui_id == cui_id) {
-                               /*
-                                * Drop the CUD reference to the CUI. This
-                                * removes the CUI from the AIL and frees it.
-                                */
-                               spin_unlock(&ailp->ail_lock);
-                               xfs_cui_release(cuip);
-                               spin_lock(&ailp->ail_lock);
-                               break;
-                       }
-               }
-               lip = xfs_trans_ail_cursor_next(ailp, &cur);
-       }
-
-       xfs_trans_ail_cursor_done(&cur);
-       spin_unlock(&ailp->ail_lock);
 
+       xlog_recover_release_intent(log, XFS_LI_CUI, cud_formatp->cud_cui_id);
        return 0;
 }
 
index 1b7c7e3db8725be890a013cd559d39bb3eeaa9e8..31d35de518d1ff70a28843f2225814cc30b2ced7 100644 (file)
@@ -606,12 +606,21 @@ xfs_rui_item_recover(
        return error;
 }
 
+STATIC bool
+xfs_rui_item_match(
+       struct xfs_log_item     *lip,
+       uint64_t                intent_id)
+{
+       return RUI_ITEM(lip)->rui_format.rui_id == intent_id;
+}
+
 static const struct xfs_item_ops xfs_rui_item_ops = {
        .iop_size       = xfs_rui_item_size,
        .iop_format     = xfs_rui_item_format,
        .iop_unpin      = xfs_rui_item_unpin,
        .iop_release    = xfs_rui_item_release,
        .iop_recover    = xfs_rui_item_recover,
+       .iop_match      = xfs_rui_item_match,
 };
 
 /*
@@ -675,42 +684,11 @@ xlog_recover_rud_commit_pass2(
        xfs_lsn_t                       lsn)
 {
        struct xfs_rud_log_format       *rud_formatp;
-       struct xfs_rui_log_item         *ruip = NULL;
-       struct xfs_log_item             *lip;
-       uint64_t                        rui_id;
-       struct xfs_ail_cursor           cur;
-       struct xfs_ail                  *ailp = log->l_ailp;
 
        rud_formatp = item->ri_buf[0].i_addr;
        ASSERT(item->ri_buf[0].i_len == sizeof(struct xfs_rud_log_format));
-       rui_id = rud_formatp->rud_rui_id;
-
-       /*
-        * Search for the RUI with the id in the RUD format structure in the
-        * AIL.
-        */
-       spin_lock(&ailp->ail_lock);
-       lip = xfs_trans_ail_cursor_first(ailp, &cur, 0);
-       while (lip != NULL) {
-               if (lip->li_type == XFS_LI_RUI) {
-                       ruip = (struct xfs_rui_log_item *)lip;
-                       if (ruip->rui_format.rui_id == rui_id) {
-                               /*
-                                * Drop the RUD reference to the RUI. This
-                                * removes the RUI from the AIL and frees it.
-                                */
-                               spin_unlock(&ailp->ail_lock);
-                               xfs_rui_release(ruip);
-                               spin_lock(&ailp->ail_lock);
-                               break;
-                       }
-               }
-               lip = xfs_trans_ail_cursor_next(ailp, &cur);
-       }
-
-       xfs_trans_ail_cursor_done(&cur);
-       spin_unlock(&ailp->ail_lock);
 
+       xlog_recover_release_intent(log, XFS_LI_RUI, rud_formatp->rud_rui_id);
        return 0;
 }
 
index 3f6a79108991b824b6de5e35c1d2c6822901b410..3e8808bb07c5971519c10d59352774f8bcd0de55 100644 (file)
@@ -78,6 +78,7 @@ struct xfs_item_ops {
        xfs_lsn_t (*iop_committed)(struct xfs_log_item *, xfs_lsn_t);
        void (*iop_error)(struct xfs_log_item *, xfs_buf_t *);
        int (*iop_recover)(struct xfs_log_item *lip, struct xfs_trans *tp);
+       bool (*iop_match)(struct xfs_log_item *item, uint64_t id);
 };
 
 /*