[XFS] Propagate xfs_trans_reserve() errors.
authorDavid Chinner <dgc@sgi.com>
Thu, 10 Apr 2008 02:21:11 +0000 (12:21 +1000)
committerLachlan McIlroy <lachlan@redback.melbourne.sgi.com>
Fri, 18 Apr 2008 01:58:08 +0000 (11:58 +1000)
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 <dgc@sgi.com>
Signed-off-by: Niv Sardi <xaiki@sgi.com>
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
fs/xfs/xfs_log_recover.c

index c37521467fdc94926dad7e470253b7f9d0311f11..957b8caddf1ee56db8720ee6b479d50f2ca66f81 100644 (file)
@@ -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