From 3c1e2bbe5bcdcd435510a05eb121fa74b848e24f Mon Sep 17 00:00:00 2001 From: David Chinner Date: Thu, 10 Apr 2008 12:21:11 +1000 Subject: [PATCH] [XFS] Propagate xfs_trans_reserve() errors. xfs_trans_reserve() reports errors that should not be ignored. For example, a shutdown filesystem will report errors through xfs_trans_reserve() to prevent further changes from being attempted on a damaged filesystem. Catch and propagate all error conditions from xfs_trans_reserve(). SGI-PV: 980084 SGI-Modid: xfs-linux-melb:xfs-kern:30794a Signed-off-by: David Chinner Signed-off-by: Niv Sardi Signed-off-by: Lachlan McIlroy --- fs/xfs/xfs_log_recover.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index c37521467fdc..957b8caddf1e 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c @@ -2965,7 +2965,7 @@ xlog_recover_process_data( * Process an extent free intent item that was recovered from * the log. We need to free the extents that it describes. */ -STATIC void +STATIC int xlog_recover_process_efi( xfs_mount_t *mp, xfs_efi_log_item_t *efip) @@ -2973,6 +2973,7 @@ xlog_recover_process_efi( xfs_efd_log_item_t *efdp; xfs_trans_t *tp; int i; + int error = 0; xfs_extent_t *extp; xfs_fsblock_t startblock_fsb; @@ -2996,12 +2997,16 @@ xlog_recover_process_efi( * free the memory associated with it. */ xfs_efi_release(efip, efip->efi_format.efi_nextents); - return; + return XFS_ERROR(EIO); } } tp = xfs_trans_alloc(mp, 0); - xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0, 0, 0); + error = xfs_trans_reserve(tp, 0, XFS_ITRUNCATE_LOG_RES(mp), 0, 0, 0); + if (error) { + xfs_trans_cancel(tp, XFS_TRANS_ABORT); + return error; + } efdp = xfs_trans_get_efd(tp, efip, efip->efi_format.efi_nextents); for (i = 0; i < efip->efi_format.efi_nextents; i++) { @@ -3013,6 +3018,7 @@ xlog_recover_process_efi( efip->efi_flags |= XFS_EFI_RECOVERED; xfs_trans_commit(tp, 0); + return error; } /* @@ -3060,7 +3066,7 @@ xlog_recover_check_ail( * everything already in the AIL, we stop processing as soon as * we see something other than an EFI in the AIL. */ -STATIC void +STATIC int xlog_recover_process_efis( xlog_t *log) { @@ -3068,6 +3074,7 @@ xlog_recover_process_efis( xfs_efi_log_item_t *efip; int gen; xfs_mount_t *mp; + int error = 0; mp = log->l_mp; spin_lock(&mp->m_ail_lock); @@ -3092,11 +3099,14 @@ xlog_recover_process_efis( } spin_unlock(&mp->m_ail_lock); - xlog_recover_process_efi(mp, efip); + error = xlog_recover_process_efi(mp, efip); + if (error) + return error; spin_lock(&mp->m_ail_lock); lip = xfs_trans_next_ail(mp, lip, &gen, NULL); } spin_unlock(&mp->m_ail_lock); + return error; } /* @@ -3116,9 +3126,9 @@ xlog_recover_clear_agi_bucket( int error; tp = xfs_trans_alloc(mp, XFS_TRANS_CLEAR_AGI_BUCKET); - xfs_trans_reserve(tp, 0, XFS_CLEAR_AGI_BUCKET_LOG_RES(mp), 0, 0, 0); - - error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, + error = xfs_trans_reserve(tp, 0, XFS_CLEAR_AGI_BUCKET_LOG_RES(mp), 0, 0, 0); + if (!error) + error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, XFS_AG_DADDR(mp, agno, XFS_AGI_DADDR(mp)), XFS_FSS_TO_BB(mp, 1), 0, &agibp); if (error) { @@ -3919,7 +3929,14 @@ xlog_recover_finish( * rather than accepting new requests. */ if (log->l_flags & XLOG_RECOVERY_NEEDED) { - xlog_recover_process_efis(log); + int error; + error = xlog_recover_process_efis(log); + if (error) { + cmn_err(CE_ALERT, + "Failed to recover EFIs on filesystem: %s", + log->l_mp->m_fsname); + return error; + } /* * Sync the log to get all the EFIs out of the AIL. * This isn't absolutely necessary, but it helps in