aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_log_recover.c
diff options
context:
space:
mode:
authorBrian Foster <bfoster@redhat.com>2015-08-18 19:52:21 -0400
committerDave Chinner <david@fromorbit.com>2015-08-18 19:52:21 -0400
commite32a1d1fbf6eb2bdc24aa0502e827ff4d2234604 (patch)
tree86f8a2fc5ac53c1db1a499d0ffe7213a09f9fd49 /fs/xfs/xfs_log_recover.c
parent6bc43af3d5f507254b8de2058ea51f6ec998ae52 (diff)
xfs: use EFI refcount consistently in log recovery
The EFI is initialized with a reference count of 2. One for the EFI to ensure the item makes it to the AIL and one for the subsequently created EFD to release the EFI once the EFD is committed. Log recovery uses the EFI in a similar manner, but implements a hack to remove both references in one call once the EFD is handled. Update log recovery to use EFI reference counting in a manner consistent with the log. When an EFI is encountered during recovery, an EFI item is allocated and inserted to the AIL directly. Since the EFI reference is typically dropped when the EFI is unpinned and this is analogous with AIL insertion, drop the EFI reference at this point. When a corresponding EFD is encountered in the log, this indicates that the extents were freed, no processing is required and the EFI can be dropped. Update xlog_recover_efd_pass2() to simply drop the EFD reference at this point rather than open code the AIL removal and EFI free. Remaining EFIs (i.e., with no corresponding EFD) are processed in xlog_recover_finish(). An EFD transaction is allocated and the extents are freed, which transfers ownership of the EFI reference to the EFD item in the log. Signed-off-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Dave Chinner <dchinner@redhat.com> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs/xfs_log_recover.c')
-rw-r--r--fs/xfs/xfs_log_recover.c43
1 files changed, 23 insertions, 20 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 434ba2cdf6e8..05c0cc83f9a4 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -2928,16 +2928,16 @@ xlog_recover_efi_pass2(
2928 struct xlog_recover_item *item, 2928 struct xlog_recover_item *item,
2929 xfs_lsn_t lsn) 2929 xfs_lsn_t lsn)
2930{ 2930{
2931 int error; 2931 int error;
2932 xfs_mount_t *mp = log->l_mp; 2932 struct xfs_mount *mp = log->l_mp;
2933 xfs_efi_log_item_t *efip; 2933 struct xfs_efi_log_item *efip;
2934 xfs_efi_log_format_t *efi_formatp; 2934 struct xfs_efi_log_format *efi_formatp;
2935 2935
2936 efi_formatp = item->ri_buf[0].i_addr; 2936 efi_formatp = item->ri_buf[0].i_addr;
2937 2937
2938 efip = xfs_efi_init(mp, efi_formatp->efi_nextents); 2938 efip = xfs_efi_init(mp, efi_formatp->efi_nextents);
2939 if ((error = xfs_efi_copy_format(&(item->ri_buf[0]), 2939 error = xfs_efi_copy_format(&item->ri_buf[0], &efip->efi_format);
2940 &(efip->efi_format)))) { 2940 if (error) {
2941 xfs_efi_item_free(efip); 2941 xfs_efi_item_free(efip);
2942 return error; 2942 return error;
2943 } 2943 }
@@ -2945,20 +2945,23 @@ xlog_recover_efi_pass2(
2945 2945
2946 spin_lock(&log->l_ailp->xa_lock); 2946 spin_lock(&log->l_ailp->xa_lock);
2947 /* 2947 /*
2948 * xfs_trans_ail_update() drops the AIL lock. 2948 * The EFI has two references. One for the EFD and one for EFI to ensure
2949 * it makes it into the AIL. Insert the EFI into the AIL directly and
2950 * drop the EFI reference. Note that xfs_trans_ail_update() drops the
2951 * AIL lock.
2949 */ 2952 */
2950 xfs_trans_ail_update(log->l_ailp, &efip->efi_item, lsn); 2953 xfs_trans_ail_update(log->l_ailp, &efip->efi_item, lsn);
2954 xfs_efi_release(efip);
2951 return 0; 2955 return 0;
2952} 2956}
2953 2957
2954 2958
2955/* 2959/*
2956 * This routine is called when an efd format structure is found in 2960 * This routine is called when an EFD format structure is found in a committed
2957 * a committed transaction in the log. It's purpose is to cancel 2961 * transaction in the log. Its purpose is to cancel the corresponding EFI if it
2958 * the corresponding efi if it was still in the log. To do this 2962 * was still in the log. To do this it searches the AIL for the EFI with an id
2959 * it searches the AIL for the efi with an id equal to that in the 2963 * equal to that in the EFD format structure. If we find it we drop the EFD
2960 * efd format structure. If we find it, we remove the efi from the 2964 * reference, which removes the EFI from the AIL and frees it.
2961 * AIL and free it.
2962 */ 2965 */
2963STATIC int 2966STATIC int
2964xlog_recover_efd_pass2( 2967xlog_recover_efd_pass2(
@@ -2980,8 +2983,8 @@ xlog_recover_efd_pass2(
2980 efi_id = efd_formatp->efd_efi_id; 2983 efi_id = efd_formatp->efd_efi_id;
2981 2984
2982 /* 2985 /*
2983 * Search for the efi with the id in the efd format structure 2986 * Search for the EFI with the id in the EFD format structure in the
2984 * in the AIL. 2987 * AIL.
2985 */ 2988 */
2986 spin_lock(&ailp->xa_lock); 2989 spin_lock(&ailp->xa_lock);
2987 lip = xfs_trans_ail_cursor_first(ailp, &cur, 0); 2990 lip = xfs_trans_ail_cursor_first(ailp, &cur, 0);
@@ -2990,18 +2993,18 @@ xlog_recover_efd_pass2(
2990 efip = (xfs_efi_log_item_t *)lip; 2993 efip = (xfs_efi_log_item_t *)lip;
2991 if (efip->efi_format.efi_id == efi_id) { 2994 if (efip->efi_format.efi_id == efi_id) {
2992 /* 2995 /*
2993 * xfs_trans_ail_delete() drops the 2996 * Drop the EFD reference to the EFI. This
2994 * AIL lock. 2997 * removes the EFI from the AIL and frees it.
2995 */ 2998 */
2996 xfs_trans_ail_delete(ailp, lip, 2999 spin_unlock(&ailp->xa_lock);
2997 SHUTDOWN_CORRUPT_INCORE); 3000 xfs_efi_release(efip);
2998 xfs_efi_item_free(efip);
2999 spin_lock(&ailp->xa_lock); 3001 spin_lock(&ailp->xa_lock);
3000 break; 3002 break;
3001 } 3003 }
3002 } 3004 }
3003 lip = xfs_trans_ail_cursor_next(ailp, &cur); 3005 lip = xfs_trans_ail_cursor_next(ailp, &cur);
3004 } 3006 }
3007
3005 xfs_trans_ail_cursor_done(&cur); 3008 xfs_trans_ail_cursor_done(&cur);
3006 spin_unlock(&ailp->xa_lock); 3009 spin_unlock(&ailp->xa_lock);
3007 3010