aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_log_recover.c
diff options
context:
space:
mode:
authorDavid Chinner <david@fromorbit.com>2008-10-30 02:38:39 -0400
committerLachlan McIlroy <lachlan@sgi.com>2008-10-30 02:38:39 -0400
commit27d8d5fe0ef9daeaafbdd32b14b32a2211930062 (patch)
treee170fd577c1f6e58bee1cabb5cad75ced643c3ac /fs/xfs/xfs_log_recover.c
parent82fa9012458d867936d7bf130e6e14bdebc6873c (diff)
[XFS] Use a cursor for AIL traversal.
To replace the current generation number ensuring sanity of the AIL traversal, replace it with an external cursor that is linked to the AIL. Basically, we store the next item in the cursor whenever we want to drop the AIL lock to do something to the current item. When we regain the lock. the current item may already be free, so we can't reference it, but the next item in the traversal is already held in the cursor. When we move or delete an object, we search all the active cursors and if there is an item match we clear the cursor(s) that point to the object. This forces the traversal to restart transparently. We don't invalidate the cursor on insert because the cursor still points to a valid item. If the intem is inserted between the current item and the cursor it does not matter; the traversal is considered to be past the insertion point so it will be picked up in the next traversal. Hence traversal restarts pretty much disappear altogether with this method of traversal, which should substantially reduce the overhead of pushing on a busy AIL. Version 2 o add restart logic o comment cursor interface o minor cleanups SGI-PV: 988143 SGI-Modid: xfs-linux-melb:xfs-kern:32347a Signed-off-by: David Chinner <david@fromorbit.com> Signed-off-by: Lachlan McIlroy <lachlan@sgi.com> Signed-off-by: Christoph Hellwig <hch@infradead.org>
Diffstat (limited to 'fs/xfs/xfs_log_recover.c')
-rw-r--r--fs/xfs/xfs_log_recover.c61
1 files changed, 21 insertions, 40 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 199c8ea36474..37ba4899f3e6 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -54,10 +54,8 @@ STATIC void xlog_recover_insert_item_backq(xlog_recover_item_t **q,
54 xlog_recover_item_t *item); 54 xlog_recover_item_t *item);
55#if defined(DEBUG) 55#if defined(DEBUG)
56STATIC void xlog_recover_check_summary(xlog_t *); 56STATIC void xlog_recover_check_summary(xlog_t *);
57STATIC void xlog_recover_check_ail(xfs_mount_t *, xfs_log_item_t *, int);
58#else 57#else
59#define xlog_recover_check_summary(log) 58#define xlog_recover_check_summary(log)
60#define xlog_recover_check_ail(mp, lip, gen)
61#endif 59#endif
62 60
63 61
@@ -2710,8 +2708,8 @@ xlog_recover_do_efd_trans(
2710 xfs_efd_log_format_t *efd_formatp; 2708 xfs_efd_log_format_t *efd_formatp;
2711 xfs_efi_log_item_t *efip = NULL; 2709 xfs_efi_log_item_t *efip = NULL;
2712 xfs_log_item_t *lip; 2710 xfs_log_item_t *lip;
2713 int gen;
2714 __uint64_t efi_id; 2711 __uint64_t efi_id;
2712 struct xfs_ail_cursor cur;
2715 2713
2716 if (pass == XLOG_RECOVER_PASS1) { 2714 if (pass == XLOG_RECOVER_PASS1) {
2717 return; 2715 return;
@@ -2730,7 +2728,8 @@ xlog_recover_do_efd_trans(
2730 */ 2728 */
2731 mp = log->l_mp; 2729 mp = log->l_mp;
2732 spin_lock(&mp->m_ail_lock); 2730 spin_lock(&mp->m_ail_lock);
2733 lip = xfs_trans_first_ail(mp, &gen); 2731 xfs_trans_ail_cursor_init(mp->m_ail, &cur);
2732 lip = xfs_trans_first_ail(mp, &cur);
2734 while (lip != NULL) { 2733 while (lip != NULL) {
2735 if (lip->li_type == XFS_LI_EFI) { 2734 if (lip->li_type == XFS_LI_EFI) {
2736 efip = (xfs_efi_log_item_t *)lip; 2735 efip = (xfs_efi_log_item_t *)lip;
@@ -2741,11 +2740,13 @@ xlog_recover_do_efd_trans(
2741 */ 2740 */
2742 xfs_trans_delete_ail(mp, lip); 2741 xfs_trans_delete_ail(mp, lip);
2743 xfs_efi_item_free(efip); 2742 xfs_efi_item_free(efip);
2744 return; 2743 spin_lock(&mp->m_ail_lock);
2744 break;
2745 } 2745 }
2746 } 2746 }
2747 lip = xfs_trans_next_ail(mp, lip, &gen, NULL); 2747 lip = xfs_trans_next_ail(mp, &cur);
2748 } 2748 }
2749 xfs_trans_ail_cursor_done(mp->m_ail, &cur);
2749 spin_unlock(&mp->m_ail_lock); 2750 spin_unlock(&mp->m_ail_lock);
2750} 2751}
2751 2752
@@ -3030,33 +3031,6 @@ abort_error:
3030} 3031}
3031 3032
3032/* 3033/*
3033 * Verify that once we've encountered something other than an EFI
3034 * in the AIL that there are no more EFIs in the AIL.
3035 */
3036#if defined(DEBUG)
3037STATIC void
3038xlog_recover_check_ail(
3039 xfs_mount_t *mp,
3040 xfs_log_item_t *lip,
3041 int gen)
3042{
3043 int orig_gen = gen;
3044
3045 do {
3046 ASSERT(lip->li_type != XFS_LI_EFI);
3047 lip = xfs_trans_next_ail(mp, lip, &gen, NULL);
3048 /*
3049 * The check will be bogus if we restart from the
3050 * beginning of the AIL, so ASSERT that we don't.
3051 * We never should since we're holding the AIL lock
3052 * the entire time.
3053 */
3054 ASSERT(gen == orig_gen);
3055 } while (lip != NULL);
3056}
3057#endif /* DEBUG */
3058
3059/*
3060 * When this is called, all of the EFIs which did not have 3034 * When this is called, all of the EFIs which did not have
3061 * corresponding EFDs should be in the AIL. What we do now 3035 * corresponding EFDs should be in the AIL. What we do now
3062 * is free the extents associated with each one. 3036 * is free the extents associated with each one.
@@ -3080,20 +3054,25 @@ xlog_recover_process_efis(
3080{ 3054{
3081 xfs_log_item_t *lip; 3055 xfs_log_item_t *lip;
3082 xfs_efi_log_item_t *efip; 3056 xfs_efi_log_item_t *efip;
3083 int gen;
3084 xfs_mount_t *mp; 3057 xfs_mount_t *mp;
3085 int error = 0; 3058 int error = 0;
3059 struct xfs_ail_cursor cur;
3086 3060
3087 mp = log->l_mp; 3061 mp = log->l_mp;
3088 spin_lock(&mp->m_ail_lock); 3062 spin_lock(&mp->m_ail_lock);
3089 3063
3090 lip = xfs_trans_first_ail(mp, &gen); 3064 xfs_trans_ail_cursor_init(mp->m_ail, &cur);
3065 lip = xfs_trans_first_ail(mp, &cur);
3091 while (lip != NULL) { 3066 while (lip != NULL) {
3092 /* 3067 /*
3093 * We're done when we see something other than an EFI. 3068 * We're done when we see something other than an EFI.
3069 * There should be no EFIs left in the AIL now.
3094 */ 3070 */
3095 if (lip->li_type != XFS_LI_EFI) { 3071 if (lip->li_type != XFS_LI_EFI) {
3096 xlog_recover_check_ail(mp, lip, gen); 3072#ifdef DEBUG
3073 for (; lip; lip = xfs_trans_next_ail(mp, &cur))
3074 ASSERT(lip->li_type != XFS_LI_EFI);
3075#endif
3097 break; 3076 break;
3098 } 3077 }
3099 3078
@@ -3102,17 +3081,19 @@ xlog_recover_process_efis(
3102 */ 3081 */
3103 efip = (xfs_efi_log_item_t *)lip; 3082 efip = (xfs_efi_log_item_t *)lip;
3104 if (efip->efi_flags & XFS_EFI_RECOVERED) { 3083 if (efip->efi_flags & XFS_EFI_RECOVERED) {
3105 lip = xfs_trans_next_ail(mp, lip, &gen, NULL); 3084 lip = xfs_trans_next_ail(mp, &cur);
3106 continue; 3085 continue;
3107 } 3086 }
3108 3087
3109 spin_unlock(&mp->m_ail_lock); 3088 spin_unlock(&mp->m_ail_lock);
3110 error = xlog_recover_process_efi(mp, efip); 3089 error = xlog_recover_process_efi(mp, efip);
3111 if (error)
3112 return error;
3113 spin_lock(&mp->m_ail_lock); 3090 spin_lock(&mp->m_ail_lock);
3114 lip = xfs_trans_next_ail(mp, lip, &gen, NULL); 3091 if (error)
3092 goto out;
3093 lip = xfs_trans_next_ail(mp, &cur);
3115 } 3094 }
3095out:
3096 xfs_trans_ail_cursor_done(mp->m_ail, &cur);
3116 spin_unlock(&mp->m_ail_lock); 3097 spin_unlock(&mp->m_ail_lock);
3117 return error; 3098 return error;
3118} 3099}